FAQ
Quick answers to the questions that come up most when integrating the Factuarea public API — keys, test mode, money, dates, idempotency and rate limits.
Short answers to the questions that come up most when building against the Factuarea public API. Each one links to the guide that covers it in full.
Access & keys
How do I get access to the API?
The API is in private beta: write to info@factuarea.com from the email associated with your company, including your legal name, tax ID, use case and estimated invoice volume. We respond within ≤ 5 business days. See Request beta access.
Is this key live or test?
Read the prefix: fact_live_ operates on your real company
(production), fact_test_ on an isolated sandbox. The prefix is the
single source of truth — no request parameter changes the environment. See
Test mode & sandbox.
I lost my API key secret. Can I recover it?
No. The backend stores only a bcrypt hash of the secret, which is shown only once at creation. Rotate the key from the dashboard to issue a new secret and redeploy it. See Authentication › Rotation.
How do I rotate a key with zero downtime?
Rotate from the dashboard: the old and new secrets both stay valid for a
grace period, so you can roll out the new one without dropped
requests. Revoke a key only when you suspect a leak — that invalidates it
instantly (401 api_key_revoked). See
Authentication › Rotation and revocation.
Test mode
Is test data isolated from production?
Yes — structurally, not by a filter. A fact_test_ key operates on a
dedicated sandbox company, so resources created in test are never
visible to a fact_live_ key (and vice versa), and test fiscal numbering
never touches your production series. See
Test mode › Data isolation.
Why aren't my webhooks firing in test mode?
In test, external effects are switched off: VeriFactu → AEAT, FACe, emails and
webhook delivery are all neutralized. Events are still recorded with
livemode: false and are queryable via GET /v1/events, but they are
not delivered to your endpoints. Use
POST /v1/webhook_endpoints/{id}/ping to exercise your receiver. See
Test mode › What is switched off.
Documents
What's the difference between delete, annul and void an invoice?
DELETE /v1/invoices/{id} only works on drafts. Once an invoice is
issued it cannot be deleted: use POST /v1/invoices/{id}/annul (records a
documented reason, and creates the AEAT anulación record when VeriFactu
is enabled) or POST /v1/invoices/{id}/void (irreversible, records a
void_reason, rejected if the invoice has already been corrected). See
Migrate from Holded › Intentional differences.
Money & dates
How are monetary amounts represented?
In euros, with two decimal places, Stripe-style — the canonical form is
a decimal string like "1234.56". Parse money as a fixed decimal, never a
binary float, and let the API compute totals from raw line inputs. See
Amounts & dates › Money.
What format do dates use?
Calendar dates such as issued_on and due_on use YYYY-MM-DD (for
example 2026-05-15). Timestamps such as created and expires_at are
ISO 8601 in UTC with a Z suffix — e.g. 2026-05-15T10:23:18Z. See
Amounts & dates.
What timezone do quotas use?
The monthly rate-limit quota resets on day 1 at 00:00 Europe/Madrid, while timestamps are returned in UTC. See Amounts & dates › Timezone for quotas and Rate limits.
Idempotency & retries
What happens if I replay an Idempotency-Key?
Within the 24h TTL, the API returns the cached response (status,
headers and body) without re-running the handler, adding the
Idempotent-Replayed: true header. A cached 4xx is replayed too. Reusing
the key with a different body responds 409 idempotency_key_reused.
See Idempotency.
Does an idempotent replay count against my rate limit?
No. A key replayed within its TTL doesn't count against your quota. Different keys with the same payload each count, one by one. See Idempotency › What idempotency is NOT.
What's the maximum Idempotency-Key length?
Between 1 and 64 characters. Any opaque unique value works (UUID v7 recommended, but UUID v4, ULID or nanoid are fine). See Idempotency › Key format.
Rate limits & errors
How do I know my remaining quota?
Every response (including 429) carries X-RateLimit-Limit,
X-RateLimit-Remaining and X-RateLimit-Reset; a 429 adds Retry-After
with the seconds to wait. Limits depend on your key's tier. See
Rate limits.
How should I retry a failed request?
4xx (except 429) → don't retry, fix the request. 429 → honor
Retry-After. 5xx → exponential back-off with jitter, up to 5 attempts.
See Errors › Retry strategy.
Where do I report a problem with a specific request?
Grab the request_id from the error envelope (also in the X-Request-Id
header) and send it to support — it lets us correlate logs, metrics and
traces. See Support.
Retrieve an event
Retrieve a single event by its `id` (format `evt_<ulid>`, an opaque identifier). Useful for auditing and replaying webhook payloads. Returns `404 not_found` if the event does not exist or belongs to another company.
Support
How to reach the Factuarea API team, what to include when reporting an issue, beta status, the status page and the changelog.