Factuarea APIDevelopers

All error codes

Complete reference of every public API error code, grouped by bounded context, with its HTTP status and type.

This is the canonical reference of every error code the public API can return, grouped by the bounded context that emits it. Each code is stable across versions; the message is for display only. The total count and grouping are generated from the live catalog.

Account

CodeTypeHTTPDescription
account_not_foundnot_found_error404The account behind the key could not be resolved, which usually means the key no longer points at a live company.
api_key_already_revokedinvalid_request_error422The key was already revoked, and a revoked key admits no further operations: revocation is terminal.
api_key_not_foundnot_found_error404The identifier does not match any API key of the authenticated company.
sender_identity_not_verifiedinvalid_request_error422The sending company has not proven its identity yet, and without that it cannot write to external recipients from the shared sender domain. This is neither an exhausted quota nor a permission problem: the credential holds the scope, and waiting does not clear it.

Authentication

CodeTypeHTTPDescription
api_key_expiredauthentication_error401The key passed its expiry date.
api_key_revokedauthentication_error401The key was revoked, and a revoked key never authenticates again — revocation is the way to cut off a leaked credential.
invalid_api_keyauthentication_error401The key does not match any active key. It may be mistyped, truncated, or belong to a different environment — test keys and live keys are not interchangeable.
ip_not_allowedauthentication_error401The key restricts the addresses it accepts, and the request came from one outside that list.
missing_api_keyauthentication_error401The request carries no credentials: neither the Authorization header nor X-API-Key.
origin_not_allowedauthentication_error401The request comes from a browser origin that the key does not accept.
too_many_auth_failuresauthentication_error429Too many failed authentication attempts arrived from the same address, so it is temporarily locked out to stop credential guessing.

Authorization

CodeTypeHTTPDescription
addon_not_activeauthorization_error403The functionality belongs to an add-on that is not active for the company right now.
feature_not_available_in_planauthorization_error403The feature is not included in the company plan.
forbidden_actionauthorization_error403The action is blocked for this resource even though the scope is right: the resource belongs to a shared catalogue, or the change travels through a different endpoint.
insufficient_scopeauthorization_error403The key authenticates correctly but does not carry the scope this operation requires. Scopes are granted when the key is issued and are not widened at call time.
max_api_keys_exceededauthorization_error422The company reached the number of API keys its plan allows.
max_webhook_endpoints_exceededauthorization_error422The company reached the number of webhook endpoints its add-on tier allows.
module_not_available_in_sandboxauthorization_error403The resource belongs to a module vetoed in test mode. Sandbox never touches AEAT, banks or real billing, so those modules stay out on purpose.
portfolio_max_api_keys_exceededauthorization_error422The portfolio already holds the maximum number of ACTIVE credentials. The cap is counted over the managing company and its active children together, not per company, so onboarding another child to mint its credential will not let you create this one either.
scope_not_allowed_by_planauthorization_error422One of the requested scopes belongs to a module that the plan does not include, so the key would be born with a permission that could never be exercised.
scope_not_allowed_in_sandboxauthorization_error422A test key cannot be born with scopes of modules vetoed in sandbox.

Automations

CodeTypeHTTPDescription
automation_action_order_invalidinvalid_request_error422The position of a step inside the sequence is not a whole number, or it is negative. That position is what fixes the order in which the actions run.
automation_action_parameter_missinginvalid_request_error422A parameter the action declares as required did not arrive. It is rejected here, rather than filled in with a default inside the adapter, so that a dry run predicts the real execution.
automation_action_parameter_unknowninvalid_request_error422A parameter key does not belong to the schema of the action. Accepting it would store a setting no adapter reads, and you would believe it active until the rule fired and did something else.
automation_action_parameter_value_invalidinvalid_request_error422A parameter of the action carries a value outside the set its schema accepts.
automation_action_parameters_invalidinvalid_request_error422The parameters of an action do not hold as a set: a value is not serialisable, a key is not text, two mutually exclusive parameters arrived together, or a pair that requires one of the two arrived with neither.
automation_action_type_invalidinvalid_request_error422One of the steps declares an action type with no adapter behind it, so nothing would run at that position.
automation_chain_depth_exceededinvalid_request_error422One automation fired another until the chaining margin ran out, so the run stops before queueing any step. Waiting does not fix it: the same event would walk the same chain again.
automation_condition_combinator_invalidinvalid_request_error422A branch of the condition declares a logical combinator outside the accepted set, so the branch cannot be read as an "and" or as an "or".
automation_condition_depth_exceededinvalid_request_error422The condition nests more levels than the evaluator walks, so the rule cannot be evaluated end to end.
automation_condition_expression_invalidinvalid_request_error422The shape of the condition tree does not hold: a malformed node, an operator receiving the wrong kind of value, a field path that is not a dotted route, or a tree past the limit of depth or of nodes.
automation_condition_field_not_evaluableinvalid_request_error422The condition reads a field the trigger does not publish as evaluable. The allowlist never resolves an unknown path to a default value, because a field resolved in silence is the very hole the sandbox exists to close.
automation_condition_operator_invalidinvalid_request_error422A comparison of the condition names an operator outside the accepted set.
automation_condition_operator_not_applicableinvalid_request_error422The operator does not apply to the type of the field it compares: asking whether one piece of text is greater than another is not a comparison the evaluator can make.
automation_condition_operator_unsupportedinvalid_request_error422The evaluator has no implementation for that operator, so it stops instead of answering "false": a silent "false" would make "the condition does not match" indistinguishable from "it cannot be evaluated".
automation_condition_payload_field_missinginvalid_request_error422The key the condition reads is absent from the payload of the event, which is not the same as being present with a null value. Some events carry a reduced payload — a deletion, for instance, may only keep the identifier.
automation_condition_payload_type_mismatchinvalid_request_error422The value in the event contradicts the type the trigger declares for that field, and the evaluator does not convert types: a converted comparison would give a right answer by accident and hide that the payload changed shape.
automation_dry_run_event_type_mismatchinvalid_request_error422The dry run was asked with an event type other than the trigger of the rule being rehearsed, and a rule only ever receives events of its own trigger. The prediction would describe a delivery that is never going to happen.
automation_event_company_unresolvableinvalid_request_error422The event reached the engine without a company that could be resolved, and the engine stops rather than guessing one: writing a run under a substituted company would break the isolation between companies.
automation_event_payload_not_resolvableinvalid_request_error422The content of the event could not be recovered, so there is no payload to freeze into the run. It happens when the resource behind the event is no longer readable at the moment of delivery.
automation_monthly_budget_exhaustedpayment_required_error402The company used up the automation runs its plan includes for the current period, so the run stops before queueing any step. Unlike a rate limit, waiting a few seconds changes nothing: what ran out is the budget of the cycle.
automation_portfolio_scope_forbids_actioninvalid_request_error422One of the actions acts on the data of a single company, and under portfolio scope every run has a different managed company as its subject. Only actions that notify the managing company, or that touch no document at all, are admitted.
automation_portfolio_scope_not_availableauthorization_error403This company cannot create automations over a portfolio: either it has no accounting-practice module, or it is itself a company managed by another one, and the relationship is only one level deep.
automation_rate_limit_exceededrate_limit_error429The company went over the automation runs its plan admits inside the limiter window. The work is admissible; it simply arrived too fast.
automation_replay_not_allowedinvalid_request_error422The run exists and is yours, but relaunching it does not apply: it has not finished yet, it finished well and its effect already happened, its outcome would take exactly the same branch again, or no outcome was recorded for it.
automation_rule_actions_emptyinvalid_request_error422The rule declares no actions, so there would be nothing to run when its trigger fired.
automation_rule_actions_limit_exceededinvalid_request_error422The rule contains more than 50 actions. One triggering event would therefore fan out into too many steps, queued jobs, and possible external effects.
automation_rule_already_deletedinvalid_request_error422The rule had already been taken down. Removal is logical and does not succeed in silence the second time, so two different removals never get confused with one another.
automation_rule_company_mismatchinvalid_request_error422The rule that was about to be materialised does not belong to the company of the event, so the run is not created: freezing the snapshot of an event — client, amounts, tax id — onto rows of another company is never allowed.
automation_rule_name_invalidinvalid_request_error422The name is empty or longer than the limit. The name is what identifies the rule in listings and in the history of its runs.
automation_rule_not_foundnot_found_error404No automation rule with that identifier exists for the authenticated company. A rule that belongs to another company answers exactly the same way, so the response never reveals whether it exists elsewhere.
automation_rule_scope_immutableinvalid_request_error422The request tries to change the scope of an automation that already exists. Scope is fixed at creation because it decides whose events the rule observes, and changing it would reinterpret every run it has recorded so far.
automation_rule_scope_invalidinvalid_request_error422The scope you sent is not in the automation catalogue. There are only two: the company that creates the rule, and the portfolio of companies it manages.
automation_rule_status_transition_invalidinvalid_request_error422The rule cannot move from its current state to the one you asked for: activating, pausing and taking down each accept their own origin states.
automation_rule_uuid_invalidinvalid_request_error422The identifier is not a valid UUID v7. Automations address their resources by the id the API returns, never by an internal number.
automation_rule_version_not_foundnot_found_error404The rule exists, but it has no version with that number: every save publishes a new version and the numbering never reuses a value.
automation_rule_version_number_invalidinvalid_request_error422The version number is below 1. Versions are numbered from one upwards, in the order they were published.
automation_rule_version_snapshot_not_foundnot_found_error404The run points at a rule version whose frozen definition is not stored, so there is no definition to execute: a run always executes the version it started with, never the live rule.
automation_run_not_foundnot_found_error404No automation run with that identifier exists for the authenticated company. A run of another company answers exactly the same way, so the response never reveals whether it exists elsewhere.
automation_run_status_transition_invalidinvalid_request_error422The run cannot move from its current state to the one requested: the life cycle of a run only admits the transitions its state declares.
automation_run_step_not_foundnot_found_error404The run exists and belongs to you, but it has no step at that index. A run materialises every one of its steps when it starts, and the count never changes afterwards.
automation_run_uuid_invalidinvalid_request_error422The run identifier is not a valid UUID v7.
automation_step_index_invalidinvalid_request_error422A step index cannot be negative: no run addresses a step that way.
automation_step_status_transition_invalidinvalid_request_error422The step cannot move from its current state to the one requested. It is what stops a finished step from being claimed twice, and that guard is what makes a replay produce each effect only once.
automation_step_subject_company_mismatchinvalid_request_error422The item the action was about to act on does not belong to the company of the run, or its company could not be determined. Either way the step aborts before the adapter is invoked, so no effect is produced.
automation_subject_company_ownership_not_verifiedinvalid_request_error422While preparing the run it could not be proven that the company behind the event is still an active managed company of whoever created the automation. The link may have been archived, the company deactivated, or the run reached this point with mismatched data.
automation_trigger_not_foundnot_found_error404The trigger is not in the catalogue your company can see. A name that does not exist and a real trigger whose module your company has not been granted answer the same, so the response never confirms which of the two it is.
automation_trigger_payload_contract_unknowninvalid_request_error422The trigger publishes no contract of evaluable fields, so there is no catalogue against which to resolve a condition.
automation_trigger_type_invalidinvalid_request_error422The write carries a trigger that is not in the catalogue available to your company, so the rule would never receive an event.

