Factuarea APIDevelopers

Test mode & sandbox

Build your integration safely with fact_test_ keys — isolated sandbox data, AEAT, email and webhooks switched off, and what a test key can and cannot do on your account.

Every Factuarea API key belongs to one of two environments, told apart by its prefix:

PrefixEnvironmentOperates onExternal effects
fact_live_live (production)Your real companyReal: legal fiscal numbering, VeriFactu → AEAT, FACe submissions, emails to clients, outbound webhooks
fact_test_test (sandbox)An isolated sandbox companySwitched off (see below)

The prefix is the source of truth for the environment: a fact_test_ key always operates in test mode and a fact_live_ key always in live. No request parameter changes the environment — it is determined entirely by the key you authenticate with.

Always build and test your integration with a fact_test_ key first. Once your flow works end-to-end, switch the prefix to fact_live_ to go to production. The API surface is identical in both environments.

Getting a test key

Test keys are created from the developer dashboard exactly like live keys, selecting the Test environment (app.factuarea.com/settings/developers/api-keys). The generated secret looks like:

fact_test_<24 alphanumeric characters>

Example:

fact_test_3pXnR2VbY7TcA9eFmN5z8KqW

Same format and entropy as a live key (24 base62 characters), same scopes apart from those of the modules that test mode does not offer (for example webhooks:write), same rate-limit tier. The only difference is the prefix and what it points to. As with live keys, the secret is shown only once at creation — if you lose it you must rotate.

You can also issue one with a live key, with POST /v1/accounts/{account}/api-keys and environment set to test. A test key never issues keys: see the account axis.

Using a test key

Send it on every request just like a live key, via Authorization: Bearer or X-API-Key:

curl https://api.factuarea.com/v1/companies/{company}/contacts \
  -H "Authorization: Bearer fact_test_3pXnR2VbY7TcA9eFmN5z8KqW"

The same endpoints and operations available in live are available in test — nothing is removed or stubbed — with the exceptions that the account axis and the webhook endpoints describe.

Data isolation: the sandbox company

A fact_test_ key operates on a dedicated sandbox company — a technical "twin" of your real company, provisioned automatically the first time you use test mode, that inherits your real company's plan so feature-gating is faithful. Thanks to multi-tenant isolation by company:

  • Resources created with a fact_test_ key are not visible to a fact_live_ key, and vice versa.
  • Test fiscal numbering uses the sandbox's own series and never consumes or alters the correlative numbering of your production series.

This is structural isolation, not a filter: test and live data live in separate companies, so there is no way for them to mix.

What is switched off in test

When you operate with a fact_test_ key (sandbox environment), effects that reach the outside world are disabled so you can exercise your integration without real-world consequences:

EffectIn liveIn test
VeriFactuThe Alta record is created and transmitted to the AEAT.The Alta record is created locally, but never transmitted to the AEAT.
EmailDocument emails are delivered to real recipients.Document emails are not delivered to real recipients.
WebhooksSubscribed events are delivered to your external HTTP endpoints.Events are recorded with livemode: false (queryable via GET /v1/companies/{company}/events) but not delivered to your endpoints. An account endpoint of the test environment records each delivery and does not send it either: see account webhook endpoints in test.
FACe (FacturaE)Submissions are presented to the real FACe web service.The whole flow is simulated — no SOAP call leaves Factuarea and the registry number is synthetic (FACE-SANDBOX-*). See FACe invoicing.

Everything else behaves identically: validation, totals, document state machines, idempotency, pagination, rate limits and error envelopes are the same as in production.

Because webhooks are not delivered in test, you cannot exercise your webhook receiver against sandbox data. That includes test-event, which from the sandbox is recorded and never delivered. A test key cannot call the webhook endpoints of a tax ID at all: it cannot carry webhooks:write, and an operation that it carries anyway answers 403 module_not_available_in_sandbox. Exercise your receiver with a live key on a live endpoint instead. A test-event is signed and retried like a production delivery and carries "test": true, so it validates your signature check and your real handler. POST /v1/companies/{company}/webhook-endpoints/{id}/ping only confirms that your URL answers: it sends a bare { "type": "webhook.ping" } with no signature.

The account axis with a test key

A fact_test_ key belongs to your real account, so it reaches the account axis: GET /v1/me and the operations under /v1/accounts/{account}/…. The rule is short: it reads, and it does not write on a live account.

You do with a fact_test_ keyWhat you get
Read your account: team, invitations, keys, tax ID portfolio, tax ID transfers, usage, employee seats and provisioning usage200. The key reads your account as a production key does.
Read the webhook endpoints, the deliveries and the request logs of your account200, but only those of the test environment. A test key never reads the live ones.
Write on your live account: team, invitations, ownership, tax ID transfers, tax ID portfolio and employee seats403 live_credential_required, with nothing written. Use a fact_live_ key.
Create, edit, rotate, test, retry or delete an account webhook endpoint403, because a test key cannot carry webhooks:write. See account webhook endpoints in test.
Issue, re-scope, rotate or revoke API keys403 live_credential_required, with nothing written. A test key never issues a key, so it never issues a live one. To get a test key, issue it with a live key and environment set to test, or create it in the app.
Operate the test managed accounts that your account provisions: change their level or plan, end their managementAllowed, with no charge: see test managed accounts.