Companies

CodeTypeHTTPDescription
company_inactiveauthorization_error403The profile named in X-Active-Profile is one of your managed companies, but it is deactivated and cannot be operated until it comes back.
gestoria_module_requiredauthorization_error403The master company holds a live plan, but one without the accounting-firm module, so it cannot create or operate managed companies.
gestoria_plan_requiredpayment_required_error402The accounting firm has no active paid subscription, so there is no subscription on which to charge the seat.
payment_method_requiredpayment_required_error402Adding a managed company charges a seat immediately, and the accounting firm operates in live mode with no payment method on file.
seat_charge_failedpayment_required_error402The immediate pro-rated charge for the seat was declined: the card was refused, it needs authentication, or the payment provider was unreachable. The company is not created if the seat is not paid.

Contacts

CodeTypeHTTPDescription
alternative_id_type_invalidinvalid_request_error422The alternative identifier type is outside the catalogue nif_iva, passport, country_id, residence_certificate, other_document, not_registered.
bank_account_usage_requiredinvalid_request_error422The bank account does not declare what it is for: neither collection nor payment, and it does not flag a default usage to infer it from. An account with no purpose cannot be used for collections or payments.
cannot_have_both_tax_id_and_alternative_idinvalid_request_error422The client sends tax_id and an alternative identifier at the same time. Fiscal identity is one: the alternative identifier exists precisely for parties without a Spanish tax id.
census_requires_tax_idinvalid_request_error422Census verification checks the pair name plus tax id against AEAT, and one of the two is missing.
client_has_documentsinvalid_request_error422The client is referenced by issued documents. Deleting it would leave invoices, quotes or delivery notes without the party they were issued to, and fiscal records must remain traceable.
client_import_too_largeinvalid_request_error422The CSV exceeds the row limit the synchronous import accepts, since the whole file is processed within the request.
client_not_foundnot_found_error404The identifier does not resolve to any client of the authenticated company.
client_requires_tax_identityinvalid_request_error422The client carries no fiscal identity: neither tax_id nor an alternative identifier, and an invoice cannot be issued to an unidentified party.
contact_not_foundnot_found_error404The identifier does not resolve to any business contact of the authenticated company.
direct_debit_requires_default_bank_accountinvalid_request_error422Direct debit was selected as the payment method, but the client has no default bank account to charge.
supplier_has_documentsinvalid_request_error422The supplier is referenced by registered purchase invoices, and deleting it would leave those expenses without the party that issued them.
supplier_not_foundnot_found_error404The identifier does not resolve to any supplier of the authenticated company.
tax_id_already_existsconflict_error409Another client of the company already holds that tax id, and the tax id identifies the party uniquely inside a company.

Delivery Notes

CodeTypeHTTPDescription
delivery_note_cannot_be_sentinvalid_request_error422The delivery note is already invoiced or cancelled: delivering it now would hand the customer a superseded document.
delivery_note_not_foundnot_found_error404The identifier does not resolve to any delivery note of the authenticated company.
delivery_note_section_not_editable_in_statusinvalid_request_error422The logistics section — carrier, vehicle, driver — is frozen because the delivery note is already delivered, invoiced or cancelled.
driver_tax_id_requires_nameinvalid_request_error422The driver tax id was sent without the driver name, and an identifier with no name identifies nobody on the delivery document.
signature_payload_too_largeinvalid_request_error422The signature image exceeds the accepted size for the field.

Employees

CodeTypeHTTPDescription
employee_seat_charge_failedpayment_required_error402The immediate pro-rated charge for the employee seat was declined: the card was refused, it needs authentication, or the payment provider was unreachable. The employee is not activated if the seat is not paid.
employee_seat_payment_method_requiredpayment_required_error402Adding or reactivating an employee charges a seat immediately, and the company operates in live mode with no payment method on file.

Events

CodeTypeHTTPDescription
event_not_foundnot_found_error404The identifier does not match any event of the authenticated company, or the event was purged by the 30-day retention policy.

Exports

CodeTypeHTTPDescription
export_budget_exceededrate_limit_error429The hourly budget of PACKAGING WORK for the company is exhausted. This is not a request limit: it counts packaged documents and generated artifacts against the disk and render pool shared by every tenant, so neither spreading the calls nor using another credential changes anything. The subcode says which of the two axes ran out — export_documents_budget (packaged content) or export_artifacts_budget (number of generated files).
export_byte_cap_exceededinvalid_request_error413The packaged download exceeds the BYTE cap of that artifact type. It counts weight, not documents, so a small batch of very heavy documents —illustrated template, attachments— reaches it too. The subcode says when it was rejected: before_writing, when the estimated weight already exceeded it and NOTHING was written, or while_writing, when the real weight exceeded it mid-packaging and the partial file was discarded.
export_document_cap_exceededinvalid_request_error413The packaged download asks for MORE DOCUMENTS than that artifact type allows. It is not a request limit nor a permissions problem: it is the size of what a single call asks for, and the very same cap rules the web application and the API, so splitting the work across surfaces does not dodge it.

Idempotency

CodeTypeHTTPDescription
idempotency_key_in_useidempotency_error409Another request with the same Idempotency-Key is still in flight, and the result is not known yet.
idempotency_key_invalidinvalid_request_error400The Idempotency-Key does not fit the accepted format: it must be 1 to 255 printable ASCII characters.
idempotency_key_requiredinvalid_request_error422The request arrived without an Idempotency-Key header, and this operation delivers an effect that cannot be taken back — an email sent, a file generated, a charge — so its transition window has already closed for this credential's environment.
idempotency_key_reusedidempotency_error409That Idempotency-Key was already used with a different payload. The key identifies one specific operation, so reusing it for another would make replay meaningless.

Integration

CodeTypeHTTPDescription
shopify_api_version_expiredapi_error500The Admin API version this connector speaks to the shop with is no longer supported. Shopify does not return an error when that happens: it serves the oldest stable version with a 200, so the breakage shows up as fields quietly missing from the response.
shopify_credentials_rejectedinvalid_request_error422The shop answered and rejected the access token, or there was none to use. In Shopify the token comes from authorising the app, and the merchant can revoke that authorisation from their admin at any time, so a token that worked yesterday may not work today without anyone changing a setting.
shopify_store_unreachableapi_error502The shop did not answer: the request timed out, the transport failed, Shopify returned an error of its own, or the Admin API query cost budget was exhausted. What is failing sits upstream, not in the credential.
store_already_connectedinvalid_request_error422That shop is already connected to your company under the same provider. The pair provider plus remote shop is unique per company, so connecting it twice would leave two stores ingesting the same orders and invoicing them twice.
store_external_id_mismatchinvalid_request_error422The remote identifier you are sending does not match any shop your company has authorised for that integration. With providers that sign their notifications using the application secret — Shopify — that identifier decides which company each sale is invoiced to, so only a shop that went through the authorisation flow is accepted.
store_not_foundnot_found_error404The identifier does not resolve to any connected store of the authenticated company. A store belonging to another company answers exactly the same way, so the response never reveals whether it exists elsewhere.
store_url_not_allowedinvalid_request_error422The base address of the shop is not an authorised outbound destination for your company. Reading orders back from the shop would open a connection to a host nobody approved.
woocommerce_credentials_rejectedinvalid_request_error422The shop answered and rejected the credential, or the credential could not be used at all: the key is missing, the secret is missing, or the base address is not https. Authentication travels in the header over HTTPS, so a shop published in clear text would hand over both pieces on the first hop, which is why it is rejected before anything leaves.
woocommerce_rest_route_missinginvalid_request_error422The shop answered, but its REST API is not published: WordPress replied that the route does not exist. The usual cause is permalinks left on the plain setting, so /wp-json/ is not served. The credential may be perfectly valid.
woocommerce_store_unreachableapi_error502The shop did not answer: the request timed out, the transport failed, or its hosting returned an error of its own. What is failing sits upstream, in the merchant's installation, not in the platform and not in the credential.

Invoices