Test managed accounts

If you provision accounts for your clients, you can rehearse it with a test key. POST /v1/accounts with a fact_test_ key creates a test account: a managed account in the test environment, with a sandbox company as its tax ID and no real company behind it. It is not charged, it has no claim voucher (claim_token and claim_url are null) and nobody claims it, it does not count against max_managed_accounts, and nothing reaches VeriFactu or a real recipient. Only your fact_test_ keys and the app in Test mode reach it: a live key answers 404 account_not_found. A test account never becomes a live one, and its external_ref is unique across both environments: repeating it with a live key answers 409 managed_account_external_ref_in_other_environment.

Two things differ from what you may expect:

  • The bulk import. With a test key, the managed_account rows create or reconcile test accounts. The own_nif rows and the options row come out ERROR with code live_credential_required, create nothing and add 0 to the totals.
  • The data of its tax ID. A test key reaches only the sandbox company of your own account, so /v1/companies/{company}/… with the id of a tax ID of a test account answers 404 profile_not_found. To work with that data, switch the app to Test mode: your test accounts appear among your client accounts, and choosing one makes its sandbox company the active one.

Test managed accounts with fact_test_ walks through the whole path, from reading your account to reading the events of a test account.

Account webhook endpoints in test

An account webhook endpoint belongs to one environment, live or test, fixed when it is created and never changed. An endpoint of the test environment receives only the events of the test environment, and a live endpoint never receives them. It never makes an outgoing request: each delivery is recorded with its envelope and stays pending, with attempt set to 0. So "receiving" an event means reading it, with GET /v1/accounts/{account}/webhooks/{webhook}/deliveries.

A test key cannot create a test endpoint. The environment of an endpoint comes from the credential or the session that creates it, and an environment in the body is ignored. A fact_test_ key reads the endpoints and the deliveries of the test environment with webhooks:read, but it cannot create, edit, rotate, test, retry or delete an account endpoint. You create the test endpoint in the web app, with Test mode on, from Settings → Developers → Webhooks, choosing Account: test managed accounts shows the steps.

With the official SDKs

The TypeScript and PHP SDKs follow the same rule: the key prefix selects the environment — there is no flag. Build against a fact_test_ key, then swap the env var to fact_live_ to go to production. No code changes.

import { Factuarea } from "@factuarea/sdk";

const sandbox = new Factuarea({ apiKey: "fact_test_…" });
sandbox.environment; // "test"

const prod = new Factuarea({ apiKey: "fact_live_…" });
prod.environment;    // "live"

The SDK exposes the resolved environment on .environment, derived from the prefix — handy for guards and logging.

use Factuarea\Sdk\Custom\FactuareaClient;

$sandbox = FactuareaClient::create('fact_test_…'); // sandbox
$prod    = FactuareaClient::create('fact_live_…'); // production

Webhooks are still not delivered in test even via the SDK. To exercise your receiver's SDK verifier, send a test-event with a live key: it is signed like a production delivery. ping is not signed, so it cannot exercise the verifier.

Switching environment in the app

Beyond API keys, the Factuarea web app lets you toggle between live and test at any time from the top bar. Switching to test:

  • Re-issues your session without re-login, pointing it at the sandbox company (provisioning it if it doesn't exist yet). The previous token is invalidated.
  • Shows a persistent "Test mode" banner across the whole interface so the active context is always obvious.
  • Re-hydrates the client state so listings reflect sandbox data and never show cached production data.

Switching back to live re-issues the session against your real company. The sandbox is never shown as a real company in the company selector — it exists only to back the test environment.

Test mode is also where you create the test endpoints of your account webhooks, and where you work with the data of the tax IDs of your test managed accounts, which a test key does not reach.

From test to production

When your integration works against fact_test_:

  1. Create a fact_live_ key in the dashboard (same scopes you validated in test).
  2. Swap the key your client uses (environment variable / secret manager).
  3. No code changes are needed — the request shape is identical.

From that point, real effects (fiscal numbering, VeriFactu → AEAT, emails, webhooks) are active again.

Nothing you created in test moves to production. A test managed account is never promoted: provision the live ones with a fact_live_ key and a different external_ref. Create the live account webhook endpoints with a live key or in the app in live mode, because a test endpoint never receives live events.

Store environment and delivery

A store’s environment is separate from the environment selected by the API-key prefix. New stores default to test, with automatic invoicing and sending disabled. Store test events can be discarded as store_environment_test; the isolated sandbox also suppresses real email and public webhook delivery. Changing the store flag does not promote a test credential to live. See stores and the n8n trigger.

On this page

Need a hand?Contact support