CodeTypeHTTPDescription
corrective_invoice_inanulableinvalid_request_error422The invoice is itself a corrective, and correctives are never annulled: the correction chain has to stay auditable end to end.
export_limit_exceededinvalid_request_error422The filtered selection exceeds the 5,000-invoice cap of the export, so the file is refused up front instead of being silently truncated.
invalid_correction_natureinvalid_request_error422correction_nature only accepts S (substitution: the corrective carries the full corrected amounts) or I (by difference: it carries only the delta).
invalid_correction_reasoninvalid_request_error422The correction reason is outside the closed fiscal list (error_fundado, concurso, incobrable, error_importe, error_cliente, devolucion, descuento, otras), which maps to the AEAT codes R1 to R4.
invalid_invoice_idinvalid_request_error400The invoice reference received is not a valid identifier; it usually means an internal value slipped in where the API expects the public id.
invalid_invoice_numberinvalid_request_error422The invoice number does not follow the canonical format SERIES-YYYY-NNN, plus the -RECn suffix on correctives.
invalid_invoice_statusinvalid_request_error422The value sent as invoice status is outside the document lifecycle catalogue (draft, scheduled, sent, overdue, cancelled, annulled). paid is a valid value to read and to filter by, but not to write: register a payment instead.
invalid_invoice_uuidinvalid_request_error400The invoice identifier in the path or in the payload is not a valid UUID.
invalid_payment_methodinvalid_request_error422The payment method is outside the closed allowlist: bank_transfer, cash, credit_card, sepa_direct_debit, paypal, bizum, other.
invoice_already_annulledinvalid_request_error422The invoice was already annulled. Annulment is terminal and, with VeriFactu active, its annulment record has already reached AEAT.
invoice_already_paidinvalid_request_error422The invoice is already settled. paid is a terminal, accounting-closed state: the output VAT has been declared, or will be declared for the period.
invoice_already_sentinvalid_request_error422The invoice was already issued: it holds a definitive series number and, with VeriFactu active, its registration with AEAT. Issuing does not happen twice.
invoice_cannot_assign_numberinvalid_request_error422A definitive number was requested for an invoice that is not a draft, or that already carries one. Series numbering is monotonic and numbers are never reassigned.
invoice_cannot_be_sentinvalid_request_error422The invoice is voided or cancelled: it no longer represents a valid operation, so its PDF is not delivered to the recipient.
invoice_invalid_status_transitioninvalid_request_error422The target status is unreachable from the current one. The document lifecycle is directed: draft moves to scheduled or sent, sent to overdue or annulled, overdue to annulled, and cancelled and annulled are terminal. Being paid is not a step of that lifecycle: it is read from the payment ledger.
invoice_not_cancellable_in_current_stateinvalid_request_error422Cancelling withdraws a draft that is not yet fiscally binding, so it only applies while the invoice is draft.
invoice_not_correctable_in_current_stateinvalid_request_error422A corrective invoice can only be issued against an invoice that is already issued (sent or paid). A draft, a cancelled or an annulled invoice has nothing to correct.
invoice_not_deletable_in_current_stateinvalid_request_error422Only draft and cancelled invoices can be deleted. A numbered invoice never disappears: the correlative sequence must stay auditable.
invoice_not_editable_in_current_stateinvalid_request_error422Only a draft admits editing. Once issued, the invoice is immutable and its content is frozen along with its fiscal record.
invoice_not_eligible_for_actioninvalid_request_error422The requested action does not apply to this invoice: its type or its current state leaves it outside the scope of the operation.
invoice_not_foundnot_found_error404The identifier does not resolve to any invoice of the authenticated company. Invoices belonging to another company answer exactly the same way.
invoice_not_modifiable_in_current_stateinvalid_request_error422The field you are changing is frozen for the current state — for instance the tax regime of an annulled invoice.
invoice_not_paidinvalid_request_error422A payment receipt was requested for an invoice with no settled payment, so there is nothing to certify.
invoice_not_reschedulable_in_current_stateinvalid_request_error422Rescheduling moves the issuing date of an invoice that is waiting in scheduled, and this invoice is not waiting.
invoice_not_schedulable_in_current_stateinvalid_request_error422Only a draft can be scheduled: scheduling reserves a future issuing moment without consuming a series number yet.
invoice_not_unschedulable_in_current_stateinvalid_request_error422Unscheduling returns an invoice from scheduled to draft, so it only applies while it is still waiting to be issued.
invoice_not_unsendable_in_current_stateinvalid_request_error422Undoing the delivery mark only applies to a sent invoice: it clears sent_at and keeps the invoice issued.
invoice_requires_at_least_one_lineinvalid_request_error422The invoice carries no operation line, so it has no taxable base and cannot be issued. This happens both when you send no lines at all and when every line you send is a disbursement: a disbursement is an amount paid on the customer's behalf (art. 78.Tres.3 LIVA), not an operation of your own.
invoice_year_required_for_ambiguous_numberinvalid_request_error422That invoice number matches more than one invoice, so on its own it identifies none. It repeats for two independent reasons: the fiscal year (series recycle numbering every year) and the series (two series of your company each issue their own F-2026-001).
line_total_checksum_mismatchinvalid_request_error422The line_total you declared does not match the one Factuarea computes for that line (quantity × price − discount + VAT − withholding + surcharge) and the deviation is above the one-cent tolerance. The amount that gets invoiced and reported to the tax authority is always the one computed here, so the discrepancy means your system and the issued invoice would not reconcile.
line_type_invalidinvalid_request_error422The line type falls outside the closed NORMAL / SUPLIDO catalogue. An issued invoice only tells two natures apart: what you sell, which forms the taxable base and carries VAT, and a disbursement (suplido), money advanced in the name and on behalf of the customer, which is therefore left out of the base (art. 78.Tres.3 of the Spanish VAT Act).
no_invoices_in_periodinvalid_request_error422The quarterly operation found no invoices in the requested period, so there is nothing to package or send.
payment_method_invalidinvalid_request_error422Same closed allowlist as invalid_payment_method, reported when the value is rejected while reading the payment method field of the payload.
rectified_invoice_inanulableinvalid_request_error422This invoice already has a full corrective (correction_type: full), which returned its amount and its goods. Annulling it now would return both a second time. A partial corrective does not block: the invoice stays alive and annulling it is legitimate.
reminder_not_applicableinvalid_request_error422The payment reminder does not apply: the invoice is not sent or overdue, there is no recipient email, the public link is missing or disabled, or another reminder went out in the last 24 hours.
scheduled_for_in_pastinvalid_request_error422scheduled_for is not strictly in the future, so there is no waiting period to reserve.
simplified_invoice_cannot_be_substitutedinvalid_request_error422One invoice of the substitution list cannot be replaced: it is not simplified, it is cancelled or annulled, it belongs to another company, or it already has a substitute.
simplified_invoice_not_allowedinvalid_request_error422The operation is not eligible for a simplified invoice: it exceeds EUR 3,000, or it is an intra-EU supply, an export, a reverse-charge operation, or the customer needs a full invoice to deduct VAT.
simplified_limit_exceededinvalid_request_error422The lines would push the simplified invoice (F2) over the absolute legal cap of EUR 3,000 VAT included.
suplido_line_cannot_carry_taxesinvalid_request_error422The disbursement line carries charges of its own: a VAT rate, withholding, equivalence surcharge, discount, regime key, exemption cause or product/pack. A disbursement is not an operation of the issuer, so charging tax on it would mean paying tax on a supply you never made, and tying it to a product would move stock you never sold.
suplido_not_allowed_in_simplified_invoiceinvalid_request_error422The invoice is simplified (F2) and a simplified invoice does not identify the recipient. With no identified recipient there is nobody to evidence the payment on behalf of, so the amount cannot take disbursement treatment on this invoice type.
suplido_requires_source_invoice_referenceinvalid_request_error422The disbursement line does not carry source_invoice_reference, the number of the supporting document the third party issued in the customer's name. Without that document the payment is not evidenced as made on someone else's behalf, and the tax authority would treat it as the issuer's own taxable base, with VAT charged on it.

MCP

CodeTypeHTTPDescription
mcp_guardrail_violationinvalid_request_error422The call breaks a declared tax rule and was rejected LOCALLY, before anything ran: no document was created, modified or deleted. It is the only code in the catalogue that no API v1 route can emit — whoever receives it is talking over MCP. The subcode says which of the nine guardrails was broken, and the error data carries guardrail_uri (the resource that explains the rule) and rule_id (the specific rule, shaped BR-XXX-NNN).

Notifications

CodeTypeHTTPDescription
notification_not_foundnot_found_error404The identifier does not match any notification of the authenticated company, or the notification fell out of the retention window.

Payments

CodeTypeHTTPDescription
invalid_payment_dateinvalid_request_error422The payment date falls outside the accepted window: it cannot precede the invoice issue date, nor be in the future.
payment_already_reversedinvalid_request_error422The payment is already reverted, and its trail is not overwritten by a second reversal: the reason, instant and author of the first one are the accounting record of why the invoice stopped being paid.
payment_reversal_invalidinvalid_request_error422The reversal note is longer than the 500 characters allowed.
payment_reversal_reason_invalidinvalid_request_error422The reversal reason is outside the closed catalog: only a returned SEPA direct debit, a card dispute or chargeback, a misapplied payment, a dishonoured bill and a recording error are accepted.
payout_reconciliation_amount_mismatchinvalid_request_error422The confirmed amount does not match the net amount of the payout, so the reconciliation would close with a difference nobody accounts for.
receipt_not_availableinvalid_request_error422There is no receipt to issue because the document has no settled payment behind it.
stripe_payout_already_reconciledinvalid_request_error422The payout was already reconciled, and reconciliation is terminal: repeating it would double-count the bank entry.
stripe_payout_not_foundnot_found_error404The identifier does not resolve to any payout of the authenticated company.

Pricing

CodeTypeHTTPDescription
duplicate_price_list_nameinvalid_request_error422Another price list in the company already uses that name, which must be unique within the tenant.
inactive_price_listinvalid_request_error422The price list is inactive and may only be read to explain historical documents, not selected for a new operation.
invalid_price_list_iteminvalid_request_error422The price-list entry has an incompatible target, amount or unit, or duplicates the same product, variant and presentation within the list.
price_list_in_useinvalid_request_error422The price list is assigned to clients or drafts, and deleting it would leave those price references without their source.
price_list_not_foundnot_found_error404The identifier does not resolve to any price list of the authenticated company.

Products

CodeTypeHTTPDescription
pack_in_useinvalid_request_error422The pack is referenced by issued documents, so deleting it would break their composition.
pack_not_foundnot_found_error404The identifier does not resolve to any pack of the authenticated company.
pack_share_link_failedapi_error500The share link for the pack could not be produced. The pack itself is unaffected.
product_in_useinvalid_request_error422The product is referenced by issued documents or by other catalogue entries, and removing it would leave those references dangling.
product_not_foundnot_found_error404The identifier does not resolve to any product of the authenticated company.
sku_already_existsconflict_error409Another product of the company already uses that SKU, and the SKU identifies the item uniquely in the catalogue.

Proformas

CodeTypeHTTPDescription
invalid_expiry_dateinvalid_request_error422The expiry date is earlier than the issue date, or more than 365 days after it.
invalid_proforma_idinvalid_request_error400The pro forma reference received is not a valid identifier, usually because an internal value replaced the public id.
invalid_proforma_numberinvalid_request_error422The pro forma number does not follow the canonical numbering format of its series.
invalid_proforma_statusinvalid_request_error422The value sent as status is outside the catalogue draft, accepted, rejected, expired, invoiced, cancelled.
invalid_proforma_uuidinvalid_request_error400The pro forma identifier in the path or in the payload is not a valid UUID.
proforma_already_acceptedinvalid_request_error422The customer already accepted the pro forma, and acceptance is registered once.
proforma_already_rejectedinvalid_request_error422The pro forma is already marked as rejected.
proforma_cannot_be_acceptedinvalid_request_error422Acceptance does not apply from the current state: an invoiced, cancelled or expired pro forma no longer admits it.
proforma_cannot_be_rejectedinvalid_request_error422Rejection does not apply from the current state: once invoiced, cancelled or expired, the pro forma is closed.
proforma_cannot_be_sentinvalid_request_error422Sending by email does not apply to a pro forma in a terminal state: there is no live offer to deliver.
proforma_invalid_status_transitioninvalid_request_error422The target status is unreachable from the current one: a draft can be accepted, cancelled or expire; an accepted pro forma can be invoiced, rejected or expire; invoiced, cancelled and expired are terminal.
proforma_not_convertible_in_current_stateinvalid_request_error422Converting into an invoice requires the customer to have accepted the pro forma; from any other state there is no agreement to bill.
proforma_not_deletable_in_current_stateinvalid_request_error422Only a draft pro forma can be deleted. Once it has been accepted, rejected or invoiced, it is part of the commercial trail.
proforma_not_draftinvalid_request_error422The operation only makes sense while the pro forma is a draft, and this one has already moved on.
proforma_not_editable_in_current_stateinvalid_request_error422Only a draft pro forma admits editing. Once it is accepted, rejected, expired, invoiced or cancelled, its content is settled.
proforma_not_foundnot_found_error404The identifier does not resolve to any pro forma of the authenticated company.
proforma_requires_at_least_one_lineinvalid_request_error422The pro forma has no lines, so there is no amount to put in front of the customer.
public_link_expires_at_exceeds_max_daysinvalid_request_error422The requested expiry for the public link goes beyond the maximum window your plan allows for shared documents.

Purchase Invoices

CodeTypeHTTPDescription
attachment_invalid_filenameinvalid_request_error422The file name is not usable: it is empty, it carries path components, or it exceeds 200 characters.
attachment_mime_not_allowedinvalid_request_error422The file type is outside the accepted set: PDF, PNG, JPEG, XML and HTML.
attachment_missingnot_found_error404The purchase invoice exists but carries no attached file, so there is nothing to download.
attachment_too_largeinvalid_request_error422The file exceeds the maximum size allowed for a document attachment.
cannot_attach_to_cancelled_purchase_invoiceinvalid_request_error422The invoice is cancelled, and attaching documents to a cancelled record would alter closed documentation.
invalid_purchase_invoice_idinvalid_request_error400The purchase invoice reference received is not a valid identifier, usually because an internal value replaced the public id.
invalid_purchase_invoice_numberinvalid_request_error422The invoice number is empty or does not fit the accepted format. On a purchase invoice the number is the one the supplier printed, not one Factuarea generates.
invalid_purchase_invoice_uuidinvalid_request_error400The purchase invoice identifier in the path or in the payload is not a valid UUID.
operation_regime_invalidinvalid_request_error422The operation regime is outside the catalogue general, intracomunitaria, importacion_exportacion, isp.
purchase_invoice_already_existsconflict_error409That supplier already has a purchase invoice registered with the same number. The pair supplier plus number identifies the document uniquely and prevents recording an expense twice.
purchase_invoice_not_deletable_in_current_stateinvalid_request_error422Only draft and cancelled purchase invoices can be deleted. A pending or paid one is part of the expense ledger.
purchase_invoice_not_draftinvalid_request_error422The operation only applies while the purchase invoice is a draft, and this one has already been registered.
purchase_invoice_not_editable_in_current_stateinvalid_request_error422Only a draft purchase invoice can be edited. Once registered as pending, paid or cancelled, its content backs an accounting entry.
purchase_invoice_not_foundnot_found_error404The identifier does not resolve to any purchase invoice of the authenticated company.
purchase_invoice_requires_at_least_one_lineinvalid_request_error422The purchase invoice has no lines, so there is no expense nor deductible VAT to record.

Quotes

CodeTypeHTTPDescription
quote_already_acceptedinvalid_request_error422The quote was already approved, and approval is registered once.
quote_already_rejectedinvalid_request_error422The quote is already marked as rejected.
quote_cannot_be_sentinvalid_request_error422The quote is rejected, converted, expired or cancelled: it is no longer a live offer to deliver.
quote_expiredinvalid_request_error422The quote passed its validity date, so the offered conditions are no longer binding and it cannot be approved or converted as is.
quote_not_foundnot_found_error404The identifier does not resolve to any quote of the authenticated company.

Rate Limit

CodeTypeHTTPDescription
account_probation_limit_exceededrate_limit_error429The company is inside its NEW-ACCOUNT PROBATION window, and the ceiling that rejected this call comes from the ACCOUNT'S AGE, not from its plan. A freshly created account starts with a reduced allowance that widens on its own as the account matures.
company_monthly_quota_exceededrate_limit_error429The company used up the monthly volume its plan grants to all of its keys together.
company_rate_limit_exceededrate_limit_error429The company exceeded the per-minute rate its plan grants to all of its keys together, not the rate of a single key.
email_delivery_circuit_openrate_limit_error429Email sending is temporarily CUT, either by a provider incident or by a delivery problem of this company. It is not a quota: it is a safety cut so sending reputation is not burnt further while delivery keeps failing.
email_recipient_budget_exceededrate_limit_error429The company ran out of DISTINCT RECIPIENT budget for the window. This is not a request limit: it counts mailboxes reached, so neither splitting the send across more calls nor using another credential changes anything.
monthly_quota_exceededrate_limit_error429The company exhausted the monthly call quota its plan includes.
pdf_generation_budget_exceededrate_limit_error429The hourly budget of PDF RENDER WORK is exhausted. This is not a request limit: it counts renders against the Chrome pool shared by every tenant, so neither spreading the calls nor using another credential changes anything. The subcode says which of the two budgets ran out — company_budget (the whole company) or document_budget (this single document, while the rest keep generating).
portfolio_monthly_quota_exceededrate_limit_error429The portfolio MONTHLY quota is exhausted. It is counted over the managing company and its active children together, so one child's consumption exhausts everyone's.
portfolio_rate_limit_exceededrate_limit_error429The per-minute ceiling you hit belongs to the PORTFOLIO — the managing company plus all its active child companies together — not to this credential nor to this company. That is why neither spreading traffic across credentials nor onboarding another child company changes anything: both keep counting in the same bucket.
rate_limit_exceededrate_limit_error429The key sent more requests than its rate allows in the current window.
upload_in_flight_budget_exceededrate_limit_error429The company has too many bytes crossing the temporary disk at once (tabular imports and their previews, UBL, OCR and backup restore). This is a budget of bytes IN FLIGHT, not of stored space: it consumes no request bucket and does not appear in the rate-limit headers.

Recurring Invoices

CodeTypeHTTPDescription
invalid_frequency_intervalinvalid_request_error422The interval is lower than 1, so the recurrence would never advance to a next run.
invalid_frequency_typeinvalid_request_error422The frequency is outside the catalogue daily, weekly, biweekly, monthly, bimonthly, quarterly, semiannual, annual, custom.
invalid_holiday_handlinginvalid_request_error422The holiday policy is outside the catalogue skip, before, after, same.
invalid_recurring_invoice_idinvalid_request_error400The recurrence reference received is not a valid identifier, usually because an internal value replaced the public id.
invalid_recurring_invoice_uuidinvalid_request_error400The recurrence identifier in the path or in the payload is not a valid UUID.
recurring_already_activeinvalid_request_error422The recurrence is already running, so there is nothing to activate. Legacy code kept for compatibility: current endpoints report this as recurring_invoice_already_active.
recurring_invoice_already_activeinvalid_request_error422The recurrence is already running.
recurring_invoice_already_cancelledinvalid_request_error422The recurrence was already cancelled, and cancellation is terminal.
recurring_invoice_already_pausedinvalid_request_error422The recurrence is already paused, so pausing it again changes nothing.
recurring_invoice_cancelled_cannot_resumeinvalid_request_error422A cancelled recurrence cannot be resumed: cancellation closes it for good, unlike a pause.
recurring_invoice_cannot_runinvalid_request_error422The recurrence cannot generate an invoice right now: it is not running, its cycle is over, or it lacks the data an invoice needs. error.message states the specific reason.
recurring_invoice_has_generated_invoicesinvalid_request_error422The recurrence already produced invoices, and those invoices depend on it for their traceability.
recurring_invoice_not_foundnot_found_error404The identifier does not resolve to any recurrence of the authenticated company.
recurring_invoice_requires_at_least_one_lineinvalid_request_error422The recurrence has no lines, so every generated invoice would come out empty.
recurring_not_activeinvalid_request_error422The operation needs a running recurrence and this one is paused, completed or cancelled. Legacy code kept for compatibility with older integrations.

Request

CodeTypeHTTPDescription
business_rule_violationinvalid_request_error422A domain invariant rejected the operation. This code carries the family; error.subcode names the concrete rule and error.message explains it.
conflicting_pagination_paramsinvalid_request_error422starting_after and ending_before travelled in the same request. They walk the collection in opposite directions, so only one of them can apply.
external_id_already_existsconflict_error409The external_id you use to reconcile with your own system is already assigned to another object of the same type in this company.
invalid_param_formatinvalid_request_error422A legacy form request rejected the shape of a value. Migrated endpoints report the same situation as parameter_invalid_format or parameter_invalid_integer.
invalid_param_valueinvalid_request_error422A legacy form request rejected the value of a field. Migrated endpoints report the same situation as parameter_invalid_enum or parameter_invalid_range.
invalid_status_transitioninvalid_request_error422The requested state is not reachable from the state the document is in right now.
length_requiredinvalid_request_error411A request with a body arrived using chunked transfer encoding, without declaring its size. The API needs the length up front to reject oversized payloads before buffering them.
metadata_too_many_keysinvalid_request_error422The metadata object exceeds the limit of 50 keys per resource.
metadata_value_too_longinvalid_request_error422One value of metadata exceeds 500 characters once serialised to text.
method_not_allowedinvalid_request_error405The path exists but does not accept the HTTP verb used.
missing_required_paraminvalid_request_error422A legacy form request found a required field missing. Endpoints already migrated to the canonical parsers report the same situation as parameter_missing.
parameter_invalidinvalid_request_error422A value object built from the payload rejected the value it received. error.subcode names which one — tax code, country code, rate, and so on.
parameter_invalid_booleaninvalid_request_error400A parameter that must be a boolean received a value outside the accepted representations (true/false, 1/0).
parameter_invalid_cursorinvalid_request_error400The starting_after or ending_before cursor is not a valid UUID, so it cannot point at any row of the collection.
parameter_invalid_emptyinvalid_request_error400A parameter arrived with an empty value: an in filter with no items, a comparison with nothing after the operator, or an equality filter with an empty string.
parameter_invalid_enuminvalid_request_error400The value falls outside the closed set the parameter accepts. On listings it also covers a filter operator other than eq, gte, lte, gt, lt, in or contains.
parameter_invalid_formatinvalid_request_error400The value has the right type but not the shape the parameter requires: a date, an identifier pattern or a header such as Factuarea-Version.
parameter_invalid_integerinvalid_request_error400A parameter that must be a whole number received something that cannot be parsed as one, such as limit=abc.
parameter_invalid_iso8601invalid_request_error400A range filter (gte, lte, gt, lt) received a value that is neither numeric nor an ISO 8601 date.
parameter_invalid_rangeinvalid_request_error400A numeric parameter fell outside its accepted bounds. The usual case is limit, which must be between 1 and 100.
parameter_invalid_stringinvalid_request_error400A parameter that must be text received an array, an object or a value that cannot be read as a string.
parameter_invalid_urlinvalid_request_error400A field that must hold an absolute URL received a value that is not one, usually because the scheme or the host is missing.
parameter_invalid_uuidinvalid_request_error400An identifier field received a value that is not a valid UUID. Every v1 resource id is a UUID.
parameter_invalid_valueinvalid_request_error422The value is syntactically correct but not admissible for this resource: outside the canonical catalogue of the field, or inconsistent with the rest of the payload.
parameter_missinginvalid_request_error400The endpoint requires a parameter that the request did not carry. error.param names it.
parameter_unknowninvalid_request_error400The request carries a parameter the endpoint does not accept: a filter outside its allowlist, a sort field that is not sortable, or the offset-style page — v1 paginates by cursor.
payload_too_largeinvalid_request_error413The request body exceeds the accepted size: 1 MB as a rule, 6 MB on the endpoints that accept files.
profile_not_foundnot_found_error404The X-Active-Profile header names a company that does not exist or does not belong to the accounting-firm tree of the authenticated key. Both cases answer the same so that the API never reveals companies of other tenants.
resource_already_existsconflict_error409Creating the object would duplicate one that already exists under a unique key — tax id, SKU, external id. error.details.existing_resource_id points at the object that already holds the value.
resource_conflictconflict_error409The operation collided with the current state of the resource and no more specific conflict code applies.
resource_immutableinvalid_request_error422The object is closed to changes for this operation: its state or its accounting record forbids modifying it.
resource_lockedconflict_error409Another operation holds the resource until it finishes: concurrent writes on the same object are serialised instead of interleaved.
resource_not_deletableinvalid_request_error422The object exists but its state or its dependants block the deletion. In bulk deletions this is the per-row code of every entry that could not be removed.
resource_not_foundnot_found_error404The identifier resolves to nothing visible to the authenticated company. Objects belonging to another company answer exactly the same way, by design.
route_not_foundnot_found_error404The path does not match any v1 endpoint. It is usually a typo, a missing /v1 prefix, or a path from a different area of the API.
unknown_filterinvalid_request_error422A listing received a filter it does not know. The canonical v1 parsers report this as parameter_unknown; this code survives for endpoints that have not migrated yet.
unsupported_api_versioninvalid_request_error400The Factuarea-Version header is well formed but names a version outside the supported set.
unsupported_media_typeinvalid_request_error415A request with a body declared a Content-Type other than application/json.

Series

CodeTypeHTTPDescription
cannot_archive_last_default_seriesinvalid_request_error422The series is the only active one for its document type. Archiving it would leave the company with no numbering available and freeze that kind of document.
document_type_required_for_ambiguous_codeinvalid_request_error422That series code exists for more than one document type, so on its own it does not identify a single series.
invalid_series_codeinvalid_request_error422The series code is empty, too long, or carries characters that do not belong in a fiscal prefix.
invalid_series_nameinvalid_request_error422The series name is empty or exceeds the allowed length.
invalid_series_numberinvalid_request_error422The starting number is not valid: it is not a positive integer, or it falls at or below the last number already issued, which would re-issue numbers already in use.
invalid_series_uuidinvalid_request_error400The series identifier in the path or in the payload is not a valid UUID.
invalid_series_yearinvalid_request_error422The fiscal year is not a valid four-digit year for a numbering series.
monthly_requires_month_segmented_formatinvalid_request_error422The counter resets monthly but the numbering mask does not segment by month, so two months would start on the same correlative and produce duplicate numbers within the year.
series_already_archivedinvalid_request_error422The series was already archived, and archiving is not repeated: a second call means the client is out of sync with the real state.
series_code_immutable_with_documentsinvalid_request_error422Changing the prefix of a series that already issued documents would retroactively rewrite their fiscal identifier, while customers and AEAT hold the original number.
series_has_documentsinvalid_request_error422The series already numbered documents, so it cannot be removed: the correlative sequence has to stay auditable.
series_immutableinvalid_request_error405Series are not editable nor deletable through the API: legal numbering continuity requires their prefix, year and counter to stay put.
series_initial_number_creates_gapinvalid_request_error422The starting number jumps beyond the next natural correlative while documents already exist for the current year, and that gap in the sequence is not acceptable to AEAT.
series_locked_by_verifactuinvalid_request_error422At least one invoice of the series holds a billing record accepted by AEAT, which freezes the prefix, the year and the numbering base of the series.
series_not_foundnot_found_error404The identifier does not resolve to any numbering series of the authenticated company.
series_type_invalidinvalid_request_error422The document type of the series is outside the catalogue invoice, quote, delivery_note, proforma, purchase_invoice, recurring_invoice.
series_year_lockedinvalid_request_error422The series already issued documents in its current year. Moving the year would leave those documents pointing at an empty year while their taxable base sits in another.

Server

CodeTypeHTTPDescription
dependency_unavailableservice_unavailable_error503An external service the operation relies on did not answer in time.
face_transmission_failedapi_error502The FACe platform — the public administration entry point — was unreachable or answered with a fault. The failure is upstream, not in your request.
facturae_signing_failedapi_error500The XAdES signature of the Facturae file could not be produced, usually because the signing certificate is unusable at that moment.
internal_errorapi_error500Something broke on our side while processing the request. The condition is not caused by your payload.
maintenanceservice_unavailable_error503The platform is in a maintenance window and writes are held back on purpose.
pdf_generation_failedservice_unavailable_error503The rendering service could not produce the PDF. The document and its data are intact — what failed is the file.
register_sealing_failedapi_error500The cryptographic sealing of the record did not complete, so the closure was left unsigned rather than sealed with a broken signature.
send_failedapi_error500The document was not delivered by email: the mail provider rejected the message or was unreachable.
service_unavailableservice_unavailable_error503The service, or a dependency it needs, is temporarily unable to answer.

Storage

CodeTypeHTTPDescription
storage_quota_exceededpayment_required_error402The file does not fit in the space left for the company. The balance compared is the AGGREGATE of every surface that stores bytes — vault, contract PDFs, company branding, parcels, packs, purchase attachments, certificates, bank statements and delivery-note signatures — so the disk may be full because of a surface other than the one you are using.

Tax Reports

CodeTypeHTTPDescription
insufficient_data_for_reportinvalid_request_error422The period has no data to file, or an invoice of the period lacks a mandatory field for this model — typically the customer tax id.
invalid_periodinvalid_request_error422The period does not identify a filing: the year is outside the accepted range, or the quarter is missing or out of the range 1 to 4 for a quarterly model.
report_format_invalidinvalid_request_error422The format is outside the catalogue txt_aeat, pdf, excel.
tax_report_not_foundnot_found_error404The identifier does not resolve to any tax report of the authenticated company.
tax_report_type_invalidinvalid_request_error422The report type is outside the catalogue modelo_303, modelo_347, modelo_130.
unsupported_formatinvalid_request_error422The requested format is not available for this model: not every filing produces every output.

Taxes

CodeTypeHTTPDescription
custom_tax_creation_disabledauthorization_error403Creating custom taxes is disabled for this company.
duplicate_tax_default_for_document_typeinvalid_request_error422Another tax of the same type is already the default for that document type, and the pair (tax type, document type) admits a single default.
indirect_tax_regime_invalidinvalid_request_error422The indirect regime is outside the catalogue iva, igic, ipsi.
invalid_aeat_codeinvalid_request_error422The AEAT operation code is outside the closed catalogue S1, S2, S3, E1-E6, N1, N2 used by VeriFactu and SII.
invalid_country_aeat_zoneinvalid_request_error422The AEAT territorial zone is outside the catalogue peninsula, canarias, ceuta, melilla.
invalid_country_codeinvalid_request_error422The country code is not exactly two characters, so it is not a valid ISO 3166-1 alpha-2 code.
invalid_customer_visible_labelinvalid_request_error422The label shown to the customer on the document exceeds the allowed length.
invalid_descriptioninvalid_request_error422The description exceeds the maximum length allowed for the field.
invalid_document_typeinvalid_request_error422The document type is outside the catalogue: invoice, quote, delivery_note, proforma, purchase_invoice, recurring_invoice.
invalid_rate_for_tax_regimeinvalid_request_error422The rate does not belong to the legal grid of its regime: IGIC admits 0, 3, 5, 7, 9.5, 15 and 20%; IPSI admits 0, 0.5, 1, 2, 4, 8 and 10%.
invalid_tax_codeinvalid_request_error422The tax code is empty or longer than 50 characters.
invalid_tax_nameinvalid_request_error422The tax name is empty or longer than 255 characters.
invalid_tax_rateinvalid_request_error422The rate falls outside the range allowed for its type: VAT 0-27%, withholding 0-47%, equivalence surcharge 0-10%, other 0-100%.
invalid_tax_type_filterinvalid_request_error422The type filter of the by-type listing carries a value outside the enum vat, retention, surcharge, other.
invalid_validity_windowinvalid_request_error422The validity window is inverted: valid_until falls before valid_from.
system_tax_default_modification_forbiddenauthorization_error403Defaults of the shared catalogue taxes are not set on the tax itself: the catalogue is global and the preference belongs to your company.
system_tax_immutableinvalid_request_error422The tax belongs to the canonical AEAT catalogue shipped with the product. Its rate, code and name are fixed so that every company shares the same fiscal reference.
system_tax_immutable_fieldinvalid_request_error422The update touches a field that is frozen on a system tax; error.param names it.
system_tax_undeletableinvalid_request_error422System taxes are part of the shared fiscal catalogue and cannot be removed: deleting one would break the documents that reference it.
tax_applies_to_invalidinvalid_request_error422The scope of the tax is outside the catalogue sale, purchase, both.
tax_code_already_existsconflict_error409Another tax of the catalogue already uses that code, and codes identify taxes unambiguously.
tax_id_requiredinvalid_request_error422The operation needs the tax identification number (NIF, CIF or NIE) of the party involved and the record does not carry one.
tax_in_useinvalid_request_error422The tax is referenced by documents, products or suppliers. Removing it would leave historical documents without their fiscal reference.
tax_inactive_cannot_be_defaultinvalid_request_error422A deactivated tax cannot become the default, either globally or for a document type — it would offer a hidden default that no form can pick.
tax_not_foundnot_found_error404The identifier does not match any tax of the catalogue reachable by this company.
tax_type_invalidinvalid_request_error422The tax type is outside the catalogue vat, retention, surcharge, other.

VeriFactu

CodeTypeHTTPDescription
alta_record_not_foundnot_found_error404The invoice has no registration record, so the operation that depends on it has nothing to work with.
anulacion_record_already_existsconflict_error409The invoice already carries an annulment record in the chain, and annulment is reported only once.
certificate_expiredinvalid_request_error422The certificate is outside its validity window: it has expired, or it is not valid yet.
certificate_nif_mismatchinvalid_request_error422The tax id of the certificate holder does not match the company tax id. AEAT records are signed on behalf of the company, so both must be the same.
certificate_not_foundnot_found_error404The company has no FNMT certificate matching the identifier, or none uploaded at all.
certificate_too_largeinvalid_request_error422The file exceeds the 100 KB limit, while a real FNMT certificate weighs a few kilobytes.
clock_drift_exceededinvalid_request_error422The server clock drifted from NTP beyond the allowed margin. The generation timestamp is part of the AEAT fingerprint, so an unsynchronised clock would produce records AEAT rejects.
declaracion_already_existsconflict_error409The company already filed its SIF responsibility statement for that period.
declaracion_not_foundnot_found_error404The company has no SIF responsibility statement filed for the requested period.
event_already_processedinvalid_request_error422That SIF event is already recorded in the event chain, and each event is processed exactly once.
invalid_certificate_formatinvalid_request_error422The file is not a PKCS#12 container: its first bytes do not match the ASN.1 structure the format requires, whatever its extension says.
invalid_certificate_passwordinvalid_request_error422The password does not open the certificate file.
max_retries_exceededinvalid_request_error422The record exhausted the technical retry budget for resending the stored XML. Retrying the same content again would fail the same way.
mode_switch_blocked_until_year_endinvalid_request_error422VeriFactu mode was activated during this fiscal year and at least one billing record was issued. Stepping back would degrade the integrity of a chain already reported to AEAT.
record_already_acceptedinvalid_request_error422AEAT already accepted the record. Acceptance is terminal and its content is frozen as part of the fingerprint chain.
record_immutableinvalid_request_error422The record belongs to an append-only ledger: once written, its fiscal content is closed to changes and to deletion.
record_not_rejectedinvalid_request_error422The correction flow only applies to records AEAT rejected on data grounds. This record is in another state — a technical failure, for instance, is covered by the automatic retry.
record_not_subsanableinvalid_request_error422The record cannot be amended: it is not a registration record, or it has no source invoice from which its content could be regenerated.
requires_annulmentinvalid_request_error422The regenerated content changes a field that takes part in the fingerprint — issuer tax id, series and number, issue date, invoice type, tax amount or total — and the chain cannot be rewritten.
sii_excludedinvalid_request_error422The company is registered with SII, and SII filers are excluded from the VeriFactu regulation.
verifactu_already_submittedinvalid_request_error422The invoice already has its registration record. Exactly one registration exists per invoice, so a second one would break the idempotency of the chain.
verifactu_mode_invalidinvalid_request_error422The mode is outside the catalogue verifactu / no_verifactu.
verifactu_not_eligibleinvalid_request_error422The invoice cannot be registered with AEAT right now: the company is not on VeriFactu mode, it has no active certificate, or the certificate is revoked or issued for a different tax id.
verifactu_record_not_foundnot_found_error404The identifier does not match any billing record of the authenticated company.
verifactu_transmission_failedinvalid_request_error422The transmission of the record to AEAT did not complete: the endpoint was unreachable or answered with an incident.

Webhooks

CodeTypeHTTPDescription
addon_requiredpayment_required_error402Creating webhook endpoints belongs to the Developer API add-on, and the company does not have it active — the free tier allows zero endpoints.
api_version_invalid_formatinvalid_request_error422The payload version of the endpoint is not a YYYY-MM-DD date.
api_version_unsupportedinvalid_request_error422The payload version is well formed but is not among the ones the platform serves.
custom_header_blocklistedinvalid_request_error422One of the custom headers is reserved: the HTTP layer manages it (host, content-type, content-length, user-agent), Factuarea sends it as part of the signed contract (factuarea-*), or the proxy owns it (x-forwarded-*).
custom_header_value_too_longinvalid_request_error422The value of a custom header exceeds 1024 characters.
invalid_url_targetinvalid_request_error422The destination host is not a publicly reachable address, so we refuse to deliver to it: private ranges (RFC 1918), loopback, link-local, CGNAT (100.64.0.0/10), IPv6 ULA (fc00::/7) and multicast are all rejected. Despite the wording of the message, the restriction applies in every environment, not only in production.
replay_delivery_not_retryableinvalid_request_error422Only failed deliveries can be replayed. A delivery that succeeded, or one still in flight, has nothing to resend.
replay_event_expiredinvalid_request_error422The event behind the delivery was purged by the 30-day retention policy, so there is no payload left to resend.
timeout_seconds_out_of_rangeinvalid_request_error422timeout_seconds falls outside the range 1 to 30 seconds.
too_many_custom_headersinvalid_request_error422The endpoint declares more than 20 custom headers.
webhook_delivery_not_foundnot_found_error404The identifier does not match any delivery attempt, or the delivery falls outside the retention window kept for the history.
webhook_endpoint_degradedinvalid_request_error422The endpoint is degraded after repeated delivery failures, so test pings are refused while it stays in that state.
webhook_endpoint_not_foundnot_found_error404The identifier does not resolve to any webhook endpoint of the authenticated company.
webhook_secret_recently_rotatedrate_limit_error429The signing secret was rotated less than five minutes ago. The grace window lets your receiver accept both secrets during the switch; rotating again inside it would invalidate signatures still in flight.

On this page

Need a hand?Contact support