# Factuarea API > Factuarea is a multi-tenant invoicing SaaS for Spanish businesses. The REST API (`https://api.factuarea.com/v1`) authenticates with API keys (`fact_live_*` prefix, fine-grained scopes), uses UUID v7 as opaque identifiers, returns normalized JSON envelopes (`data` + `meta`), and is fully compliant with Spanish tax law: **VeriFactu** (Royal Decree 1007/2023, AEAT real-time invoice registration), **FacturaE** 3.2.x (XML for B2G public-sector invoicing), and **Modelos 303/347** (quarterly VAT and informative declarations). All write endpoints support **idempotency keys**; events are delivered as **HMAC SHA-256 signed webhooks** with dual-secret rotation and exponential retries. This file follows the [llms.txt](https://llmstxt.org) convention. For a single-file dump of every page as clean Markdown (no MDX components, no layout chrome, no JavaScript), fetch `/llms-full.txt`. ## Getting Started - [Factuarea API](https://docs.factuarea.com/): The Factuarea REST API to automate your multi-tenant invoicing SaaS for Spanish businesses. - [Authentication](https://docs.factuarea.com/guides/authentication): API keys with fact_live_ / fact_test_ prefixes, fine-grained scopes, the privileged accounts:* scopes, what OAuth consent reaches, grace-period rotation and IP allowlist. ## Core concepts - [Pagination](https://docs.factuarea.com/guides/pagination): Cursor pagination with starting_after and ending_before, Stripe-style, plus the page-based lists of the template library and presentation history. - [Idempotency](https://docs.factuarea.com/guides/idempotency): Idempotency-Key header with 24h TTL. Retry POST without duplicating resources. - [Error handling](https://docs.factuarea.com/guides/errors): Normalized error envelope, type and code catalog with stable anchors, and retry strategy. - [Rate limits](https://docs.factuarea.com/guides/rate-limits): Per-key, company and account-portfolio quotas by tier. X-RateLimit-* headers and recommended back-off. - [Versioning](https://docs.factuarea.com/guides/versioning): Flat-versioned /v1 policy with Factuarea-Version header. Stability and deprecation commitments. ## Webhooks and events - [Webhooks](https://docs.factuarea.com/guides/webhooks): Signed POST notifications with HMAC SHA256. Verification, exponential retries and secret rotation. - [Events](https://docs.factuarea.com/guides/events): Read-only event objects with an opaque id. Historical query via the API and webhook delivery. - [Create a webhook endpoint](https://docs.factuarea.com/api-reference/webhooks/public-api.v1.webhook_endpoints.create): `POST /v1/companies/{company}/webhook-endpoints` — Create a webhook endpoint that receives event notifications via HTTPS callbacks. The signing `secret` is returned **once** in this response and never again — store it securely. - [Delete a webhook endpoint](https://docs.factuarea.com/api-reference/webhooks/public-api.v1.webhook_endpoints.delete): `DELETE /v1/companies/{company}/webhook-endpoints/{webhook_endpoint}` — Delete a webhook endpoint. In-flight deliveries are not cancelled but no new deliveries are queued. - [List all webhook endpoints](https://docs.factuarea.com/api-reference/webhooks/public-api.v1.webhook_endpoints.list): `GET /v1/companies/{company}/webhook-endpoints` — List your webhook endpoints with cursor-based pagination. - [List webhook deliveries](https://docs.factuarea.com/api-reference/webhooks/public-api.v1.webhook_endpoints.deliveries.list): `GET /v1/companies/{company}/webhook-endpoints/{webhook_endpoint}/deliveries` — List delivery attempts for a webhook endpoint with cursor-based pagination. Each delivery captures the HTTP response status, body (truncated), duration, and retry schedule. - [Ping webhook endpoint](https://docs.factuarea.com/api-reference/webhooks/public-api.v1.webhook_endpoints.ping): `POST /v1/companies/{company}/webhook-endpoints/{webhook_endpoint}/ping` — Send a synchronous test request (`{"type": "webhook.ping"}`, 10-second timeout) to the endpoint URL and return its HTTP status, a truncated body and the duration. - It carries no `Factuarea-Signature` and creates no delivery; use `test-event` to exercise the signature. - An inactive endpoint becomes `active` if the request succeeds. - [Replay webhook delivery](https://docs.factuarea.com/api-reference/webhooks/public-api.v1.webhook_endpoints.deliveries.replay): `POST /v1/companies/{company}/webhook-endpoints/{webhook_endpoint}/deliveries/{delivery}/replay` — Re-queue a webhook delivery. A new delivery attempt is created (with `attempt: 1`) for the same event/endpoint pair. - [Retrieve a webhook endpoint](https://docs.factuarea.com/api-reference/webhooks/public-api.v1.webhook_endpoints.show): `GET /v1/companies/{company}/webhook-endpoints/{webhook_endpoint}` — Retrieve a webhook endpoint by its `id`. The signing secret is never exposed in this representation. - [Retrieve webhook delivery](https://docs.factuarea.com/api-reference/webhooks/public-api.v1.webhook_endpoints.deliveries.show): `GET /v1/companies/{company}/webhook-endpoints/{webhook_endpoint}/deliveries/{delivery}` — Retrieve a single delivery attempt by its `id`, including the full event payload that was delivered. - [Rotate webhook secret](https://docs.factuarea.com/api-reference/webhooks/public-api.v1.webhook_endpoints.rotate_secret): `POST /v1/companies/{company}/webhook-endpoints/{webhook_endpoint}/rotate-secret` — Rotate the signing secret of a webhook endpoint; the new secret is returned once. - The previous secret stays valid for 24 hours (`previous_secret_valid_until`). - Rotating again within five minutes returns 422 `business_rule_violation` (subcode `webhook_secret_recently_rotated`); nothing changes. - [Send a test event](https://docs.factuarea.com/api-reference/webhooks/public-api.v1.webhook_endpoints.test_event): `POST /v1/companies/{company}/webhook-endpoints/{webhook_endpoint}/test-event` — Trigger a test delivery of a real catalog event type to this endpoint, marked `test: true` in the envelope. - Unlike `ping`, it records a real `Event` and queues a signed, retried delivery to this endpoint only. - Optional `type` picks the subscribed event to simulate. - [Update a webhook endpoint](https://docs.factuarea.com/api-reference/webhooks/public-api.v1.webhook_endpoints.update): `PATCH /v1/companies/{company}/webhook-endpoints/{webhook_endpoint}` — Update a webhook endpoint (URL, description, enabled events, status, IP allowlist). - [List all events](https://docs.factuarea.com/api-reference/events/public-api.v1.events.list): `GET /v1/companies/{company}/events` — List events in your event log with cursor-based pagination. Each event records something that happened in your account (an invoice was paid, a quote accepted, …) and is the same object delivered to your webhook endpoints. Supports filtering by `type[in]` and `created[gte|lte]`. - [List event types](https://docs.factuarea.com/api-reference/events/public-api.v1.event_catalog.list): `GET /v1/event-catalog` — List the closed catalog of event types Factuarea can emit to webhooks. Each entry exposes its `name`, `category`, a description and a `status`: `available` types are emitted today and subscribable via `enabled_events`; `coming_soon` types are reserved for a future release and not yet subscribable (passing one in `enabled_events` returns 422). - [Retrieve an event](https://docs.factuarea.com/api-reference/events/public-api.v1.events.show): `GET /v1/companies/{company}/events/{event}` — Retrieve a single event by its `id`, a UUID v7. Useful for auditing and replaying webhook payloads. Returns `404 event_not_found` if the event does not exist or belongs to another company. ## Spanish tax compliance (VeriFactu, FacturaE, Modelos) - [Activate a company certificate](https://docs.factuarea.com/api-reference/verifactu/public-api.v1.verifactu.certificates.activate): `POST /v1/companies/{company}/verifactu/certificates/{certificate}/activate` — Make a previously uploaded certificate the active one. Any other active certificate is deactivated atomically. Returns 404 if the certificate does not exist within your company. - [Find a VeriFactu record by AEAT CSV](https://docs.factuarea.com/api-reference/verifactu/public-api.v1.verifactu.records.find_by_csv): `POST /v1/companies/{company}/verifactu/records/find-by-csv` — Look up a VeriFactu record by the `aeat_csv` (Código Seguro de Verificación) returned by AEAT on acceptance, sent in the JSON body. Returns the matching record or 404 `verifactu_record_not_found`. - [Find a VeriFactu record by hash](https://docs.factuarea.com/api-reference/verifactu/public-api.v1.verifactu.records.find_by_huella): `POST /v1/companies/{company}/verifactu/records/find-by-huella` — Look up a VeriFactu record by its `huella` (the chained SHA-256 fingerprint sent in the JSON body). Returns the matching record or 404 `verifactu_record_not_found` if none exists within your company. - [Find a VeriFactu record by invoice number](https://docs.factuarea.com/api-reference/verifactu/public-api.v1.verifactu.records.find_by_invoice_number): `POST /v1/companies/{company}/verifactu/records/find-by-invoice-number` — Look up the VeriFactu record associated with a given invoice number (sent in the JSON body). Returns the matching record or 404 `verifactu_record_not_found` if the invoice has no record within your company. - [Force-create VeriFactu record for invoice](https://docs.factuarea.com/api-reference/verifactu/public-api.v1.invoices.verifactu_create): `POST /v1/companies/{company}/invoices/{invoice}/verifactu` — Creates the VeriFactu alta record for an already-issued invoice and enqueues AEAT transmission. Use when automatic creation on send was skipped. - [Get VeriFactu event summary](https://docs.factuarea.com/api-reference/verifactu/public-api.v1.verifactu.events.summary): `GET /v1/companies/{company}/verifactu/events/summary` — Return an aggregated summary of your VeriFactu SIF events grouped by type and outcome. Useful for dashboards. Returned as `{ "data": VeriFactuEventSummary }`. - [Get VeriFactu stats](https://docs.factuarea.com/api-reference/verifactu/public-api.v1.verifactu.stats): `GET /v1/companies/{company}/verifactu/stats` — Return aggregated KPIs of your VeriFactu records: totals, counts per status, breakdown by record and invoice type and last transmission time. - Optional filters: `date_from`, `date_to`, `environment` (a value other than the AEAT environment of the instance counts no records). - `pending_incident_count`, `blocked_incident_count` and `oldest_pending_at` report the pending-remission alert and ignore the filters. - [List AEAT access records](https://docs.factuarea.com/api-reference/verifactu/public-api.v1.verifactu.aeat_access.list): `GET /v1/companies/{company}/verifactu/aeat-access/records` — Return the dissociated (anonymized) AEAT access ledger with cursor-based pagination. Third-party tax identifiers (NIF) are never exposed; the cursor uses the underlying record UUID v7 only for ordering. - [List company certificates](https://docs.factuarea.com/api-reference/verifactu/public-api.v1.verifactu.certificates.list): `GET /v1/companies/{company}/verifactu/certificates` — List the FNMT (PKCS#12) certificates uploaded for your company. The certificate password is never exposed in this representation. - [List declaración responsable history](https://docs.factuarea.com/api-reference/verifactu/public-api.v1.verifactu.declaracion.history): `GET /v1/companies/{company}/verifactu/declaracion-responsable/history` — Return every version of the producer-level VeriFactu Declaración Responsable (the SIF compliance declaration issued by Factuarea), ordered by `version` descending. Read-only: the declaration is global to the producer of the system, not per-company. - [List VeriFactu events](https://docs.factuarea.com/api-reference/verifactu/public-api.v1.verifactu.events.list): `GET /v1/companies/{company}/verifactu/events` — List the VeriFactu SIF events of your company (alta/anulación transmissions, retries, AEAT responses) with cursor-based pagination. - [List VeriFactu record activity timeline](https://docs.factuarea.com/api-reference/verifactu/public-api.v1.verifactu.records.activities): `GET /v1/companies/{company}/verifactu/records/{record}/activities` — Return the audit timeline for a single VeriFactu record (creation, transmission attempts, AEAT acceptance/rejection). Paginated with a page-number cursor. - [List VeriFactu records](https://docs.factuarea.com/api-reference/verifactu/public-api.v1.verifactu.records.list): `GET /v1/companies/{company}/verifactu/records` — List the VeriFactu (Spanish AEAT SIF) records of your company with cursor-based pagination. Each record captures the alta/anulación submitted to AEAT, its hash chain (`huella`), `aeat_csv`, and transmission status. Supports filtering by `status`, `type`, `date_from`/`date_to`, and `environment`: every record goes to the AEAT environment of the instance, so a matching value returns all records and any other value none. - [Register a representation](https://docs.factuarea.com/api-reference/verifactu/public-api.v1.verifactu.representation.register): `POST /v1/companies/{company}/verifactu/representation` — Register the representation that lets Factuarea remit your VeriFactu records to AEAT; send `multipart/form-data`. - Required: `kind` (`social_collaboration_annex_i`/`aeat_power_of_attorney`), `signer_name`, `signer_tax_id`, `granted_on`, `document` (PDF, up to 5 MB). - An active one is revoked; `remission_mode` may change. Returns 201 with `data`. - [Retrieve a VeriFactu event](https://docs.factuarea.com/api-reference/verifactu/public-api.v1.verifactu.events.show): `GET /v1/companies/{company}/verifactu/events/{event}` — Retrieve a single VeriFactu SIF event by its `id` (UUID v7). Returns 404 if the event does not exist or belongs to another company. - [Retrieve a VeriFactu record](https://docs.factuarea.com/api-reference/verifactu/public-api.v1.verifactu.records.show): `GET /v1/companies/{company}/verifactu/records/{record}` — Retrieve a VeriFactu record by its `id` (UUID v7). Returns 404 `verifactu_record_not_found` if the record does not exist or belongs to another company. - [Retrieve an AEAT access record](https://docs.factuarea.com/api-reference/verifactu/public-api.v1.verifactu.aeat_access.show): `GET /v1/companies/{company}/verifactu/aeat-access/records/{record}` — Retrieve a single dissociated AEAT access record by its `id` (UUID v7). Returns 404 if the record does not exist or belongs to another company. - [Retrieve invoice VeriFactu record](https://docs.factuarea.com/api-reference/verifactu/public-api.v1.invoices.verifactu_get): `GET /v1/companies/{company}/invoices/{invoice}/verifactu` — Returns the VeriFactu (Spanish AEAT SIF) record associated with the invoice if one exists. Responds with `data: null` when the invoice has no record yet. - [Retrieve the active certificate](https://docs.factuarea.com/api-reference/verifactu/public-api.v1.verifactu.certificates.active): `GET /v1/companies/{company}/verifactu/certificates/active` — Return the currently active FNMT certificate used to sign VeriFactu transmissions. Returns 404 if no certificate has been uploaded yet. - [Retrieve the active representation](https://docs.factuarea.com/api-reference/verifactu/public-api.v1.verifactu.representation.show): `GET /v1/companies/{company}/verifactu/representation` — Return the current representation that authorizes Factuarea to remit your VeriFactu records to AEAT: kind, signer, grant date, `valid_until`, `is_expired` and whether the document is custodied. - An expired representation is still returned but no longer enables third-party remission. - Returns 404 `resource_not_found` only when there is none. - [Retrieve the current declaración responsable](https://docs.factuarea.com/api-reference/verifactu/public-api.v1.verifactu.declaracion.current): `GET /v1/companies/{company}/verifactu/declaracion-responsable` — Return the current version of the producer-level VeriFactu Declaración Responsable (art. 15 of Order HAC/1177/2024). - Read-only and global to the producer (Factuarea), not per company. - Returns 404 `declaracion_not_found` if none has been published. - [Retrieve VeriFactu config](https://docs.factuarea.com/api-reference/verifactu/public-api.v1.verifactu.config): `GET /v1/companies/{company}/verifactu/config` — Return your company's VeriFactu configuration (mode, enrollment status, the AEAT environment your records go to) and how it remits to AEAT. - `environment` and `auto_transmit` are set by the Factuarea instance, not per company: on the production API records always go to the real AEAT (`production`), automatically. - `remission_mode` is `own_certificate`, `social_collaborator` or `power_of_attorney`; `presenter_certificate_status` is `valid`, `invalid` or `not_configured`. - Includes active representation fields and `social_collaborator_available`. Passwords are never exposed. - [Retry a VeriFactu event](https://docs.factuarea.com/api-reference/verifactu/public-api.v1.verifactu.events.retry): `POST /v1/companies/{company}/verifactu/events/{event}/retry` — Re-queue the AEAT transmission of a failed VeriFactu event. Returns 404 if the event does not exist, 422 `business_rule_violation` / `event_already_processed` if it was already accepted, and 422 `max_retries_exceeded` once the retry limit is reached. - [Retry every blocked VeriFactu record](https://docs.factuarea.com/api-reference/verifactu/public-api.v1.verifactu.records.retry_blocked): `POST /v1/companies/{company}/verifactu/records/retry-blocked` — Reactivate all blocked VeriFactu records of your company and schedule their remission batch. - Blocked means in `error` and needing your action (certificate, representation, presenter, rejection); fix the cause first. - Returns 202 with `data.reactivated` (`0` if none). Bulk equivalent of `.../records/{record}/retry`. - [Retry VeriFactu transmission](https://docs.factuarea.com/api-reference/verifactu/public-api.v1.verifactu.records.retry): `POST /v1/companies/{company}/verifactu/records/{record}/retry` — Schedule your company's AEAT remission batch so a failed VeriFactu record goes out in it, never ahead of an earlier record of the chain. - There is no retry limit for records. - Returns 404 if the record does not exist and 422 `business_rule_violation` / `record_already_accepted` if AEAT accepted it. - [Revoke a company certificate](https://docs.factuarea.com/api-reference/verifactu/public-api.v1.verifactu.certificates.revoke): `DELETE /v1/companies/{company}/verifactu/certificates/{certificate}` — Revoke (delete) a company certificate so it can no longer sign VeriFactu transmissions. Returns 404 if the certificate does not exist within your company. - [Revoke the active representation](https://docs.factuarea.com/api-reference/verifactu/public-api.v1.verifactu.representation.revoke): `DELETE /v1/companies/{company}/verifactu/representation` — Revoke the active representation: Factuarea stops remitting on your behalf and `remission_mode` returns to `own_certificate`. - Terminal: a revoked representation is never reactivated; register another one. - `reason` is optional (3 to 500 characters). Returns 204; with no current representation, 422 `business_rule_violation` / `invalid_representation`. - [Subsanar a VeriFactu record](https://docs.factuarea.com/api-reference/verifactu/public-api.v1.verifactu.records.subsanar): `POST /v1/companies/{company}/verifactu/records/{record}/subsanar` — Correct (subsanar) an accepted or rejected VeriFactu `alta` by generating a NEW correction `alta`; the original is never edited. - Returns 202 with `data.id` of the new record, which starts `pending`; `can_subsanar` says if it is admitted. - 422 `record_not_rejected`, `record_not_subsanable` or `requires_annulment` (annul and issue a new `alta`). - [Update VeriFactu settings](https://docs.factuarea.com/api-reference/verifactu/public-api.v1.verifactu.settings.update): `PATCH /v1/companies/{company}/verifactu/settings` — Update your company's VeriFactu settings (activation, mode, notification emails and, with `remission_mode`, who remits to AEAT). - `auto_transmit` and `environment` are deprecated and ignored (accepted until 2026-12-07): the AEAT environment and automatic submission are set by the instance and returned in the response. - A locked transition returns 422 `business_rule_violation`; once enabled, VeriFactu mode cannot be disabled. - A third-party `remission_mode` needs a current representation of its kind, else 422 subcode `representation_required`. - Every mode change is audited. - [Upload a company certificate](https://docs.factuarea.com/api-reference/verifactu/public-api.v1.verifactu.certificates.upload): `POST /v1/companies/{company}/verifactu/certificates` — Upload an FNMT certificate (PKCS#12) as `multipart/form-data` with `certificate_file` and `certificate_password`. - Validated by magic bytes and capped at 100 KB; the password is encrypted at rest. - It is activated automatically (previous ones are deactivated); `Location` points to `.../verifactu/certificates/active`. - [Validate the VeriFactu hash chain](https://docs.factuarea.com/api-reference/verifactu/public-api.v1.verifactu.chain.validate): `GET /v1/companies/{company}/verifactu/chain/validate` — Recompute the VeriFactu hash chain (`huella`) for your company and compare it with the stored values, without changing data. - Returns whether the chain is intact and, if not, the first corrupted record. - Limited to 1 request per minute per credential and company; datasets over 50,000 records return 422 `dataset_too_large`. - [Download current or retained Facturae XML](https://docs.factuarea.com/api-reference/facturae/public-api.v1.invoices.facturae): `GET /v1/companies/{company}/invoices/{invoice}/facturae` — Stream the Facturae 3.2.2 XML of an issued invoice: signed `.xsig` with a signing certificate, otherwise `.xml` (see `X-Facturae-Signed`). - Without `submission_id` it exports the current legal source; draft and scheduled invoices return 422 `invoice_not_emittable_for_facturae`. - With an own `submission_id` it returns that attempt's exact retained bytes, never regenerated or completed with live data. - Hash and `ETag` only accompany a known retained artifact. - [List invoice FACe submissions](https://docs.factuarea.com/api-reference/facturae/public-api.v1.invoices.face_submissions.list): `GET /v1/companies/{company}/invoices/{invoice}/face-submissions` — Flat durable history for the authorized issuer and invoice. Empty history returns data: []. Includes prepared/uncertain status, source and artifact fingerprints, retained administrative/payment versions, can_transmit and requires_reconciliation. GET performs no capture, signing, transmission or reconciliation. - [Prepare or continue a FACe submission](https://docs.factuarea.com/api-reference/facturae/public-api.v1.invoices.face_submissions.submit): `POST /v1/companies/{company}/invoices/{invoice}/face-submissions` — Submit an issued invoice to FACe; needs send capability, the issuer signing certificate, DIR3 roles 01/02/03 and a contact email. - Omit the body for a fresh attempt (201); an own `submission_id` continues that prepared attempt with its retained bytes (200). - Concurrent claims and uncertain transmissions return 409; after a 500 or 502 with `attempt_id`, read that attempt before retrying. - Test keys never contact FACe. - [Request FACe submission cancellation](https://docs.factuarea.com/api-reference/facturae/public-api.v1.face_submissions.cancel): `POST /v1/companies/{company}/face-submissions/{faceSubmission}/cancel` — Requires current issuer/actor access, the edit capability of the Facturae module, facturae:write and a nonempty reason. Only submitted, registered_rcf and accounted with a durable registry number may request cancellation. Prepared and uncertain attempts cannot be cancelled. The durable processing state becomes cancellation_requested after the FACe request; retries never create another submission. - [Retrieve a durable FACe attempt](https://docs.factuarea.com/api-reference/facturae/public-api.v1.face_submissions.show): `GET /v1/companies/{company}/face-submissions/{faceSubmission}` — Read one authorized own attempt, including prepared or transmission_uncertain. Unknown and foreign identities are indistinguishable. Processing polling applies only to pollable attempts with a durable registry number. An uncertain attempt blocks new submission, cancellation and automatic retry; authorized operational reconciliation is required. Read access does not imply send capability. There is no public refresh endpoint. - [Download tax report file](https://docs.factuarea.com/api-reference/tax-reports/public-api.v1.tax_reports.download): `GET /v1/companies/{company}/tax-reports/{tax_report}/download` — Downloads the generated file for a tax report. Adds `X-Tax-Report-Hash` header for integrity verification. - [Find a tax report by period](https://docs.factuarea.com/api-reference/tax-reports/public-api.v1.tax_reports.find_by_period): `POST /v1/companies/{company}/tax-reports/find-by-period` — Looks up the most recent generated tax report for a given type and period. Returns the report or 404 `tax_report_not_found` when none exists for the period. - [Generate Modelo 130](https://docs.factuarea.com/api-reference/tax-reports/public-api.v1.tax_reports.generate_130): `POST /v1/companies/{company}/tax-reports/130` — Generates the Spanish Modelo 130 (quarterly IRPF instalment payment, direct estimation) for the given year and quarter in the requested format (txt_aeat, pdf, excel; defaults to pdf). The calculation is cumulative year-to-date (1 Jan to end of quarter). - [Generate Modelo 303](https://docs.factuarea.com/api-reference/tax-reports/public-api.v1.tax_reports.generate_303): `POST /v1/companies/{company}/tax-reports/303` — Generates the Spanish Modelo 303 (quarterly VAT) for the given year and quarter in the requested format (txt_aeat, pdf, excel). - [Generate Modelo 347](https://docs.factuarea.com/api-reference/tax-reports/public-api.v1.tax_reports.generate_347): `POST /v1/companies/{company}/tax-reports/347` — Generates the Spanish Modelo 347 (annual third-party operations > 3,005.06 EUR) for the given year. - [List tax report activities](https://docs.factuarea.com/api-reference/tax-reports/public-api.v1.tax_reports.activities): `GET /v1/companies/{company}/tax-reports/{tax_report}/activities` — Returns the cursor-paginated activity timeline (generation, download, etc.) of a single tax report generation. - [List tax report history](https://docs.factuarea.com/api-reference/tax-reports/public-api.v1.tax_reports.history): `GET /v1/companies/{company}/tax-reports/history` — Returns the paginated history of generated tax reports for the company. Optional filters: type, year. - [Preview a tax report](https://docs.factuarea.com/api-reference/tax-reports/public-api.v1.tax_reports.preview): `POST /v1/companies/{company}/tax-reports/preview` — Computes the breakdown of a tax report without persisting a generation or writing files. Ideal for interactive UIs that confirm totals before commit. - [Retrieve tax report stats](https://docs.factuarea.com/api-reference/tax-reports/public-api.v1.tax_reports.stats): `GET /v1/companies/{company}/tax-reports/stats` — Returns aggregate KPIs of the generated tax report history: totals by type and format, accumulated file size, and the current fiscal quarter/year. ## API Reference — Account and authentication - [Accept a tax ID transfer](https://docs.factuarea.com/api-reference/account/public-api.v1.account.nif_transfers.accept): `POST /v1/accounts/{account}/nif-transfers/accept` — Accept a tax ID transfer with its `secret`: the tax ID moves to the account in the path. Irreversible. - The body carries only `secret`; requires `Idempotency-Key` (else 422 `idempotency_key_required`). - Plan gates run first, e.g. 402 `additional_nif_plan_required`, 402 `payment_method_required`. - 422 `nif_transfer_invalid` for an unusable secret; 422 `nif_transfer_expired`. Requires the `nif_transfers:write` scope, which `*` does not cover: the API key must list it explicitly. - [Add a member to the account](https://docs.factuarea.com/api-reference/account/public-api.v1.account.members.create): `POST /v1/accounts/{account}/members` — Create a new person as a member of the account with a `role` (`admin` or `member`) and a required `grants` list (may be empty). - Each grant is a `company_id` plus `level` (`view` or `operate`); returns 201 with `Location`. - The credential scope must cover every tax ID (403 `forbidden_action`). - A registered email returns 422 `business_rule_violation`. Requires the `members:write` scope, which `*` does not cover: the API key must list it explicitly. - [Add a Stripe Connect return domain](https://docs.factuarea.com/api-reference/account/public-api.v1.account.connect_return_domains.create): `POST /v1/accounts/{account}/connected-accounts/return-domains` — Allow a host as the `return_url` destination of Stripe Connect authorizations started by your account. - `domain` is the bare lower-cased host (422 subcode `invalid_return_domain`). - Returns 201 without `Location`; a duplicate returns 409 `connect_return_domain_already_exists`. - Needs a live key from an owner or admin. - [Apply a bulk import of managed accounts](https://docs.factuarea.com/api-reference/account/public-api.v1.managed_accounts.imports.create): `POST /v1/accounts/imports` — Apply a bulk import of managed accounts and own tax IDs from files (`multipart/form-data`); returns 201. - Declarative and NOT atomic: each row is applied on its own; failures come back as `BLOCKED` or `ERROR`. - `Idempotency-Key` required; vouchers are returned EXACTLY ONCE, or emailed with `options.send_email`. - Requires the privileged `accounts:write` scope. - [Change an account member role](https://docs.factuarea.com/api-reference/account/public-api.v1.account.members.update): `PATCH /v1/accounts/{account}/members/{member}` — Change the account `role` of a member (`admin` or `member`), its `external_advisor` mark, or both; at least one is required. - Moving to `admin` revokes the member’s grants. Returns 200. - 422 `external_advisor_already_assigned`; 422 `business_rule_violation` for the owner. - The credential scope must cover every tax ID. Requires the `members:write` scope, which `*` does not cover: the API key must list it explicitly. - [Change the access level on a managed account](https://docs.factuarea.com/api-reference/account/public-api.v1.managed_accounts.access_level.update): `PATCH /v1/accounts/{account}/access-level` — Change the `level` (`none`, `view` or `operate`) your account keeps on one of its managed accounts. - Before the claim you can raise or lower; after it, raising returns 422 `access_level_raise_forbidden`. - A foreign or non-managed account returns 404 `account_not_found`. - Requires the privileged `accounts:write` scope. - [Change the plan of a managed account](https://docs.factuarea.com/api-reference/account/public-api.v1.managed_accounts.plan.update): `PATCH /v1/accounts/{account}/plan` — Change the plan of a managed account your account pays. - An upgrade applies and is charged at once; a downgrade stays pending until period end (`pending_plan`). - Irreversible: `Idempotency-Key` required; `enterprise` returns 422 `managed_account_plan_not_self_serve`. - Requires `operate` access on the account (403 `forbidden_action`) and the privileged `accounts:write` scope. - [Change the tax IDs an API key reaches](https://docs.factuarea.com/api-reference/account/public-api.v1.account.api_keys.update_nif_scope): `PATCH /v1/accounts/{account}/api-keys/{api_key}/nif-scope` — Replace the tax-ID scope of an API key with `scoped_company_ids`, the complete resulting list (not a delta). - The new scope can never exceed yours; a scope the plan of any tax ID disallows returns 422. - Test keys and browser-published keys cannot change scope. - Uncovered scopes return 403 `insufficient_scope`. - [Create an account webhook endpoint](https://docs.factuarea.com/api-reference/account/public-api.v1.account.webhooks.create): `POST /v1/accounts/{account}/webhooks` — Create an account webhook endpoint for HTTPS event callbacks; returns 201 and the signing `secret` once. - `account_relationship` is `own`, `managed` or `all` (default). - Needs a live key from an owner or admin (test key: 403 `insufficient_scope`). - 402 `addon_required` if the plan allows none; 422 `account_webhook_endpoint_limit_reached`. - [Create an API key](https://docs.factuarea.com/api-reference/account/public-api.v1.account.api_keys.create): `POST /v1/accounts/{account}/api-keys` — Create an API key in your account; its plaintext `secret` is returned exactly once. - Without `scoped_company_ids` it reaches the creator’s tax IDs, never more; a scope above the plan returns 422. - `environment: test` mints a sandbox `fact_test_` key; otherwise `fact_live_`. - An uncovered scope returns 403 `insufficient_scope`; `*` excludes `accounts:*` and admin scopes. - [Delete an account webhook endpoint](https://docs.factuarea.com/api-reference/account/public-api.v1.account.webhooks.delete): `DELETE /v1/accounts/{account}/webhooks/{webhook}` — Delete an account webhook endpoint: it stops receiving events at once and its queued deliveries are cancelled. Irreversible. - Requires a live key and an `Idempotency-Key`; a test key gets 403 `insufficient_scope`. - Returns 204; an unknown or foreign endpoint returns 404 `webhook_endpoint_not_found`. - [Download the bulk import template](https://docs.factuarea.com/api-reference/account/public-api.v1.managed_accounts.imports.template): `GET /v1/accounts/imports/template` — Download the CSV template of the managed account bulk import (UTF-8 with BOM, semicolon-separated, example row ignored). - `mode` is required on every row (`own_nif` or `managed_account`); `plan` only applies to `managed_account`. - Requires the privileged `accounts:read` scope. - [End the management of an account](https://docs.factuarea.com/api-reference/account/public-api.v1.managed_accounts.management.end): `DELETE /v1/accounts/{account}/management` — End the management of one of your managed accounts: your account loses access to it and its tax IDs. - Irreversible; `Idempotency-Key` required (422 `idempotency_key_required`). - If the holder claimed and you paid, the payment moves to the holder. - Requires the privileged `accounts:write` scope. - [Issue a tax ID transfer](https://docs.factuarea.com/api-reference/account/public-api.v1.account.nif_transfers.create): `POST /v1/accounts/{account}/nif-transfers` — Issue a tax ID transfer over ONE tax ID of your account (`company_id`); returns 201 with its plaintext `secret`. - The secret is shown once and never stored (`null` on replay); requires `Idempotency-Key`. - Optional `recipient_account_id` restricts who can accept; `expires_at` defaults to 24 hours (max 7 days). - 403 `forbidden_action`; 404 `profile_not_found`. Requires the `nif_transfers:write` scope, which `*` does not cover: the API key must list it explicitly. - [List account invitations](https://docs.factuarea.com/api-reference/account/public-api.v1.account.invitations.list): `GET /v1/accounts/{account}/invitations` — List the invitations of the account, cursor-paginated with `limit` (1-100, default 25) and `starting_after` or `ending_before`. - Filter by `status` (`pending`, `accepted`, `revoked`, `expired`); grants shown are only those on tax IDs your credential reads. - The acceptance secret is never listed; owner or admin only (403 `forbidden_action`). Requires the `invitations:read` scope, which `*` does not cover: the API key must list it explicitly. - [List account members](https://docs.factuarea.com/api-reference/account/public-api.v1.account.members.list): `GET /v1/accounts/{account}/members` — List every member of the account, cursor-paginated with `limit` (1-100, default 25) and `starting_after` or `ending_before`. - Each item exposes `id`, `name`, `email`, `role`, `external_advisor`, `grants[]` and a `permissions` block; only grants on tax IDs you read are published. - Requires an owner or admin credential holder (403 `forbidden_action`). Requires the `members:read` scope, which `*` does not cover: the API key must list it explicitly. - [List account webhook deliveries](https://docs.factuarea.com/api-reference/account/public-api.v1.account.webhooks.deliveries.list): `GET /v1/accounts/{account}/webhooks/{webhook}/deliveries` — List the delivery attempts of one account webhook endpoint, cursor-paginated with `limit` (1-100, default 25). - OLDEST FIRST; filter by `status` (`pending`, `delivered`, `failed`, `failed_permanently`, `cancelled`) to find failures. - Test-environment deliveries stay `pending`; `ending_before` returns 400 `parameter_unknown`; unseen endpoint returns 404. - [List account webhook endpoints](https://docs.factuarea.com/api-reference/account/public-api.v1.account.webhooks.list): `GET /v1/accounts/{account}/webhooks` — List the account webhook endpoints in the credential’s environment, cursor-paginated with `limit` (1-100, default 25) and `starting_after`. - Each shows `account_relationship`, `enabled_events`, `status` and `api_version`; the secret is never returned. - Needs a credential reaching every tax ID, issued by an owner or admin (403 `forbidden_action`); `ending_before` returns 400. - [List available personalization templates](https://docs.factuarea.com/api-reference/account/public-api.v1.account.personalization.templates): `GET /v1/companies/{company}/personalization/templates` — List the PDF templates available for the account's plan (plan-aware) plus the accepted format for the `accent_color`. Use it to discover which `pdf_template` slugs and colors can be set via `PATCH /v1/companies/{company}/personalization`. - [List issued tax ID transfers](https://docs.factuarea.com/api-reference/account/public-api.v1.account.nif_transfers.list): `GET /v1/accounts/{account}/nif-transfers` — List the tax ID transfers your account has ISSUED, cursor-paginated with `limit` (1-100, default 25). - Optional `status` filter (`active`, `expired`, `revoked`, `consumed`); invalid returns 422 `invalid_param_value`. - Limited to tax IDs you reach; received transfers and the `secret` are never listed. Needs `nif_transfers:read`. Requires the `nif_transfers:read` scope, which `*` does not cover: the API key must list it explicitly. - [List managed accounts](https://docs.factuarea.com/api-reference/account/public-api.v1.managed_accounts.list): `GET /v1/accounts` — List the managed accounts your account provisioned, only in the environment of the key. - Filter by `status` and `external_ref`; cursor-paginated with `limit` (1-100) and `starting_after`. - Without `status` only managements in force are listed; `ended` items carry just the identifiers. - Requires the privileged `accounts:read` scope. - [List Stripe Connect return domains](https://docs.factuarea.com/api-reference/account/public-api.v1.account.connect_return_domains.list): `GET /v1/accounts/{account}/connected-accounts/return-domains` — List the hosts your account allows as `return_url` destination for Stripe Connect authorizations, cursor-paginated. - Each item exposes `id` (UUID v7), `domain` and `created_at`. - The credential must reach every tax ID of the account and come from an owner or admin. - [List the grants of an account member](https://docs.factuarea.com/api-reference/account/public-api.v1.account.members.grants.list): `GET /v1/accounts/{account}/members/{member}/grants` — List the per-tax-ID grants of one member. - The list is complete: `has_more` is always `false` and `next_cursor` is `null`. - Only grants on tax IDs your credential reads are published; an `owner` or `admin` returns an empty list. - 404 `member_not_found` if unknown or of another account. Requires the `members:read` scope, which `*` does not cover: the API key must list it explicitly. - [List your account API request logs](https://docs.factuarea.com/api-reference/account/public-api.v1.account.request_logs.list): `GET /v1/accounts/{account}/request-logs` — List the requests made with ANY API key of your account, newest first, in the credential’s environment. - Filters: `method`, `status_range`, `only_errors`, `api_key_prefix`, `path_search`, `created_at[gte|lte]`; cursor is `starting_after`. - Rows are purged after 30 days. Needs a credential reaching every tax ID, issued by an owner or admin. - [List your API keys](https://docs.factuarea.com/api-reference/account/public-api.v1.account.api_keys.list): `GET /v1/accounts/{account}/api-keys` — List the API keys of your account with cursor-based pagination; the plaintext secret is never returned. - Each key exposes `prefix`, `scopes`, `tier`, `environment` (`live`/`test`) and lifecycle timestamps. - A key is listed only when every tax ID of its scope is within the calling credential’s scope. - An account identifier that is not yours returns 404. - [Preview a bulk import of managed accounts](https://docs.factuarea.com/api-reference/account/public-api.v1.managed_accounts.imports.preview): `POST /v1/accounts/imports/preview` — Preview, with no effect, a bulk import of managed accounts and own tax IDs: send the same `multipart/form-data` body you would apply. - Returns each row's `status`, `errors`, `plan` and amounts, plus totals; nothing is written or charged. - Needs no `Idempotency-Key`; limits are 5 MB per file and 100 account rows. - Requires the privileged `accounts:write` scope. - [Preview a managed account plan change](https://docs.factuarea.com/api-reference/account/public-api.v1.managed_accounts.plan.preview): `GET /v1/accounts/{account}/plan/preview` — Preview, with no effect, changing the plan of a managed account your account pays. - Upgrades are `immediate` and charged at once; downgrades are `period_end` and list tax IDs to deactivate. - Requires `operate` access on the account (403 `forbidden_action`). - Requires the privileged `accounts:read` scope. - [Preview the provisioning of a managed account](https://docs.factuarea.com/api-reference/account/public-api.v1.managed_accounts.provisioning_preview): `GET /v1/accounts/provisioning-preview` — Preview, with no effect, provisioning a NEW managed account of the `plan` in the query: what is charged today and the monthly fee after. - Amounts are integer cents; nothing is created or charged, so no `Idempotency-Key` is needed. - With a `fact_test_` key every amount is 0. - Requires the privileged `accounts:read` scope. - [Provision a managed account](https://docs.factuarea.com/api-reference/account/public-api.v1.managed_accounts.create): `POST /v1/accounts` — Provision a SEPARATE account for one of your clients, with its tax ID, plan and your `access_level`; your account pays it. - Returns 201 with the claim voucher shown EXACTLY ONCE, or emailed with `send_email: true`. - Repeating an `external_ref` returns 200 with no new voucher; `Idempotency-Key` is required. - Requires the privileged `accounts:write` scope. - [Reissue the claim voucher of a managed account](https://docs.factuarea.com/api-reference/account/public-api.v1.managed_accounts.claim_tokens.create): `POST /v1/accounts/{account}/claim-tokens` — Issue a NEW claim voucher for a managed account its holder has not claimed yet; pending vouchers stop working. - Returns 201; `claim_token` and `claim_url` are shown EXACTLY ONCE, or emailed with `send_email: true`. - `Idempotency-Key` required; 409 `provisioning_account_claimed` if already claimed. - Requires the privileged `accounts:write` scope. - [Remove a member from the account](https://docs.factuarea.com/api-reference/account/public-api.v1.account.members.delete): `DELETE /v1/accounts/{account}/members/{member}` — Remove a member from the WHOLE account: it loses every grant, session and API-key scope there. Irreversible. - To remove access to one tax ID, revoke that grant instead. Returns 204. - 422 `member_is_last_owner` for the owner (transfer ownership first); 422 `business_rule_violation` when removing yourself. - 404 `member_not_found` if unknown or of another account. Requires the `members:write` scope, which `*` does not cover: the API key must list it explicitly. - [Remove a Stripe Connect return domain](https://docs.factuarea.com/api-reference/account/public-api.v1.account.connect_return_domains.delete): `DELETE /v1/accounts/{account}/connected-accounts/return-domains/{return_domain}` — Remove a return domain of your account; responds 204 with no body. - Later `return_url` values on that host are rejected with 422 `connect_return_url_not_allowed`; started authorizations keep theirs. - An unknown domain, or one of another account, returns 404 `connect_return_domain_not_found`. - Needs a live key from an owner or admin; undo by adding the host again. - [Resend an account invitation](https://docs.factuarea.com/api-reference/account/public-api.v1.account.invitations.resend): `POST /v1/accounts/{account}/invitations/{invitation}/resend` — Resend a pending invitation: a NEW acceptance secret is issued, the previous one stops working and expiry is renewed. - Returns 200; `secret` and `accept_url` appear once, only for a copy-link invitation; `null` on replay. - An `admin` invite needs a scope covering every tax ID of the account. - 422 `invitation_expired` if expired; 404 `invitation_not_found`. Requires the `invitations:write` scope, which `*` does not cover: the API key must list it explicitly. - [Retrieve a managed account](https://docs.factuarea.com/api-reference/account/public-api.v1.managed_accounts.show): `GET /v1/accounts/{account}` — Retrieve one of your managed accounts by `id`: status, environment, plan, your `access_level`, tax IDs, claim state and management status. - Works with any `access_level`, `none` included. - A non-managed, foreign or ended account returns 404 `account_not_found`. - Requires the privileged `accounts:read` scope. - [Retrieve a member module access level](https://docs.factuarea.com/api-reference/account/public-api.v1.account.members.module_access.show): `GET /v1/accounts/{account}/members/{member}/module-access` — Retrieve the module access of an account member in the tax ID given by the required `company_id` query parameter. - `restrictions` is a DENY list per section; an empty object means no restriction. - `grants` lists administrator-only sections granted; always empty for an `owner` or `admin`. - Unknown member or tax ID returns the same 404 `member_not_found`. Requires the `members:read` scope, which `*` does not cover: the API key must list it explicitly. - [Retrieve account billing details](https://docs.factuarea.com/api-reference/account/public-api.v1.account.billing): `GET /v1/companies/{company}/billing` — Return the subscription billing snapshot of the company: base plan, additional NIF subscription and default payment method. - The additional NIF subscription is `null` without additional tax IDs. - A tax ID paid by another account gets `managed: true`, plan `gestionada`, no payment data. - Amounts are 2-decimal euro strings; unresolved ones are `null`. - [Retrieve account usage for the current period](https://docs.factuarea.com/api-reference/account/public-api.v1.account.usage): `GET /v1/accounts/{account}/usage` — Retrieve the API usage of your account for the CURRENT period: total requests, total documents and a per-tax-ID breakdown. - The subject is the account, so the answer is the same whichever tax ID is effective; the period is resolved server-side. - Distinct from automation run usage, which is per company. - An account identifier that is not yours returns 404 `account_not_found`. - [Retrieve an account API request log](https://docs.factuarea.com/api-reference/account/public-api.v1.account.request_logs.show): `GET /v1/accounts/{account}/request-logs/{request_id}` — Retrieve one request made with any API key of your account by the `req_…` id from the `X-Request-Id` header. - It is an opaque string, not a UUID v7; the body matches the listing. - A missing, foreign or purged request returns 404 `resource_not_found`. - [Retrieve an account invitation](https://docs.factuarea.com/api-reference/account/public-api.v1.account.invitations.show): `GET /v1/accounts/{account}/invitations/{invitation}` — Retrieve one invitation by its `id` (UUID v7): `email`, `role`, initial `grants[]`, `send_email`, `external_advisor`, `status` and `expires_at`. - Grants shown are only those on tax IDs your credential reads. - The acceptance secret and URL are never returned here. - An unknown, malformed or foreign invitation returns the same 404 `invitation_not_found`. Requires the `invitations:read` scope, which `*` does not cover: the API key must list it explicitly. - [Retrieve an account member](https://docs.factuarea.com/api-reference/account/public-api.v1.account.members.show): `GET /v1/accounts/{account}/members/{member}` — Retrieve one member of the account by its `id` (UUID v7): `role`, `external_advisor`, `grants[]` and the caller’s `permissions` on it. - Grants shown are only those on tax IDs your credential reads. - Owner or admin only (403 `forbidden_action`); an unknown or foreign member returns 404 `member_not_found`. Requires the `members:read` scope, which `*` does not cover: the API key must list it explicitly. - [Retrieve an account member grant](https://docs.factuarea.com/api-reference/account/public-api.v1.account.members.grants.show): `GET /v1/accounts/{account}/members/{member}/grants/{company}` — Retrieve the grant of one member on one tax ID of the account (`company_id` and `level`). - An unknown member, a tax ID outside the account or your credential reads, and a missing grant (any `owner` or `admin`) all return the same 404 `member_not_found`. Requires the `members:read` scope, which `*` does not cover: the API key must list it explicitly. - [Retrieve an account webhook delivery](https://docs.factuarea.com/api-reference/account/public-api.v1.account.webhooks.deliveries.show): `GET /v1/accounts/{account}/webhooks/{webhook}/deliveries/{delivery}` — Retrieve one account webhook delivery by its `id` (UUID v7) with the signed `payload` sent and your server’s `response_status` and truncated `response_body`. - An unseen delivery or endpoint returns 404 `webhook_delivery_not_found`. - [Retrieve an account webhook endpoint](https://docs.factuarea.com/api-reference/account/public-api.v1.account.webhooks.show): `GET /v1/accounts/{account}/webhooks/{webhook}` — Retrieve one account webhook endpoint by its `id` (UUID v7), in the credential’s environment; the signing secret is never included. - An unknown, deleted or foreign endpoint returns 404 `webhook_endpoint_not_found`. - Needs a credential reaching every tax ID, issued by an owner or admin. - [Retrieve an API key](https://docs.factuarea.com/api-reference/account/public-api.v1.account.api_keys.show): `GET /v1/accounts/{account}/api-keys/{api_key}` — Retrieve a single API key of your account by its `id` (UUID v7). The plaintext secret is never included. A key that does not belong to that account returns 404 `api_key_not_found` (anti-enumeration), and so does an account identifier that is not yours. - [Retrieve provisioning usage](https://docs.factuarea.com/api-reference/account/public-api.v1.account.provisioning_usage): `GET /v1/accounts/{account}/provisioning-usage` — Retrieve the provisioning usage of YOUR account as a provider. - Managed accounts by environment (test ones do not count), `limit`, `remaining` and `managed_accounts_by_plan`. - Also `provider_paid_additional_nifs` and `provider_paid_employee_seats`. - Needs the privileged `accounts:read` scope (403 `privileged_scope_required`). - [Retrieve the calling credential](https://docs.factuarea.com/api-reference/account/public-api.v1.account.show): `GET /v1/me` — Introspect the authenticating credential: identity, account, environment, rate-limit tier, effective scopes and reachable tax IDs. - Use it to validate a credential and learn your own opaque tax ID identifier. - `client_accounts[]` (max 100) is filled only with the privileged `accounts:read` scope; else `client_accounts_visible` is `false`. - [Retrieve the daily usage of an API key](https://docs.factuarea.com/api-reference/account/public-api.v1.account.api_keys.usage): `GET /v1/accounts/{account}/api-keys/{api_key}/usage` — Retrieve the daily usage of an API key over the last `days` days (7, 30 or 90; default 30). - `daily` lists requests, successes, 4xx, 429 and 5xx per day, oldest first; `total` sums them. - `last_used_at`/`last_used_ip` are `null` if never used. Requires `account:read`. - Unknown key returns 404 `api_key_not_found`; other `days` returns 422. - [Retry an account webhook delivery](https://docs.factuarea.com/api-reference/account/public-api.v1.account.webhooks.deliveries.retry): `POST /v1/accounts/{account}/webhooks/{webhook}/deliveries/{delivery}/retry` — Re-arm a failed delivery: the SAME delivery returns to `pending` and is sent again with the current signing secret. - Only `failed` and `failed_permanently` can be retried; others return 422 subcode `account_webhook_retry_not_allowed`. - Returns 202; requires a live key and an `Idempotency-Key`; 404 `webhook_delivery_not_found`. - [Revoke a tax ID transfer](https://docs.factuarea.com/api-reference/account/public-api.v1.account.nif_transfers.revoke): `POST /v1/accounts/{account}/nif-transfers/{nif_transfer}/revoke` — Revoke a tax ID transfer your account issued before anyone accepts it; its secret then no longer moves the tax ID. - Returns 200 with `status: revoked`; optional `reason` (max 500 characters) goes to the audit trail. - Irreversible but idempotent; requires `Idempotency-Key`. - 422 `business_rule_violation` if already accepted; 404 `resource_not_found`. Requires the `nif_transfers:write` scope, which `*` does not cover: the API key must list it explicitly. - [Revoke an account invitation](https://docs.factuarea.com/api-reference/account/public-api.v1.account.invitations.cancel): `DELETE /v1/accounts/{account}/invitations/{invitation}` — Revoke a pending invitation by its `id` (UUID v7): it becomes `revoked` and its link can no longer be accepted. - It never removes an existing member; returns 204. - 422 `business_rule_violation` if already accepted or revoked; 404 `invitation_not_found` if unknown or of another account. Requires the `invitations:write` scope, which `*` does not cover: the API key must list it explicitly. - [Revoke an account member grant](https://docs.factuarea.com/api-reference/account/public-api.v1.account.members.grants.delete): `DELETE /v1/accounts/{account}/members/{member}/grants/{company}` — Revoke the grant of a member on one tax ID of the account and return 204. - Revoking a missing grant changes nothing and also returns 204; no notification is sent. - The member loses access to that tax ID through app, API and MCP, and its API keys are lowered; set the grant again to restore. - 404 `member_not_found`; 422 `grant_company_not_in_account`. Requires the `members:write` scope, which `*` does not cover: the API key must list it explicitly. - [Revoke an API key](https://docs.factuarea.com/api-reference/account/public-api.v1.account.api_keys.revoke): `POST /v1/accounts/{account}/api-keys/{api_key}/revoke` — Revoke an API key of your account immediately and irreversibly; later requests with it fail with 401. - Revoking the key in use cuts off your own access. - A key of another account returns 404 `api_key_not_found`. - A key with scopes the calling key does not cover returns 403 `insufficient_scope`. - [Rotate an account webhook secret](https://docs.factuarea.com/api-reference/account/public-api.v1.account.webhooks.rotate_secret): `POST /v1/accounts/{account}/webhooks/{webhook}/secret` — Rotate the signing secret of an account webhook endpoint; the new secret is returned once. Irreversible. - The previous secret keeps signing for 24 hours. - Rotating again within five minutes returns 422 subcode `webhook_secret_recently_rotated`. - Requires a live key and an `Idempotency-Key`; 404 `webhook_endpoint_not_found`. - [Rotate an API key secret](https://docs.factuarea.com/api-reference/account/public-api.v1.account.api_keys.rotate_secret): `POST /v1/accounts/{account}/api-keys/{api_key}/rotate-secret` — Rotate the secret of an API key: a fresh `prefix` + `secret` is returned in plaintext exactly once. Irreversible. - The previous secret keeps working for a 24-hour grace window; rotating again in that window replaces it at once. - A key with scopes the calling key does not cover returns 403 `insufficient_scope` and nothing is rotated. - [Send a test event to an account webhook endpoint](https://docs.factuarea.com/api-reference/account/public-api.v1.account.webhooks.test): `POST /v1/accounts/{account}/webhooks/{webhook}/test` — Queue a signed test delivery (`test: true`) to an account webhook endpoint to check reachability and signature verification. - Optional `type` picks the event; an unsubscribed one returns 422 subcode `event_not_subscribed`. - Returns 202 with the delivery id; read the result in the endpoint’s deliveries. - Requires a live key and an `Idempotency-Key`. - [Send an account invitation](https://docs.factuarea.com/api-reference/account/public-api.v1.account.invitations.create): `POST /v1/accounts/{account}/invitations` — Invite a person by email to join the account with a `role` (`admin` or `member`) and a required `grants` list (may be empty). - Only a `member` carries grants; an `admin` invite needs a scope covering every tax ID. Returns 201. - `secret` and `accept_url` appear once, only with `send_email: false`. - Missing `grants` returns 400 `parameter_missing`. Requires the `invitations:write` scope, which `*` does not cover: the API key must list it explicitly. - [Set a member module access level](https://docs.factuarea.com/api-reference/account/public-api.v1.account.members.module_access.update): `PATCH /v1/accounts/{account}/members/{member}/module-access` — Replace the FULL set of module restrictions of a member in the tax ID named by `company_id`, and optionally its `grants`. - The body replaces every previous restriction; an empty `restrictions` lifts them all. Sent `grants` replace the old ones. - 422 `business_rule_violation` for restricting yourself, the owner or an unrestrictable section; 404 `member_not_found`. Requires the `members:write` scope, which `*` does not cover: the API key must list it explicitly. - [Set an account member grant](https://docs.factuarea.com/api-reference/account/public-api.v1.account.members.grants.update): `PUT /v1/accounts/{account}/members/{member}/grants/{company}` — Create or replace the grant of a `member` on one tax ID with a `level` (`view` or `operate`); returns 200 with the grant. - A `PUT` replacement: repeating it leaves the same state; lowering it also lowers the member’s API keys. - 422 `grant_company_not_in_account`; 422 `grants_only_for_member` for an `owner` or `admin`; 404 `member_not_found`. Requires the `members:write` scope, which `*` does not cover: the API key must list it explicitly. - [Transfer account ownership](https://docs.factuarea.com/api-reference/account/public-api.v1.account.owner.transfer): `PATCH /v1/accounts/{account}/owner` — Put the account in the name of another member: the outgoing owner becomes `admin`, the target `owner`. Irreversible. - Needs the `account:owner` scope, the current owner, and `Idempotency-Key`. - `owner_user_id` is the person UUID, not the member `id`; 403 `owner_transfer_forbidden` if not the owner. - 422 `business_rule_violation` for an invalid target. Requires the `account:owner` scope, which `*` does not cover: the API key must list it explicitly. - [Update account personalization](https://docs.factuarea.com/api-reference/account/public-api.v1.account.personalization.update): `PATCH /v1/companies/{company}/personalization` — Set the invoice-emission language, PDF template and accent color of the company in one partial update; omitted fields keep their value. `language` is one of `es`, `en`, `ca`; `pdf_template` is a slug from the `PdfTemplate` catalog; `accent_color` is a `#RRGGBB` hex color. Returns the updated `Account` resource. - [Update an account webhook endpoint](https://docs.factuarea.com/api-reference/account/public-api.v1.account.webhooks.update): `PATCH /v1/accounts/{account}/webhooks/{webhook}` — Partially update an account webhook endpoint: `url`, `enabled_events`, `account_relationship`, `description`, `api_version` or `status`. - Omitted fields keep their value; `description: null` clears it; `status` toggles `active`/`disabled`. - Requires a live key; 404 `webhook_endpoint_not_found`. - [Verify account against the AEAT census](https://docs.factuarea.com/api-reference/account/public-api.v1.account.verify_census): `POST /v1/companies/{company}/census-verification` — Check the persisted company name + tax ID pair against the AEAT census (VNifV2) to anticipate VeriFactu 4104 rejections. - No request body; it always verifies the persisted fiscal data. - Fail-open: if AEAT is unreachable it returns 200 with `status: unavailable`. - Test keys (`fact_test_`) return deterministic statuses per magic NIF without contacting AEAT. ## API Reference — Contacts ## API Reference — Catalog - [Bulk change product active state](https://docs.factuarea.com/api-reference/products/public-api.v1.products.bulk_status): `POST /v1/companies/{company}/products/bulk-status` — Move up to 50 products (by id) to the target `new_status` (`active` or `inactive`). Idempotent with respect to the target: a product already in the requested state counts as `successful` without flipping. Returns a `BulkPartialSuccessResult`; products not found come back in `failures[]`. - [Bulk publish or withdraw products on the web](https://docs.factuarea.com/api-reference/products/public-api.v1.products.bulk_channels): `POST /v1/companies/{company}/products/bulk-channels` — Set `channels.web` on up to 50 products (by id) in one request. Publishing generates the missing slug from the product name; withdrawing leaves the slug untouched. Idempotent with respect to the target: a product already in the requested channel state counts as `successful`. Returns a `BulkPartialSuccessResult`; products that do not exist or belong to another company come back in `failures[]` as `product_not_found`, and a row that cannot be changed is reported with its own `error_code` without aborting the batch. - [Create a product](https://docs.factuarea.com/api-reference/products/public-api.v1.products.create): `POST /v1/companies/{company}/products` — Create a new product in your catalog. - [Create a product presentation](https://docs.factuarea.com/api-reference/products/public-api.v1.products.presentations.create): `POST /v1/companies/{company}/products/{product}/presentations` — Create a commercial presentation for a product with its unit and conversion data. - [Create a product variant](https://docs.factuarea.com/api-reference/products/public-api.v1.products.variants.create): `POST /v1/companies/{company}/products/{product}/variants` — Create a variant under a product with its own SKU, barcode, optional price override and stock settings. - [Create a supplier offer](https://docs.factuarea.com/api-reference/products/public-api.v1.products.supplier-offers.create): `POST /v1/companies/{company}/products/{product}/supplier-offers` — Create a tenant-scoped supplier offer for a product or one of its variants. - [Delete a product](https://docs.factuarea.com/api-reference/products/public-api.v1.products.delete): `DELETE /v1/companies/{company}/products/{product}` — Delete a product. Returns 422 if the product is referenced by any document line, or with subcode `product_in_base_unit_replacement` if it takes part in a base unit replacement (as the replaced or the new product). - [Delete a product presentation](https://docs.factuarea.com/api-reference/products/public-api.v1.products.presentations.delete): `DELETE /v1/companies/{company}/products/{product}/presentations/{presentation}` — Retire a commercial presentation from the product catalog while historical document snapshots remain immutable. - [Delete a product variant](https://docs.factuarea.com/api-reference/products/public-api.v1.products.variants.delete): `DELETE /v1/companies/{company}/products/{product}/variants/{variant}` — Retire a product variant while preserving the immutable snapshots stored on historical documents. - [Delete a supplier offer](https://docs.factuarea.com/api-reference/products/public-api.v1.products.supplier-offers.delete): `DELETE /v1/companies/{company}/products/{product}/supplier-offers/{offer}` — Retire a supplier offer from the active catalog without changing historical purchase snapshots. - [Delete multiple products in bulk](https://docs.factuarea.com/api-reference/products/public-api.v1.products.bulk_delete): `POST /v1/companies/{company}/products/bulk-delete` — Delete up to 200 products in one request. Returns a `BulkPartialSuccessResult` with `total`, `successful` and `failed` counts plus a `failures` list (`id` + `error_code` + Spanish `error_message`); products included in packs or taking part in a base unit replacement (`product_in_base_unit_replacement`) are reported in `failures`. Decrements the plan usage counter accordingly. - [Download a product gallery image binary](https://docs.factuarea.com/api-reference/products/public-api.v1.products.gallery.download): `GET /v1/companies/{company}/products/{product}/gallery/{index}/download` — Stream the raw binary of a product gallery image by its 0-based index. Returns 404 if the index is missing or the file is not on disk. - [Download the product video binary](https://docs.factuarea.com/api-reference/products/public-api.v1.products.video.download): `GET /v1/companies/{company}/products/{product}/video/download` — Stream the raw binary of the product video. Returns 404 if the product has no video or the file is not on disk. - [Find a product by external ID](https://docs.factuarea.com/api-reference/products/public-api.v1.products.find_by_external_id): `POST /v1/companies/{company}/products/find-by-external-id` — Look up a single product by its `external_id` (sent in the JSON body), the integration key that maps it to a record in a third-party system (ERP/CRM/e-commerce). Orthogonal to the catalog `sku`. Returns the matching product or 404 if no product uses that external_id within your company. - [Find a product by SKU](https://docs.factuarea.com/api-reference/products/public-api.v1.products.find_by_sku): `POST /v1/companies/{company}/products/find-by-sku` — Look up a single product by its `sku` (sent in the JSON body). Returns the matching product or 404 if no product uses that SKU within your company. - [Get product sales analytics](https://docs.factuarea.com/api-reference/products/public-api.v1.products.sales_analytics): `GET /v1/companies/{company}/products/{product}/sales-analytics` — Return units sold, revenue, invoice count, month-over-month delta, monthly trend for the last 6 months, last buyer and recent activity feed for a single product. - [Get product stats](https://docs.factuarea.com/api-reference/products/public-api.v1.products.stats): `GET /v1/companies/{company}/products/stats` — Aggregated KPIs for your product catalog: total product count, active count, count below the low-stock threshold, accumulated stock value, and totals by category. Returned as `{ "data": ProductStats }`. - [List all products](https://docs.factuarea.com/api-reference/products/public-api.v1.products.list): `GET /v1/companies/{company}/products` — List products in your catalog with cursor-based pagination. - `view=storefront` lists only the active products enabled on the web, without costs, supplier offers, `metadata` or raw stock, and with `sale_price_from`; a `slug` not on sale there returns an empty list. - `slug` also finds products that used it before; `channel=web` and `updated[gte]` / `updated[lte]` support incremental sync. - Send `If-None-Match` to get `304` with no body. - [List product activity timeline](https://docs.factuarea.com/api-reference/products/public-api.v1.products.activities): `GET /v1/companies/{company}/products/{product}/activities` — Return the audit timeline for a product combining its own domain events plus document events whose lines reference it. Paginated with page and per_page query params (default 50). - [List product commercial combinations](https://docs.factuarea.com/api-reference/products/public-api.v1.products.configurations.list): `GET /v1/companies/{company}/products/{product}/configurations` — List the commercial combinations (variant x presentation x option values) of a product, each with its `signature`, own price and state. - An EMPTY list means LEGACY mode (any cross is accepted); once one exists, the list is an allow-list. - Cursor-paginated (`limit`, `starting_after`); another company's product returns 404 `product_not_found`. - [List product option groups](https://docs.factuarea.com/api-reference/products/public-api.v1.products.options.list): `GET /v1/companies/{company}/products/{product}/options` — List the SELLABLE option groups of a product (finish, flavour, service level) with their values and `price_adjustment`. - The `active` filter applies to groups only; values always come back in full, each with `is_active`. - Cursor-paginated (`limit`, `starting_after`); a product of another company returns 404 `product_not_found`. - [List product presentations](https://docs.factuarea.com/api-reference/products/public-api.v1.products.presentations.list): `GET /v1/companies/{company}/products/{product}/presentations` — List the commercial presentations configured for a product, including unit, conversion factor and presentation mode. - [List product variants](https://docs.factuarea.com/api-reference/products/public-api.v1.products.variants.list): `GET /v1/companies/{company}/products/{product}/variants` — List the variants configured for a product, including optional price and stock overrides. - [List products below the stock threshold](https://docs.factuarea.com/api-reference/products/public-api.v1.products.low_stock_report): `GET /v1/companies/{company}/products/low-stock-report` — Return products whose current stock is below their configured low-stock threshold. Useful for inventory alerts. - [List stock movements of a product](https://docs.factuarea.com/api-reference/products/public-api.v1.products.stock_movements.list): `GET /v1/companies/{company}/products/{product}/stock-movements` — Read the append-only stock ledger of a product, newest movement first. - Rows carry signed `delta` and `stock_after` (base units); `stock_after` ignores `direction`. - Cursor-paginated (`limit` + `starting_after`); `direction=in|out` narrows the rows. - [List supplier offers](https://docs.factuarea.com/api-reference/products/public-api.v1.products.supplier-offers.list): `GET /v1/companies/{company}/products/{product}/supplier-offers` — List supplier offers for a product, optionally filtered by variant, supplier, availability or preferred status. - [Preview a base unit replacement](https://docs.factuarea.com/api-reference/products/public-api.v1.products.base_unit_replacement.preview): `POST /v1/companies/{company}/products/{product}/base-unit-replacement/preview` — Compute, without writing anything, what replacing a product with one of a different base unit would do, and mint the `impact_token` that confirms it. - Requires `products:write` because the token authorises an irreversible write. - Send `target_base_unit`, `equivalence` and a `keep` or `retire` decision per presentation. - [Preview the impact of restricting a catalog](https://docs.factuarea.com/api-reference/products/public-api.v1.products.configurations.impact_preview): `POST /v1/companies/{company}/products/{product}/configurations/impact-preview` — Compute what would be lost if the commercial combinations of a product were replaced, and mint the `impact_token` that confirms that exact change. - A read that persists nothing, but requires `products:write`. - `configurations` is the COMPLETE list that stays active; an empty list retires the allow-list. - Send the token back when emptying `configurations`. - [Remove a gallery image from a product](https://docs.factuarea.com/api-reference/products/public-api.v1.products.gallery.delete): `DELETE /v1/companies/{company}/products/{product}/gallery/{index}` — Delete a gallery image by its 0-based index. Remaining images shift positions to fill the gap. - [Remove the product video](https://docs.factuarea.com/api-reference/products/public-api.v1.products.video.delete): `DELETE /v1/companies/{company}/products/{product}/video` — Delete the video associated with the product and release the storage. Idempotent: returns 204 even when no video was attached. - [Replace a product by changing its base unit](https://docs.factuarea.com/api-reference/products/public-api.v1.products.base_unit_replacement.create): `POST /v1/companies/{company}/products/{product}/base-unit-replacement` — Replace a product by a NEW one with a different base unit; returns 201 with the new product (`replaces` points at the old one). - Irreversible: `Idempotency-Key` is mandatory and the old product is deactivated for good. - Requires the `impact_token` of a current preview (stale: 422 `base_unit_replacement_preview_stale`). - [Resolve a catalog selection](https://docs.factuarea.com/api-reference/products/public-api.v1.products.resolve_selection): `POST /v1/companies/{company}/products/{product}/resolve-selection` — Resolve a partial or complete catalog selection into the combination that would be sold, with its price and open choices. - A read that persists nothing; an incomplete selection returns 200 with `status` and `pending_option_groups`. - Sending two values of the same group returns 422. - [Retrieve a product](https://docs.factuarea.com/api-reference/products/public-api.v1.products.show): `GET /v1/companies/{company}/products/{product}` — Retrieve a product by its `id`, with its price (`price`, and `sale_price` with and without VAT), `availability` and, with `include=configurable_catalog`, its option groups and combinations. - `view=storefront` returns the web view with the sellable graph (active variants, presentations and combinations, each with `sale_price` and `availability`); a product that is not on sale there answers 404 `product_not_found` like an unknown id. - Conditional reads: send `If-None-Match` to get `304` with no body. - [Search products](https://docs.factuarea.com/api-reference/products/public-api.v1.products.search): `GET /v1/companies/{company}/products/search` — Search products by free-text query against `name` and `sku`. Capped at 50 results. - [Set the preferred supplier offer](https://docs.factuarea.com/api-reference/products/public-api.v1.products.supplier-offers.preferred): `POST /v1/companies/{company}/products/{product}/supplier-offers/{offer}/preferred` — Atomically mark this offer as preferred for its product and variant target. No request body is required. - [Toggle product active state](https://docs.factuarea.com/api-reference/products/public-api.v1.products.toggle_active): `POST /v1/companies/{company}/products/{product}/toggle-active` — Flip a product between active and inactive. Inactive products are hidden from line-item selectors on new documents. - [Update a product](https://docs.factuarea.com/api-reference/products/public-api.v1.products.update): `PATCH /v1/companies/{company}/products/{product}` — Update a product in your catalog. - [Update a product presentation](https://docs.factuarea.com/api-reference/products/public-api.v1.products.presentations.update): `PATCH /v1/companies/{company}/products/{product}/presentations/{presentation}` — Update the selected commercial presentation while preserving tenant and product ownership. - [Update a product variant](https://docs.factuarea.com/api-reference/products/public-api.v1.products.variants.update): `PATCH /v1/companies/{company}/products/{product}/variants/{variant}` — Update the selected product variant and its optional price or stock overrides. - [Update a supplier offer](https://docs.factuarea.com/api-reference/products/public-api.v1.products.supplier-offers.update): `PATCH /v1/companies/{company}/products/{product}/supplier-offers/{offer}` — Update cost, unit conversion, availability or activation data of a supplier offer. - [Update product stock](https://docs.factuarea.com/api-reference/products/public-api.v1.products.update_stock): `PATCH /v1/companies/{company}/products/{product}/stock` — Replace, increase or decrease the stock quantity of a product. Defaults to set (replace); add and subtract are accepted aliases for increase and decrease. Fails with 422 if the resulting stock would be negative. - [Update stock for many products](https://docs.factuarea.com/api-reference/products/public-api.v1.products.bulk_update_stock): `POST /v1/companies/{company}/products/bulk-update-stock` — Apply a stock operation to multiple products in one request (up to 500). UUIDs that do not belong to your company are ignored silently. - [Upload a gallery image to a product](https://docs.factuarea.com/api-reference/products/public-api.v1.products.gallery.upload): `POST /v1/companies/{company}/products/{product}/gallery` — Attach an image (jpeg, png, jpg, gif or webp; up to 3 MB) to the product gallery. Returns the updated product. Fails with 422 if the gallery limit is exceeded. - [Upload a video to a product](https://docs.factuarea.com/api-reference/products/public-api.v1.products.video.upload): `POST /v1/companies/{company}/products/{product}/video` — Attach a video file (mp4, mov, avi or webm; up to 50 MB) to the product. Replaces any existing video. - [Archive a pack](https://docs.factuarea.com/api-reference/packs/public-api.v1.packs.archive): `POST /v1/companies/{company}/packs/{pack}/archive` — Archive a pack: it stops being sold and disappears from the default lists, but keeps its history. - Returns 422 `invalid_pack_status_transition` if the pack is already archived. - Use the restore operation to bring it back. - [Create a pack](https://docs.factuarea.com/api-reference/packs/public-api.v1.packs.create): `POST /v1/companies/{company}/packs` — Create a pack: a set of catalog products sold together at one price. - Send the `components` (at least two) and the `pricing` rule: `fixed`, `percent_off`, `amount_off` or `sum`. - The tax breakdown and the saving against buying the components separately are calculated for you. - Returns 409 if the `sku` or the `slug` is already used by another product or pack. - [Delete a pack](https://docs.factuarea.com/api-reference/packs/public-api.v1.packs.delete): `DELETE /v1/companies/{company}/packs/{pack}` — Delete a pack permanently. Returns 204 with no body. - Returns 422 `pack_in_use` if the pack appears in a document or in a recurring invoice; archive it instead. - It cannot be undone, so the request needs an `Idempotency-Key`. - [Get the price breakdown of a pack](https://docs.factuarea.com/api-reference/packs/public-api.v1.packs.price_breakdown): `GET /v1/companies/{company}/packs/{pack}/price-breakdown` — Get how the price of a pack is made up: total, tax breakdown, saving and what each component contributes. - `price_list_id`, `client_id`, `date` and `channel` price the pack for that context. The list is chosen as in a document: `price_list_id` wins (`null` = no list), else the default of `client_id` if active; an inactive `price_list_id` answers 422. - With a promotion on that date and channel, `price` and the shares are the promotion ones and `regular_price` is the price without it. - `warnings[]` lists what changes the result. Send `If-None-Match` to get `304`. - [List all packs](https://docs.factuarea.com/api-reference/packs/public-api.v1.packs.list): `GET /v1/companies/{company}/packs` — List the packs of the company with cursor-based pagination. - Filter by `search`, `slug` (also finds previous slugs), `sku`, `tag`, `channel`, `status`, `availability[in]` and `updated[gte]`. - Sort with `sort` on `created`, `name` or `price` (prefix `-` for descending). - `view=storefront` returns only the packs on sale on the web, without internal fields. - Conditional reads: send `If-None-Match` to get `304` with no body. - [Remove a pack image](https://docs.factuarea.com/api-reference/packs/public-api.v1.packs.images.delete): `DELETE /v1/companies/{company}/packs/{pack}/images/{image}` — Delete an image from the gallery of a pack and release its storage. Returns 204 with no body. - [Restore a pack](https://docs.factuarea.com/api-reference/packs/public-api.v1.packs.restore): `POST /v1/companies/{company}/packs/{pack}/restore` — Restore an archived pack so it can be sold again. - Returns 422 `invalid_pack_status_transition` if the pack is not archived. - [Retrieve a pack](https://docs.factuarea.com/api-reference/packs/public-api.v1.packs.show): `GET /v1/companies/{company}/packs/{pack}` — Retrieve a pack by its `id`, with its price, components, gallery and, in `view=all`, its availability and internal state. - `view=storefront` returns the web view; a pack that is not on sale there answers 404 like an unknown id. - Conditional reads: send `If-None-Match` to get `304` with no body. - [Update a pack](https://docs.factuarea.com/api-reference/packs/public-api.v1.packs.update): `PATCH /v1/companies/{company}/packs/{pack}` — Update a pack. Only the fields you send change. - `components` and `pricing` replace the previous ones as a whole, in one atomic step. - Returns 409 if the new `sku` or `slug` is already used by another product or pack. - Documents already issued keep the composition and price they were issued with. - [Update a pack image](https://docs.factuarea.com/api-reference/packs/public-api.v1.packs.images.update): `PATCH /v1/companies/{company}/packs/{pack}/images/{image}` — Change the `alt` text or the `position` of a pack gallery image. The other images shift to keep the order contiguous. - [Upload an image to a pack](https://docs.factuarea.com/api-reference/packs/public-api.v1.packs.images.upload): `POST /v1/companies/{company}/packs/{pack}/images` — Add an image to the gallery of a pack. Send `multipart/form-data` with the file in `photo` or `image` (jpeg, png, gif or webp). - Returns 201 with the new image and no `Location` header. - Returns 422 `pack_image_limit_reached` when the gallery is full. - An `Idempotency-Key` is required. - [Calculate a tax over a base amount](https://docs.factuarea.com/api-reference/taxes/public-api.v1.taxes.calculate): `POST /v1/companies/{company}/taxes/calculate` — Apply the referenced tax to a base amount and return the breakdown: base, tax_rate, tax_amount, total_amount and the full tax object. - [Calculate totals for a set of lines](https://docs.factuarea.com/api-reference/taxes/public-api.v1.taxes.calculate_totals): `POST /v1/companies/{company}/taxes/calculate-totals` — Compute subtotal, VAT, surcharge, retention and grand total for an array of line items with quantity, price, discount and tax rates. Returns the document totals plus the per-line breakdown. - [Check whether a tax is in use](https://docs.factuarea.com/api-reference/taxes/public-api.v1.taxes.is_in_use): `GET /v1/companies/{company}/taxes/{tax}/is-in-use` — Return whether your company uses the tax: documents, products, contacts and company defaults of your company only (usage by other companies is not counted). Useful for safe-deletion checks before calling DELETE. - [Create a tax](https://docs.factuarea.com/api-reference/taxes/public-api.v1.taxes.create): `POST /v1/companies/{company}/taxes` — Create a tax owned by your company with name, code, type (vat, retention, surcharge or other), rate, scope and the required ISO-2 country code. - The code must be unique among the global catalog and your own taxes (409 otherwise). - `default_for_documents` sets your defaults; an unsupported document type returns 422 `tax_not_defaultable_for_document`. - [Delete a tax](https://docs.factuarea.com/api-reference/taxes/public-api.v1.taxes.delete): `DELETE /v1/companies/{company}/taxes/{tax}` — Delete a tax owned by your company. Fails with 422 `tax_in_use` if existing documents reference it or it is configured as one of your company's defaults. System taxes respond 422 `system_tax_undeletable`; other global taxes, 403 `global_tax_read_only`. - [Get default taxes for a document type](https://docs.factuarea.com/api-reference/taxes/public-api.v1.taxes.defaults): `GET /v1/companies/{company}/taxes/defaults/{docType}` — Return the configured default taxes (vat, retention, surcharge) for the given document type, scoped to your company. Each slot is either a Tax or null when no default is configured. - [Get tax stats](https://docs.factuarea.com/api-reference/taxes/public-api.v1.taxes.stats): `GET /v1/companies/{company}/taxes/stats` — Aggregated KPIs for the tax rates available to your company: total tax count, active count, and breakdown by type (vat, retention, surcharge, other). Returned as `{ "data": TaxStats }`. - [List active taxes](https://docs.factuarea.com/api-reference/taxes/public-api.v1.taxes.active): `GET /v1/companies/{company}/taxes/active` — Return the active taxes available to your company, combining the global platform catalog plus the taxes owned by your company. - [List all taxes](https://docs.factuarea.com/api-reference/taxes/public-api.v1.taxes.list): `GET /v1/companies/{company}/taxes` — List the taxes visible to your company: the global platform catalog (Spanish IVA, IRPF, recargo, etc.) plus the taxes your company created. Each tax carries `ownership` (`global` or `company`) and can be filtered by it. `is_default` and `default_for_documents` reflect your company's effective defaults, not other companies'. - [List taxes applicable to purchases](https://docs.factuarea.com/api-reference/taxes/public-api.v1.taxes.for_purchases): `GET /v1/companies/{company}/taxes/for-purchases` — Return the taxes available for purchase documents (supplier invoices). - [List taxes applicable to sales](https://docs.factuarea.com/api-reference/taxes/public-api.v1.taxes.for_sales): `GET /v1/companies/{company}/taxes/for-sales` — Return the taxes available for sales documents (invoices, quotes, proformas, delivery notes). - [List taxes filtered by type](https://docs.factuarea.com/api-reference/taxes/public-api.v1.taxes.by_type): `GET /v1/companies/{company}/taxes/by-type` — Return taxes filtered by category via the type query param (vat, retention, surcharge, other). Defaults to vat when omitted. - [Mark a tax as the default for its type](https://docs.factuarea.com/api-reference/taxes/public-api.v1.taxes.set_default): `POST /v1/companies/{company}/taxes/{tax}/set-default` — Set a visible tax as your company's default for its category (vat, retention or surcharge) in every compatible document type; only your configuration changes. - Inactive taxes return 422 `tax_inactive_cannot_be_default`; non-defaultable ones 422 `tax_not_defaultable_for_document`. - If the category is off in all compatible types, 422 `tax_default_axis_disabled`. - [Retrieve a tax](https://docs.factuarea.com/api-reference/taxes/public-api.v1.taxes.show): `GET /v1/companies/{company}/taxes/{tax}` — Retrieve a tax visible to your company by its `id`. Taxes owned by another company respond 404. `is_default` and `default_for_documents` are your company's effective defaults. - [Retrieve the tax catalog](https://docs.factuarea.com/api-reference/taxes/public-api.v1.tax-catalog.show): `GET /v1/tax-catalog` — Return the Spanish tax catalog in one document: IVA/IGIC/IPSI regimes and rates, operation regimes, exemption causes, IRPF withholding rates and legal VAT/surcharge pairs. - No company data or custom taxes (see `GET /v1/companies/{company}/taxes`); withholding rates are POSITIVE. - Labels in es/en/ca; cacheable via `ETag` (304 on `If-None-Match`). - [Set tax default for a document type](https://docs.factuarea.com/api-reference/taxes/public-api.v1.taxes.set_default_for_document): `PATCH /v1/companies/{company}/taxes/{tax}/set-default/{docType}` — Set a visible tax as your company's default for one document type (invoice, quote, proforma, delivery_note, purchase_invoice); only your configuration changes. - `recurring_invoice`, type `other` and an incompatible `applies_to` return 422 `tax_not_defaultable_for_document`. - A category switched off for that document returns 422 `tax_default_axis_disabled`. - [Toggle tax active state](https://docs.factuarea.com/api-reference/taxes/public-api.v1.taxes.toggle): `POST /v1/companies/{company}/taxes/{tax}/toggle` — Flip a tax owned by your company between active and inactive. Inactive taxes are hidden from selectors but stay available for already-issued documents. Global catalog taxes respond 403 `global_tax_read_only`. - [Update a tax](https://docs.factuarea.com/api-reference/taxes/public-api.v1.taxes.update): `PATCH /v1/companies/{company}/taxes/{tax}` — Partial update of a tax owned by your company. System taxes (is_system=true) respond 422 `system_tax_immutable_field` when a definition field changes; any other change to the global catalog (for example `is_active`) responds 403 `global_tax_read_only`. `default_for_documents` is accepted on any visible tax and writes your company's defaults only. - [Archive a series](https://docs.factuarea.com/api-reference/series/public-api.v1.series.archive): `POST /v1/companies/{company}/series/{series}/archive` — Archive a series so it stops appearing as available for new documents. Returns 422 `business_rule_violation` with subcode `cannot_archive_last_default_series` if the series is the default and the only active series of its type, and with `series_already_archived` if it is already archived. Returns 204 on success. - [Assign the PDF template of a series](https://docs.factuarea.com/api-reference/series/public-api.v1.series.assign_pdf_template): `PATCH /v1/companies/{company}/series/{series}/pdf-template` — Set `pdf_template_id` to an active template compatible with the purpose of the series, or `null` to inherit the defaults. Send the current `expected_version` in the body and/or the strong `ETag` of this resource in `If-Match`: a wrong tag returns 412, an outdated version 409 and neither 428. A request that changes nothing does not increase the version. Fiscal numbering and the documents already issued are not modified. Requires `series:write` and current Series authority, and supports `Idempotency-Key`. - [Bootstrap the default series of a company](https://docs.factuarea.com/api-reference/series/public-api.v1.series.bootstrap): `POST /v1/companies/{company}/series/bootstrap` — Creates the default series for each document type that has no active series. No request body. - Returns one entry per type: `created`, `existing` or `no_default`. - `no_default` is pending: pick from `candidates` with `POST /v1/companies/{company}/series/{series}/default`. - Repeat calls change nothing; a repeated `Idempotency-Key` replays the original body. - [Create a series](https://docs.factuarea.com/api-reference/series/public-api.v1.series.create): `POST /v1/companies/{company}/series` — Creates a document numbering series, optionally with `number_format` (e.g. `{code}-{YYYY}-{00000}`) and `initial_number` (>=1). - The same `code` can repeat across document types, not within one type. - Code, mask and purpose can be changed with `PATCH` until the first document is issued. - [Find a series by code](https://docs.factuarea.com/api-reference/series/public-api.v1.series.find_by_code): `POST /v1/companies/{company}/series/find-by-code` — Looks up a series by `code` (JSON body, case-insensitive); pass `document_type` to resolve the exact series. - Without `document_type`, an ambiguous code returns 422 `document_type_required_for_ambiguous_code`. - Returns 404 if none exists. - [Get series stats](https://docs.factuarea.com/api-reference/series/public-api.v1.series.stats): `GET /v1/companies/{company}/series/stats` — Aggregated KPIs for your document numbering series: total series count, active and archived counts, and a breakdown by document type. Returned as `{ "data": SeriesStats }`. - [Get the default series for a document type](https://docs.factuarea.com/api-reference/series/public-api.v1.series.default): `GET /v1/companies/{company}/series/default` — Returns the default numbering series for a document type (invoice, quote, proforma, delivery_note). - For invoices, pass `invoice_kind` (default `complete`, `simplified`, `corrective`, `simplified_corrective`). - Returns 404 if no default exists; 422 `series_invoice_kind_invalid` for an unknown kind. - [List active series by document type](https://docs.factuarea.com/api-reference/series/public-api.v1.series.active): `GET /v1/companies/{company}/series/active` — Return the non-archived series of your company, optionally filtered by `document_type` and, for invoice series, by purpose (`invoice_kind`). Each invoice series carries its `invoice_kind`. Returns 422 `series_invoice_kind_invalid` for an unknown `invoice_kind`. - [List all series](https://docs.factuarea.com/api-reference/series/public-api.v1.series.list): `GET /v1/companies/{company}/series` — List your document numbering series with cursor-based pagination. - [List series activity timeline](https://docs.factuarea.com/api-reference/series/public-api.v1.series.activities): `GET /v1/companies/{company}/series/{series}/activities` — Return the audit timeline for a series combining its own domain events (creation, archive/unarchive, default changes, number consumption). Paginated with a page-number cursor (`starting_after` is the next page number). - [Mark a series as default for its type](https://docs.factuarea.com/api-reference/series/public-api.v1.series.set_default): `POST /v1/companies/{company}/series/{series}/default` — Promote a series to default for its document type. If another series was the default for the same type it is demoted atomically. Returns 204 on success. - [Retrieve a series](https://docs.factuarea.com/api-reference/series/public-api.v1.series.show): `GET /v1/companies/{company}/series/{series}` — Retrieve a series by its `id`. A series is **never deleted** through the API: `DELETE` and `PUT` on `/v1/companies/{company}/series/{series}` return `405 Method Not Allowed` with `error.code = "series_immutable"` and header `Allow: GET, PATCH`. To retire a series use `POST /v1/companies/{company}/series/{series}/archive`; to change it, use `PATCH /v1/companies/{company}/series/{series}`, which keeps the fiscal guards of the numbering. - [Retrieve the PDF template of a series](https://docs.factuarea.com/api-reference/series/public-api.v1.series.get_pdf_template): `GET /v1/companies/{company}/series/{series}/pdf-template` — Retrieve the visual template preference of a series as an independent resource: `pdf_template_id` (`null` when the series inherits the defaults), its own `version`, the document family, purpose and formats, availability and warnings. The response carries a strong `ETag` that belongs to this resource only; the `ETag` of the series is not valid here. It does not change numbering. Requires `series:read` and current Series authority (employees are not allowed). - [Unarchive a series](https://docs.factuarea.com/api-reference/series/public-api.v1.series.unarchive): `POST /v1/companies/{company}/series/{series}/unarchive` — Return an archived series back to the active pool. Does not change the current default of its type. Returns 204 on success. - [Update a series](https://docs.factuarea.com/api-reference/series/public-api.v1.series.update): `PATCH /v1/companies/{company}/series/{series}` — Partially updates a series; only the fields you send change. - Fiscal guards return 422 `business_rule_violation` with a `subcode`, e.g. `series_locked_by_verifactu`. - `code` and `number_format` lock once the series has documents; `initial_number` too after AEAT acceptance. - `document_type` cannot change; unknown series returns 404 `series_not_found`. ## API Reference — Sales documents - [Annul an invoice](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.annul): `POST /v1/companies/{company}/invoices/{invoice}/annul` — Withdraw an issued invoice with a required `reason` (3-500 chars); `void` does the same. - Irreversible: status `annulled`, number never reused. - VeriFactu cancellation to AEAT is asynchronous. **Signing certificate (NO VERI*FACTU).** Only in that mode, a missing or invalid company certificate is rejected before the invoice is annulled: 422 `verifactu_not_eligible`, `error.subcode: signing_certificate_unavailable`; nothing is consumed, so fix it and repeat the call. - [Assign a real invoice number](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.assign_real_number): `POST /v1/companies/{company}/invoices/{invoice}/assign-real-number` — Promotes a draft to a definitive invoice by assigning its real series number. In VeriFactu-enabled companies the same happens automatically on send. - [Assign the invoice visual template](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.assign_presentation): `PATCH /v1/companies/{company}/invoices/{invoice}/presentation` — Set an explicit tenant template or null inheritance without changing numbering, totals, references, payment terms or the existing capture. Supply the visual selection version and/or the strong validator from this exact presentation URI. A successful replay preserves the original result; current actor authority is still required. - [Bulk change invoice status](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.bulk_status): `POST /v1/companies/{company}/invoices/bulk-status` — Move up to 50 invoices to `issued`, `sent` (alias of `issued`) or `paid` in one call, with partial success. - `paid` requires `payment_date` (not in the future), applied to every invoice. - Failures are `resource_not_found` or `invalid_status_transition`, in a `BulkPartialSuccessResult`. - [Bulk create invoices](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.bulk_create): `POST /v1/companies/{company}/invoices/bulk-create` — Create up to 100 invoices in one call, each a full invoice payload; returns a `BulkCreateResult`. - `dry_run=true` validates every row without persisting and classifies each in `results[]`. - `dry_run=false` creates only the valid rows and reports the rest in `failures[]`. - Rows may carry `payment_terms`; bulk never upserts, and `invalid_invoice_payment_terms` is reported per row. - [Bulk delete invoices](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.bulk_delete): `POST /v1/companies/{company}/invoices/bulk-delete` — Delete up to 100 draft invoices (`ids`, UUID v7) with partial success; one failure never aborts the batch. - An issued invoice fails with `resource_not_deletable`; use `void` instead. - Returns a `BulkPartialSuccessResult` with `total`, `successful`, `failed` and `failures`. - [Bulk download invoice PDFs](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.bulk_pdf): `POST /v1/companies/{company}/invoices/bulk-pdf` — Packages the PDFs of up to 50 invoices (by id) into a single ZIP. Ids that are not found or have no generable PDF do not abort the request: the ZIP carries only the valid ones and the per-resource counts travel in the `X-Bulk-*` response headers. - [Bulk send invoices](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.bulk_send): `POST /v1/companies/{company}/invoices/bulk-send` — Sends up to 200 invoices by email (queued) in one call, reusing the single-send path per id. Returns a `BulkPartialSuccessResult` with `total`, `successful` and `failed` counts plus a `failures` list (`id` + `error_code` + Spanish `error_message`) for each invoice that could not be sent (not found, terminal status or no resolvable recipient). - [Check annulment eligibility](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.can_annul): `GET /v1/companies/{company}/invoices/{invoice}/can-annul` — Check whether an invoice can be annulled and whether a VeriFactu cancellation record will be created; call before `/annul`. - `can_annul` is the verdict without `revert_collections`. - If only live payments block it, `requires_collection_reversal` is `true` with `active_collections_amount`. - [Check simplified invoice eligibility](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.simplified_eligibility): `POST /v1/companies/{company}/invoices/simplified-eligibility` — Determines if an invoice may be issued as simplified (F2) under Real Decreto 1619/2012 art. 4 based on amount and counterparty data. - [Create a recurring invoice from an invoice](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.create_recurring): `POST /v1/companies/{company}/invoices/{invoice}/create-recurring` — Create a recurring invoice template that reuses the lines, client, and series of an existing invoice, applying the cadence (frequency, start date, optional end date and limits) supplied in the body. Returns the new recurring invoice. - [Create an invoice](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.create): `POST /v1/companies/{company}/invoices` — Create a `draft` invoice, or issue it at once with `options.issue_directly: true`. - Send an `Idempotency-Key`; a duplicate `external_id` upserts; `201` is not AEAT acceptance. - `type: F2`, `payment` or `options.register_verifactu` make it a paid one-call checkout. - `payment_terms` must balance `total_to_pay`. **Signing certificate (NO VERI*FACTU).** Only in that mode, a missing or invalid company certificate is rejected before the invoice is issued: 422 `verifactu_not_eligible`, `error.subcode: signing_certificate_unavailable`; nothing is consumed, so fix it and repeat the call. - [Create an invoice presentation revision](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.revise_presentation): `POST /v1/companies/{company}/invoices/{invoice}/presentation-revisions` — Append a derived capture using the authentic presentation_revision preview of the exact parent, target, policy and current source. Send the source token and preview fingerprint; a delivery or illustrative preview cannot authorize this action. Existing document state, fiscal numbering, references, instalments and totals remain intact. This action does not render, publish or send a PDF. Personal-data erasure is terminal. - [Delete an invoice](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.delete): `DELETE /v1/companies/{company}/invoices/{invoice}` — Delete a draft invoice. Issued invoices cannot be deleted (use `void` instead). - [Download invoice PDF](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.pdf): `GET /v1/companies/{company}/invoices/{invoice}/pdf` — Download the invoice PDF as a binary stream (`application/pdf`). - `format` is `a4` (default), `ticket_80` or `ticket_58`; others return 422 `parameter_invalid_enum`. - The `ETag` changes with the invoice, VeriFactu alta and format; `If-None-Match` returns 304. - With revisioned presentation, a draft returns its `BORRADOR` PDF (or `202` with `Retry-After` while it renders) and is never issued. - [Download the receipt PDF of a payment](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.payment_receipt): `GET /v1/companies/{company}/invoices/{invoice}/payment-receipt` — Stream the PDF receipt of one invoice payment, partial payments included; it is not an invoice and has no VERI*FACTU data. - Without `payment_id`, returns the most recent active payment. - 422 with no active payments or a reversed payment; 404 if `payment_id` is not of this invoice. - [Duplicate an invoice](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.duplicate): `POST /v1/companies/{company}/invoices/{invoice}/duplicate` — Copy the lines, client and metadata of an invoice into a new draft with a fresh `id`. - The draft is issued today; each `payment_terms` instalment keeps its amount and moves by the days between both issue dates, and `due_on` is the last moved instalment. - A simplified invoice is copied without a series and must still be eligible: 422 `simplified_invoice_not_allowed`. - Corrective, annulled and cancelled invoices return 422 `invoice_not_duplicatable_in_current_state`. - [Email quarterly ZIP to accountant](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.quarterly.send_email): `POST /v1/companies/{company}/invoices/quarterly/send-email` — Generate the quarterly ZIP and email it to a recipient, typically the tax accountant. - Unless `include_non_invoiced_charges` is `false`, it adds a CSV of charges left out of invoicing and their refunds. - A quarter with only such charges yields a CSV-only ZIP. - [Export invoices to a spreadsheet](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.export_excel): `POST /v1/companies/{company}/invoices/export/excel` — Export a selection of invoices to `xlsx` or `csv` and stream it back as an attachment. - Filter by `invoice_ids`, `client_id`, `series_id`, `status`, dates or `search`; `format` is `SUMMARY` or `ITEMS`. - Capped at 5,000 invoices: 422 `export_limit_exceeded`. - [Find an invoice by external ID](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.find_by_external_id): `POST /v1/companies/{company}/invoices/find-by-external-id` — Look up a single invoice by its `external_id` (sent in the JSON body), the integration key that maps it to a record in a third-party system (ERP/CRM/e-commerce). Distinct from the fiscal number and the `id`. Returns the matching invoice or 404 `invoice_not_found` if no invoice uses that external_id within your company. - [Find an invoice by number](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.find_by_number): `POST /v1/companies/{company}/invoices/find-by-number` — Look up one invoice by number, optionally narrowed with `year` and `series_id`. - Returns 404 if not found. - Returns 422 if the number still matches several invoices; the message lists the series and fiscal years. - [Generate corrective invoice](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.corrective): `POST /v1/companies/{company}/invoices/{invoice}/corrective` — Issue a corrective invoice amending an issued one; returns 201 with the new invoice. - Born issued; the original is never modified; AEAT alta is asynchronous. - 422 `series_invoice_kind_mismatch`. - `payment_terms` defaults to `[]`; negative instalments must add up exactly to a negative `total_to_pay`. **Signing certificate (NO VERI*FACTU).** Only in that mode, a missing or invalid company certificate is rejected before the invoice is issued: 422 `verifactu_not_eligible`, `error.subcode: signing_certificate_unavailable`; nothing is consumed, so fix it and repeat the call. - [Generate quarterly ZIP archive](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.quarterly.download_zip): `POST /v1/companies/{company}/invoices/quarterly/download-zip` — Builds and streams a binary ZIP with all invoice PDFs for the requested quarter. When the company has charges left out of invoicing in that quarter and `include_non_invoiced_charges` is not `false` (default `true`), it also includes the quarterly charges/refunds CSV and per-currency totals; without such charges the file is omitted, and if the quarter has no invoices the ZIP contains only that CSV. The response reports aggregate counts in X-Quarterly-* headers; it never returns a storage path or JSON metadata payload. - [Generate temporary PDF link](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.pdf_link): `GET /v1/companies/{company}/invoices/{invoice}/pdf-link` — Return a temporary signed URL to the invoice PDF instead of the bytes; `format` is `a4` (default), `ticket_80` or `ticket_58`. - The URL needs no API key and expires at `expires_at` (24 h) with 403. - 200 when the PDF is ready; 202 `pendiente` when queued, so retry until 200. - [Get invoice statistics](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.stats): `GET /v1/companies/{company}/invoices/stats` — Returns aggregate KPIs for the company: counts by status, revenue, pending and overdue totals, average days to payment, and corrective counts. Filterable by period (defaults to the current year). - [Get the invoice presentation](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.get_presentation): `GET /v1/companies/{company}/invoices/{invoice}/presentation` — Inspect the current visual selection and retained capture independently. Returns a virtual state before the first visual action. Reads never initialize templates, capture, publish, render or refresh legal content. - [Issue an invoice](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.issue): `POST /v1/companies/{company}/invoices/{invoice}/issue` — Issue a draft without sending it, assigning its series number. - Irreversible; send an `Idempotency-Key`. Only a `draft`, else 422 `invalid_status_transition`. - Freezes `payment_terms`: a 02/04 instalment without account is a 422 `invalid_invoice_payment_terms`. - With instalments, `due_on` must be the last one, else 422 `invoice_due_date_not_last_instalment`. - NO VERI*FACTU: without a valid company certificate, 422 `verifactu_not_eligible` (`signing_certificate_unavailable`); nothing is consumed. - [List all invoices](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.list): `GET /v1/companies/{company}/invoices` — List your invoices with cursor-based pagination. Supports filtering by `status[in]`, `client_id`, `series_id`, `issued_on[gte|lte]`, and `total[gte|lte]`. - [List corrective invoices](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.correctives): `GET /v1/companies/{company}/invoices/{invoice}/correctives` — Returns all corrective invoices associated with the original invoice. Used to reconstruct the original → rectificativa tree. - [List invoice activity](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.activities): `GET /v1/companies/{company}/invoices/{invoice}/activities` — Return the cursor-paginated activity timeline (audit log) of an invoice. - Covers status transitions, emails, reminders, VeriFactu submission results to AEAT, public link visits and payments. - The `metadata` of each type follows the `InvoiceActivity` schema. - [List invoice payments](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.payments_list): `GET /v1/companies/{company}/invoices/{invoice}/payments` — List the payments registered against an invoice, ordered by payment date. Reverted payments stay in the ledger and are reported with `is_reversed: true` — read the flag, do not infer it from absence. - [List invoice statuses](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.statuses): `GET /v1/companies/{company}/invoices/statuses` — Lists the closed catalog of invoice statuses with their public `value`, localized `label`, and UI `color`. Use it to populate filters or status pickers instead of hard-coding values. - [List payment methods](https://docs.factuarea.com/api-reference/invoices/public-api.v1.payment_methods.list): `GET /v1/payment-methods` — Lists the closed catalog of payment methods with their public `value` and localized `label`. Use it to populate the `payment_method` field when registering a payment instead of hard-coding values. - [List quarters to export](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.quarterly.available): `GET /v1/companies/{company}/invoices/quarterly/available-quarters` — List the quarters with at least one invoice, broken down by type (F1/F2/F3/R5), plus quarters with only Stripe charges left out of invoicing. - Those come back with `invoice_count` 0 and an empty breakdown; their ZIP holds only the charges CSV. - [List retained invoice presentations](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.list_presentations): `GET /v1/companies/{company}/invoices/{invoice}/presentation-history` — Return page-based capture history in descending number. Each summary retains its own purpose, format and availability; capture metadata does not prove prepared PDF bytes. Privacy-erased rows remain metadata tombstones. - [Mark an invoice as sent](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.mark_sent): `POST /v1/companies/{company}/invoices/{invoice}/mark-sent` — Record delivery of an invoice; the meaning depends on the API version. - Before `2026-10-01` it issues a draft. - From `2026-10-01` it only sets `is_sent`, on `issued`/`overdue`; else 422 `invoice_cannot_be_marked_as_sent`. **Signing certificate (NO VERI*FACTU).** Only in that mode, a missing or invalid company certificate is rejected before the invoice is issued: 422 `verifactu_not_eligible`, `error.subcode: signing_certificate_unavailable`; nothing is consumed, so fix it and repeat the call. - [Mark invoice as paid](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.mark_paid): `POST /v1/companies/{company}/invoices/{invoice}/mark-paid` — Mark an invoice as fully paid. Idempotent: if already paid, returns the invoice unchanged. Returns 422 if the invoice is in a status that cannot transition to `paid`, or if `paid_on` is later than today. A `paid_on` earlier than the issue date is accepted: it records an advance payment. - [Preview a payment reminder email](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.reminder_preview): `POST /v1/companies/{company}/invoices/{invoice}/reminder-preview` — Renders the HTML, subject, and resolved recipients of the reminder email without sending it. Same override fields as send-reminder. - [Preview an invoice draft PDF](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.pdf_preview): `GET /v1/companies/{company}/invoices/{invoice}/pdf/preview` — Stream a non-fiscal draft PDF (`application/pdf`) of an invoice marked BORRADOR, with a placeholder number and no VeriFactu QR. Nothing is persisted: the series counter and fingerprint are untouched. Returns 422 for an already issued invoice — use the standard `pdf` endpoint instead. - [Register a payment](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.payments_create): `POST /v1/companies/{company}/invoices/{invoice}/payments` — Register a partial or full payment against an invoice. - The invoice becomes `partially_paid` until the total is reached, then `paid`. - 422 for a status that rejects payments or `paid_on` later than today; an earlier date records an advance payment. - [Reschedule an invoice](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.reschedule): `PATCH /v1/companies/{company}/invoices/{invoice}/reschedule` — Move the issuance date of a scheduled invoice; it stays `scheduled` throughout and never returns to `draft`. - Only `scheduled_for` changes (strictly in the future); `scheduled_action` is kept. - With instalments, `due_on` must be the last one, else 422 `invoice_due_date_not_last_instalment`. - Any other status returns 422. - [Retrieve an invoice](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.show): `GET /v1/companies/{company}/invoices/{invoice}` — Retrieve a sales invoice by its `id`. - [Retrieve invoice administrative routing history](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.administrative_revisions.index): `GET /v1/companies/{company}/invoices/{invoice}/administrative-revisions` — Retrieve the frozen administrative snapshot, explicit override and append-only revisions of an invoice in your company. The administrative version starts at 1. A null override inherits the snapshot; an empty override explicitly selects no centres. This history is independent of fiscal parties, payment terms and PDF presentation. - [Retrieve invoice public link](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.public_link_get): `GET /v1/companies/{company}/invoices/{invoice}/public-link` — Returns the shareable public URL of the invoice along with its status, expiration, and the plan-allowed maximum extension days. - [Revert an invoice payment](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.payments_revert): `POST /v1/companies/{company}/invoices/{invoice}/payments/{payment}/reversal` — Void a payment with a required `reason`; the payment stays flagged `is_reversed: true` and is never deleted. - Irreversible: to restate the collection, register a new payment. - 422 `payment_already_reversed`, `payment_reversal_reason_invalid` or `reversal_reason_reserved` (`issued_in_error`). - The invoice returns to `overdue` or `sent`. - [Revise invoice administrative routing](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.administrative_revisions.store): `POST /v1/companies/{company}/invoices/{invoice}/administrative-revisions` — Append an administrative routing revision to an issued or overdue invoice. Supply administrative_centres (including [] to select none), a nonblank reason of at most 500 characters and the current expected_version in the body. Missing version returns 428; a stale version returns 409 with current_version only after authorization. A successful append returns 201 and its committed administrative_version. Parent invoice If-Match does not replace the body precondition. Fiscal data, issuance, payment terms and delivery are unchanged; no invoice is emailed or submitted by this operation. - [Schedule an invoice](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.schedule): `POST /v1/companies/{company}/invoices/{invoice}/schedule` — Reserve the issuance of a draft invoice for a future instant (`scheduled_for`). - The invoice moves to `scheduled` and keeps its `BORRADOR` number; no series number is consumed yet. - Only a `draft` can be scheduled and the date must be in the future (422). - With instalments, `due_on` must be the last one, else 422 `invoice_due_date_not_last_instalment`. - `issue_and_send` also emails the client if it has an email on file. - [Send a payment reminder](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.send_reminder): `POST /v1/companies/{company}/invoices/{invoice}/send-reminder` — Emails a payment reminder to the customer for this invoice. Accepts optional `email`, `subject`, `message`, `cc`, `bcc` overrides. - [Send invoice by email](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.send): `POST /v1/companies/{company}/invoices/{invoice}/send` — Send an invoice to the client by email, to the email on file unless the payload overrides it. - `attach_facturae: true` attaches the Facturae XML; `submission_id` attaches the exact retained XML of that FACe submission of this invoice. - It never submits to FACe or regenerates the submission. **Signing certificate (NO VERI*FACTU).** Only in that mode, a missing or invalid company certificate is rejected before the invoice is issued: 422 `verifactu_not_eligible`, `error.subcode: signing_certificate_unavailable`; nothing is consumed, so fix it and repeat the call. - [Substitute simplified invoices with full invoice](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.substitute_simplified): `POST /v1/companies/{company}/invoices/substitute-simplified` — Groups N simplified invoices (F2) under a single substitutive full invoice (F3) with complete recipient data. Marks the originals as substituted. **Signing certificate (NO VERI*FACTU).** Only in that mode, a missing or invalid company certificate is rejected before the invoice is issued: 422 `verifactu_not_eligible`, `error.subcode: signing_certificate_unavailable`; nothing is consumed, so fix it and repeat the call. - [Unschedule an invoice](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.unschedule): `POST /v1/companies/{company}/invoices/{invoice}/unschedule` — Cancel a scheduled issuance and return the invoice to `draft`. - Leaves no fiscal trace: no number consumed, nothing registered with VeriFactu, no email sent. - Only while the invoice is `scheduled`; a draft or an already issued invoice returns 422. - To only move the date, use `PATCH /v1/companies/{company}/invoices/{invoice}/reschedule`. - [Unsend an invoice](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.unsend): `POST /v1/companies/{company}/invoices/{invoice}/unsend` — Clear the delivery mark of an issued invoice (`is_sent` back to `false`) without changing its fiscal status. - Only `issued` and `overdue` invoices qualify; otherwise 422 `invalid_status_transition`. - Number, VeriFactu record and stock are untouched; idempotent when the invoice is not marked as sent. - To undo the sale itself, void the invoice or issue a corrective. - [Update an invoice](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.update): `PATCH /v1/companies/{company}/invoices/{invoice}` — Update a draft invoice; once issued, most fields are immutable per AEAT. - Sending `lines` replaces the whole set; a line without tax takes the default tax or returns 422. - `operation_on` cannot be after `issued_on` (422 `operation_date_after_issue_date`); `type` switches a draft between `F1` and `F2`. - `payment_terms`: omitted keeps it, `null`, `[]` or a list replace it; any calendar write needs `expected_payment_terms_version` (428 missing, 409 stale). - [Update invoice public link](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.public_link_update): `PATCH /v1/companies/{company}/invoices/{invoice}/public-link` — Applies an action to the public link: `revoke`, `activate`, `extend` (with `extend_days`), or `reset` to the plan default. - [Void an invoice](https://docs.factuarea.com/api-reference/invoices/public-api.v1.invoices.void): `POST /v1/companies/{company}/invoices/{invoice}/void` — Withdraw an issued invoice; it moves to `annulled`. - Irreversible; only `sent` or `overdue` invoices qualify, a paid one needs a corrective. - The VeriFactu cancellation is queued asynchronously: a 200 is not AEAT acceptance. **Signing certificate (NO VERI*FACTU).** Only in that mode, a missing or invalid company certificate is rejected before the invoice is annulled: 422 `verifactu_not_eligible`, `error.subcode: signing_certificate_unavailable`; nothing is consumed, so fix it and repeat the call. - [Accept a quote](https://docs.factuarea.com/api-reference/quotes/public-api.v1.quotes.accept): `POST /v1/companies/{company}/quotes/{quote}/accept` — Mark a quote as accepted by the client. Sets `accepted_at` to the current timestamp. - [Assign the quote visual template](https://docs.factuarea.com/api-reference/quotes/public-api.v1.quotes.assign_presentation): `PATCH /v1/companies/{company}/quotes/{quote}/presentation` — Set an explicit tenant template or null inheritance without changing numbering, totals, references, payment terms or the existing capture. Supply the visual selection version and/or the strong validator from this exact presentation URI. A successful replay preserves the original result; current actor authority is still required. - [Bulk change quote status](https://docs.factuarea.com/api-reference/quotes/public-api.v1.quotes.bulk_status): `POST /v1/companies/{company}/quotes/bulk-status` — Transition up to 50 quotes (by id) to a status from the closed set `[approved, rejected]`, each through the document state guard. Returns a `BulkPartialSuccessResult`; quotes whose transition is rejected (not found or not transitionable) come back in `failures[]`. - [Bulk delete quotes](https://docs.factuarea.com/api-reference/quotes/public-api.v1.quotes.bulk_delete): `POST /v1/companies/{company}/quotes/bulk-delete` — Deletes up to 100 quotes in one call. Returns a `BulkPartialSuccessResult` with `total`, `successful` and `failed` counts plus a `failures` list (`id` + `error_code` + Spanish `error_message`) for each entry that could not be deleted. - [Bulk download quote PDFs](https://docs.factuarea.com/api-reference/quotes/public-api.v1.quotes.bulk_pdf): `POST /v1/companies/{company}/quotes/bulk-pdf` — Packages the PDFs of up to 50 quotes (by id) into a single ZIP. Ids that are not found or have no generable PDF do not abort the request: the ZIP carries only the valid ones and the per-resource counts travel in the `X-Bulk-*` response headers. - [Bulk send quotes](https://docs.factuarea.com/api-reference/quotes/public-api.v1.quotes.bulk_send): `POST /v1/companies/{company}/quotes/bulk-send` — Sends up to 200 quotes by email (queued) in one call, reusing the single-send path per id. Returns a `BulkPartialSuccessResult` with `total`, `successful` and `failed` counts plus a `failures` list (`id` + `error_code` + Spanish `error_message`) for each quote that could not be sent (not found, terminal status or no resolvable recipient). - [Convert quote to invoice](https://docs.factuarea.com/api-reference/quotes/public-api.v1.quotes.convert): `POST /v1/companies/{company}/quotes/{quote}/convert` — Convert an accepted quote into an invoice. The new invoice references the source quote via metadata; the quote moves to status `converted`. - [Create a quote](https://docs.factuarea.com/api-reference/quotes/public-api.v1.quotes.create): `POST /v1/companies/{company}/quotes` — Create a new sales quote in `draft` status. Quotes can later be converted to invoices via `POST /v1/companies/{company}/quotes/{quote}/convert`. - [Create a quote presentation revision](https://docs.factuarea.com/api-reference/quotes/public-api.v1.quotes.revise_presentation): `POST /v1/companies/{company}/quotes/{quote}/presentation-revisions` — Append a derived capture using the authentic presentation_revision preview of the exact parent, target, policy and current source. Send the source token and preview fingerprint; a delivery or illustrative preview cannot authorize this action. Existing document state, fiscal numbering, references, instalments and totals remain intact. This action does not render, publish or send a PDF. Personal-data erasure is terminal. - [Delete a quote](https://docs.factuarea.com/api-reference/quotes/public-api.v1.quotes.delete): `DELETE /v1/companies/{company}/quotes/{quote}` — Delete a quote. Returns 422 if the quote has been converted to an invoice. - [Download quote PDF](https://docs.factuarea.com/api-reference/quotes/public-api.v1.quotes.pdf): `GET /v1/companies/{company}/quotes/{quote}/pdf` — Download the PDF representation of a quote. With the revisioned presentation active, a draft is served as a draft PDF (no capture, number or delivery evidence); a document that already left draft and has no retained presentation captures its original on the first download and serves it; one that is already captured serves that capture. - [Duplicate a quote](https://docs.factuarea.com/api-reference/quotes/public-api.v1.quotes.duplicate): `POST /v1/companies/{company}/quotes/{quote}/duplicate` — Create a new draft quote by copying the lines, client, and metadata from an existing quote. - [Find a quote by external ID](https://docs.factuarea.com/api-reference/quotes/public-api.v1.quotes.find_by_external_id): `POST /v1/companies/{company}/quotes/find-by-external-id` — Look up a single quote by its `external_id` (sent in the JSON body), the integration key that maps it to a record in a third-party system (ERP/CRM/e-commerce). Returns the matching quote or 404 `quote_not_found` if no quote uses that external_id within your company. - [Get quote stats](https://docs.factuarea.com/api-reference/quotes/public-api.v1.quotes.stats): `GET /v1/companies/{company}/quotes/stats` — Aggregated KPIs for the authenticated company: total quote count and amount, count per status, expired count, and converted count. Returned as `{ "data": QuoteStats }`. - [Get the quote presentation](https://docs.factuarea.com/api-reference/quotes/public-api.v1.quotes.get_presentation): `GET /v1/companies/{company}/quotes/{quote}/presentation` — Inspect the current visual selection and retained capture independently. Returns a virtual state before the first visual action. Reads never initialize templates, capture, publish, render or refresh legal content. - [List all quotes](https://docs.factuarea.com/api-reference/quotes/public-api.v1.quotes.list): `GET /v1/companies/{company}/quotes` — List your sales quotes with cursor-based pagination. Supports filtering by `status[in]`, `client_id`, `issued_on[gte|lte]`. - [List quote statuses](https://docs.factuarea.com/api-reference/quotes/public-api.v1.quotes.statuses): `GET /v1/companies/{company}/quotes/statuses` — Returns the canonical list of quote statuses available in the API along with their human-readable label and UI color. Useful for building dropdowns and filters. - [List retained quote presentations](https://docs.factuarea.com/api-reference/quotes/public-api.v1.quotes.list_presentations): `GET /v1/companies/{company}/quotes/{quote}/presentation-history` — Return page-based capture history in descending number. Each summary retains its own purpose, format and availability; capture metadata does not prove prepared PDF bytes. Privacy-erased rows remain metadata tombstones. - [Reject a quote](https://docs.factuarea.com/api-reference/quotes/public-api.v1.quotes.reject): `POST /v1/companies/{company}/quotes/{quote}/reject` — Mark a quote as rejected by the client. Sets `rejected_at` to the current timestamp. - [Retrieve a quote](https://docs.factuarea.com/api-reference/quotes/public-api.v1.quotes.show): `GET /v1/companies/{company}/quotes/{quote}` — Retrieve a sales quote by its `id`. - [Retrieve quote public link](https://docs.factuarea.com/api-reference/quotes/public-api.v1.quotes.public_link_get): `GET /v1/companies/{company}/quotes/{quote}/public-link` — Returns the shareable public URL of the quote along with its status, expiration, and the plan-allowed maximum extension days. - [Send quote by email](https://docs.factuarea.com/api-reference/quotes/public-api.v1.quotes.send): `POST /v1/companies/{company}/quotes/{quote}/send` — Send a quote to the client by email. - [Update a quote](https://docs.factuarea.com/api-reference/quotes/public-api.v1.quotes.update): `PATCH /v1/companies/{company}/quotes/{quote}` — Update a draft quote. Once accepted/rejected/converted, the quote becomes immutable. - [Update quote public link](https://docs.factuarea.com/api-reference/quotes/public-api.v1.quotes.public_link_update): `PATCH /v1/companies/{company}/quotes/{quote}/public-link` — Applies an action to the public link: `revoke`, `activate`, `extend` (with `extend_days`), or `reset` to the plan default. - [Accept a proforma](https://docs.factuarea.com/api-reference/proformas/public-api.v1.proformas.accept): `POST /v1/companies/{company}/proformas/{proforma}/accept` — Mark a proforma as accepted by the client. Returns 422 if the proforma is in a status that cannot transition to `accepted`. - [Assign the proforma visual template](https://docs.factuarea.com/api-reference/proformas/public-api.v1.proformas.assign_presentation): `PATCH /v1/companies/{company}/proformas/{proforma}/presentation` — Set an explicit tenant template or null inheritance without changing numbering, totals, references, payment terms or the existing capture. Supply the visual selection version and/or the strong validator from this exact presentation URI. A successful replay preserves the original result; current actor authority is still required. - [Bulk change proforma status](https://docs.factuarea.com/api-reference/proformas/public-api.v1.proformas.bulk_status): `POST /v1/companies/{company}/proformas/bulk-status` — Transition up to 50 proformas (by id) to a status from the closed set `[accepted, rejected]`, each through the document state guard. Returns a `BulkPartialSuccessResult`; proformas whose transition is rejected (not found or not transitionable) come back in `failures[]`. - [Bulk delete proformas](https://docs.factuarea.com/api-reference/proformas/public-api.v1.proformas.bulk_delete): `POST /v1/companies/{company}/proformas/bulk-delete` — Deletes up to 100 proformas in one call. Returns a `BulkPartialSuccessResult` with `total`, `successful` and `failed` counts plus a `failures` list (`id` + `error_code` + Spanish `error_message`) for each entry that could not be deleted. - [Bulk download proforma PDFs](https://docs.factuarea.com/api-reference/proformas/public-api.v1.proformas.bulk_pdf): `POST /v1/companies/{company}/proformas/bulk-pdf` — Packages the PDFs of up to 50 proformas (by id) into a single ZIP. Ids that are not found or have no generable PDF do not abort the request: the ZIP carries only the valid ones and the per-resource counts travel in the `X-Bulk-*` response headers. - [Bulk send proformas](https://docs.factuarea.com/api-reference/proformas/public-api.v1.proformas.bulk_send): `POST /v1/companies/{company}/proformas/bulk-send` — Sends up to 200 proformas by email (queued) in one call, reusing the single-send path per id. Returns a `BulkPartialSuccessResult` with `total`, `successful` and `failed` counts plus a `failures` list (`id` + `error_code` + Spanish `error_message`) for each proforma that could not be sent (not found, non-sendable status or no resolvable recipient). - [Convert proforma to invoice](https://docs.factuarea.com/api-reference/proformas/public-api.v1.proformas.convert): `POST /v1/companies/{company}/proformas/{proforma}/convert` — Convert a proforma into a final invoice. The new invoice references the source proforma; the proforma moves to status `converted`. - [Create a proforma](https://docs.factuarea.com/api-reference/proformas/public-api.v1.proformas.create): `POST /v1/companies/{company}/proformas` — Create a new proforma invoice in `draft` status. Proformas can later be converted to final invoices. - [Create a proforma presentation revision](https://docs.factuarea.com/api-reference/proformas/public-api.v1.proformas.revise_presentation): `POST /v1/companies/{company}/proformas/{proforma}/presentation-revisions` — Append a derived capture using the authentic presentation_revision preview of the exact parent, target, policy and current source. Send the source token and preview fingerprint; a delivery or illustrative preview cannot authorize this action. Existing document state, fiscal numbering, references, instalments and totals remain intact. This action does not render, publish or send a PDF. Personal-data erasure is terminal. - [Delete a proforma](https://docs.factuarea.com/api-reference/proformas/public-api.v1.proformas.delete): `DELETE /v1/companies/{company}/proformas/{proforma}` — Delete a proforma. Returns 422 if the proforma has been converted to an invoice. - [Download proforma PDF](https://docs.factuarea.com/api-reference/proformas/public-api.v1.proformas.pdf): `GET /v1/companies/{company}/proformas/{proforma}/pdf` — Download the PDF representation of a proforma. With the revisioned presentation active, a draft is served as a draft PDF (no capture, number or delivery evidence); a document that already left draft and has no retained presentation captures its original on the first download and serves it; one that is already captured serves that capture. - [Duplicate a proforma](https://docs.factuarea.com/api-reference/proformas/public-api.v1.proformas.duplicate): `POST /v1/companies/{company}/proformas/{proforma}/duplicate` — Create a new draft proforma by copying lines, client, and metadata from an existing proforma. - [Find a proforma by external ID](https://docs.factuarea.com/api-reference/proformas/public-api.v1.proformas.find_by_external_id): `POST /v1/companies/{company}/proformas/find-by-external-id` — Look up a single proforma by its `external_id` (sent in the JSON body), the integration key that maps it to a record in a third-party system (ERP/CRM/e-commerce). Returns the matching proforma or 404 `proforma_not_found` if no proforma uses that external_id within your company. - [Get proforma stats](https://docs.factuarea.com/api-reference/proformas/public-api.v1.proformas.stats): `GET /v1/companies/{company}/proformas/stats` — Aggregated KPIs for the authenticated company: total proforma count and amount, count per status, expired count, and count converted to invoice. Returned as `{ "data": ProformaStats }`. - [Get the proforma presentation](https://docs.factuarea.com/api-reference/proformas/public-api.v1.proformas.get_presentation): `GET /v1/companies/{company}/proformas/{proforma}/presentation` — Inspect the current visual selection and retained capture independently. Returns a virtual state before the first visual action. Reads never initialize templates, capture, publish, render or refresh legal content. - [List all proformas](https://docs.factuarea.com/api-reference/proformas/public-api.v1.proformas.list): `GET /v1/companies/{company}/proformas` — List your proforma invoices with cursor-based pagination. - [List proforma statuses](https://docs.factuarea.com/api-reference/proformas/public-api.v1.proformas.statuses): `GET /v1/companies/{company}/proformas/statuses` — Returns the closed catalog of proforma statuses with their public `value`, localized `label`, and UI `color`. Use it to populate filters or status pickers instead of hard-coding values. - [List retained proforma presentations](https://docs.factuarea.com/api-reference/proformas/public-api.v1.proformas.list_presentations): `GET /v1/companies/{company}/proformas/{proforma}/presentation-history` — Return page-based capture history in descending number. Each summary retains its own purpose, format and availability; capture metadata does not prove prepared PDF bytes. Privacy-erased rows remain metadata tombstones. - [Reject a proforma](https://docs.factuarea.com/api-reference/proformas/public-api.v1.proformas.reject): `POST /v1/companies/{company}/proformas/{proforma}/reject` — Mark a proforma as rejected by the client. Returns 422 if the proforma is in a status that cannot transition to `rejected`. - [Retrieve a proforma](https://docs.factuarea.com/api-reference/proformas/public-api.v1.proformas.show): `GET /v1/companies/{company}/proformas/{proforma}` — Retrieve a proforma invoice by its `id`. - [Retrieve proforma public link](https://docs.factuarea.com/api-reference/proformas/public-api.v1.proformas.public_link_get): `GET /v1/companies/{company}/proformas/{proforma}/public-link` — Returns the shareable public URL of the proforma along with its status, expiration, and the plan-allowed maximum extension days. - [Send proforma by email](https://docs.factuarea.com/api-reference/proformas/public-api.v1.proformas.send): `POST /v1/companies/{company}/proformas/{proforma}/send` — Send a proforma to the client by email. - [Update a proforma](https://docs.factuarea.com/api-reference/proformas/public-api.v1.proformas.update): `PATCH /v1/companies/{company}/proformas/{proforma}` — Update a draft proforma. Once converted, the proforma becomes immutable. - [Update proforma public link](https://docs.factuarea.com/api-reference/proformas/public-api.v1.proformas.public_link_update): `PATCH /v1/companies/{company}/proformas/{proforma}/public-link` — Applies an action to the public link: `revoke`, `activate`, `extend` (with `extend_days`), or `reset` to the plan default. - [Assign the delivery-note visual template](https://docs.factuarea.com/api-reference/delivery-notes/public-api.v1.delivery_notes.assign_presentation): `PATCH /v1/companies/{company}/delivery-notes/{delivery_note}/presentation` — Set an explicit tenant template or null inheritance without changing numbering, totals, references, payment terms or the existing capture. Supply the visual selection version and/or the strong validator from this exact presentation URI. A successful replay preserves the original result; current actor authority is still required. - [Bulk change delivery note status](https://docs.factuarea.com/api-reference/delivery-notes/public-api.v1.delivery_notes.bulk_status): `POST /v1/companies/{company}/delivery-notes/bulk-status` — Transition up to 50 delivery notes (by id) to a status from the closed set `[delivered, cancelled]`, each through the document state guard. Returns a `BulkPartialSuccessResult`; delivery notes whose transition is rejected (not found or not transitionable) come back in `failures[]`. - [Bulk delete delivery notes](https://docs.factuarea.com/api-reference/delivery-notes/public-api.v1.delivery_notes.bulk_delete): `POST /v1/companies/{company}/delivery-notes/bulk-delete` — Delete several delivery notes in one request: `ids` array of UUID v7. - Returns a `BulkPartialSuccessResult`; `failures` list the notes not deleted (e.g. signed or invoiced). - Supports `Idempotency-Key`. - [Bulk download delivery note PDFs](https://docs.factuarea.com/api-reference/delivery-notes/public-api.v1.delivery_notes.bulk_pdf): `POST /v1/companies/{company}/delivery-notes/bulk-pdf` — Packages the PDFs of up to 50 delivery notes (by id) into a single ZIP. Ids that are not found or have no generable PDF do not abort the request: the ZIP carries only the valid ones and the per-resource counts travel in the `X-Bulk-*` response headers. - [Bulk send delivery notes](https://docs.factuarea.com/api-reference/delivery-notes/public-api.v1.delivery_notes.bulk_send): `POST /v1/companies/{company}/delivery-notes/bulk-send` — Sends up to 200 delivery notes by email (queued) in one call, reusing the single-send path per id. Returns a `BulkPartialSuccessResult` with `total`, `successful` and `failed` counts plus a `failures` list (`id` + `error_code` + Spanish `error_message`) for each delivery note that could not be sent (not found, non-sendable status or no resolvable recipient). - [Cancel a delivery note](https://docs.factuarea.com/api-reference/delivery-notes/public-api.v1.delivery_notes.cancel): `POST /v1/companies/{company}/delivery-notes/{delivery_note}/cancel` — Transition a delivery note to the `cancelled` state. Canonical REST replacement for the deprecated `POST /change_status`. Returns 409 `invalid_status_transition` if the note cannot be cancelled (e.g. already invoiced). Supports `Idempotency-Key` for safe retries. - [Convert delivery note to invoice](https://docs.factuarea.com/api-reference/delivery-notes/public-api.v1.delivery_notes.convert): `POST /v1/companies/{company}/delivery-notes/{delivery_note}/convert` — Convert a delivery note into an invoice. The delivery note moves to `invoiced` with `converted_to_id` populated and the new invoice is returned under `data`. Only `target=invoice` is supported. - [Create a delivery note](https://docs.factuarea.com/api-reference/delivery-notes/public-api.v1.delivery_notes.create): `POST /v1/companies/{company}/delivery-notes` — Create a new delivery note (albarán) in `draft` status. Delivery notes track goods shipped to a customer and can later be converted to invoices. - [Create a delivery-note presentation revision](https://docs.factuarea.com/api-reference/delivery-notes/public-api.v1.delivery_notes.revise_presentation): `POST /v1/companies/{company}/delivery-notes/{delivery_note}/presentation-revisions` — Append a derived capture using the authentic presentation_revision preview of the exact parent, target, policy and current source. Send the source token and preview fingerprint; a delivery or illustrative preview cannot authorize this action. Existing document state, fiscal numbering, references, instalments and totals remain intact. This action does not render, publish or send a PDF. Personal-data erasure is terminal. - [Delete a delivery note](https://docs.factuarea.com/api-reference/delivery-notes/public-api.v1.delivery_notes.delete): `DELETE /v1/companies/{company}/delivery-notes/{delivery_note}` — Delete a delivery note. Only `draft` notes without an assigned number can be deleted; any other state returns 409 `invalid_status_transition`. - [Download delivery note PDF](https://docs.factuarea.com/api-reference/delivery-notes/public-api.v1.delivery_notes.pdf): `GET /v1/companies/{company}/delivery-notes/{delivery_note}/pdf` — Download the delivery note PDF as a binary stream (`application/pdf`); `?download=1` serves it as an attachment. - The `ETag` revalidates with `If-None-Match` (304 when unchanged). - With revisioned presentation, a draft is served as a draft PDF; a document that left draft without a retained presentation captures its original on the first download, and a captured one serves that capture. - [Duplicate a delivery note](https://docs.factuarea.com/api-reference/delivery-notes/public-api.v1.delivery_notes.duplicate): `POST /v1/companies/{company}/delivery-notes/{delivery_note}/duplicate` — Create a new draft delivery note by copying lines, client, and metadata. - [Find a delivery note by external ID](https://docs.factuarea.com/api-reference/delivery-notes/public-api.v1.delivery_notes.find_by_external_id): `POST /v1/companies/{company}/delivery-notes/find-by-external-id` — Look up a single delivery note by its `external_id` (sent in the JSON body), the integration key that maps it to a record in a third-party system (ERP/CRM/e-commerce). Returns the matching delivery note or 404 `delivery_note_not_found` if no delivery note uses that external_id within your company. - [Forget delivery note signature PII](https://docs.factuarea.com/api-reference/delivery-notes/public-api.v1.delivery_notes.signature_audits.forget): `POST /v1/companies/{company}/delivery-notes/signature-audits/{auditId}/forget` — GDPR Art. 17 (right to erasure) — remove the personal data (recipient name/DNI) from a signature audit log entry while preserving the non-PII audit trail required for LSSI-CE compliance. The `{auditId}` is the UUID of the signature audit record; a numeric id answers 404. - [Get the delivery-note presentation](https://docs.factuarea.com/api-reference/delivery-notes/public-api.v1.delivery_notes.get_presentation): `GET /v1/companies/{company}/delivery-notes/{delivery_note}/presentation` — Inspect the current visual selection and retained capture independently. Returns a virtual state before the first visual action. Reads never initialize templates, capture, publish, render or refresh legal content. - [List all delivery notes](https://docs.factuarea.com/api-reference/delivery-notes/public-api.v1.delivery_notes.list): `GET /v1/companies/{company}/delivery-notes` — List your delivery notes with cursor-based pagination. - [List delivery note statuses](https://docs.factuarea.com/api-reference/delivery-notes/public-api.v1.delivery_notes.statuses): `GET /v1/companies/{company}/delivery-notes/statuses` — List the closed catalog of delivery note statuses (`draft`, `delivered`, `invoiced`, `cancelled`) with their public labels and colors. Use it to populate filters or status pickers instead of hard-coding values. The response `data` is an array of `{ value, label, color }` items. - [List retained delivery-note presentations](https://docs.factuarea.com/api-reference/delivery-notes/public-api.v1.delivery_notes.list_presentations): `GET /v1/companies/{company}/delivery-notes/{delivery_note}/presentation-history` — Return page-based capture history in descending number. Each summary retains its own purpose, format and availability; capture metadata does not prove prepared PDF bytes. Privacy-erased rows remain metadata tombstones. - [Mark delivery note as delivered](https://docs.factuarea.com/api-reference/delivery-notes/public-api.v1.delivery_notes.mark_delivered): `POST /v1/companies/{company}/delivery-notes/{delivery_note}/mark-delivered` — Transition a delivery note to the `delivered` state (public `sent`). Canonical REST replacement for the deprecated `POST /change_status`. Returns 409 `invalid_status_transition` if the note cannot transition. Supports `Idempotency-Key` for safe retries. - [Retrieve a delivery note](https://docs.factuarea.com/api-reference/delivery-notes/public-api.v1.delivery_notes.show): `GET /v1/companies/{company}/delivery-notes/{delivery_note}` — Retrieve a delivery note by its `id`. - [Retrieve a delivery note public link](https://docs.factuarea.com/api-reference/delivery-notes/public-api.v1.delivery_notes.public_link.get): `GET /v1/companies/{company}/delivery-notes/{delivery_note}/public-link` — Return the public share link state of a delivery note: `url` (absolute, ready to send to the client), `enabled`, `expires_at` (`null` = unlimited), and `max_days` (plan-enforced maximum when extending the link). - [Retrieve delivery note stats](https://docs.factuarea.com/api-reference/delivery-notes/public-api.v1.delivery_notes.stats): `GET /v1/companies/{company}/delivery-notes/stats` — Return aggregated KPIs for your delivery notes: total count, accumulated amount, per-status breakdown, count pending signature, and count converted to invoice this month. - [Send a delivery note](https://docs.factuarea.com/api-reference/delivery-notes/public-api.v1.delivery_notes.send): `POST /v1/companies/{company}/delivery-notes/{delivery_note}/send` — Send a delivery note to the client by email. Uses the email on file unless overridden in the payload. - [Sign a delivery note](https://docs.factuarea.com/api-reference/delivery-notes/public-api.v1.delivery_notes.sign): `POST /v1/companies/{company}/delivery-notes/{delivery_note}/sign` — Record a handwritten signature on a delivery note: base64 PNG up to 2 MB, other formats return 422. - `signed_by` (up to 120 characters) is required; the server sets the signature time and ignores the deprecated `signed_at`. The status does not change. - The optional presentation context (`expected_*`) is all-or-nothing and requires an `Idempotency-Key`. - The audit log keeps hashed PII for 5 years; erase it via `signature-audits/{auditId}/forget`. - [Update a delivery note](https://docs.factuarea.com/api-reference/delivery-notes/public-api.v1.delivery_notes.update): `PATCH /v1/companies/{company}/delivery-notes/{delivery_note}` — Update a draft delivery note. Once signed or invoiced, the delivery note becomes immutable. - [Update a delivery note public link](https://docs.factuarea.com/api-reference/delivery-notes/public-api.v1.delivery_notes.public_link.update): `PATCH /v1/companies/{company}/delivery-notes/{delivery_note}/public-link` — Enable/disable the public share link of a delivery note or change its expiry. Returns 422 `expiry_exceeds_max_days` if the requested expiry exceeds the plan-enforced `max_days`. Supports `Idempotency-Key` for safe retries. - [Activate recurring invoice](https://docs.factuarea.com/api-reference/recurring-invoices/public-api.v1.recurring_invoices.activate): `POST /v1/companies/{company}/recurring-invoices/{recurring_invoice}/activate` — Activate a paused recurring invoice. The next invoice will be generated according to the schedule. This is a semantic alias of `POST /companies/{company}/recurring-invoices/{recurring_invoice}/resume` — both behave identically; neither is deprecated. - [Bulk change recurring invoice status](https://docs.factuarea.com/api-reference/recurring-invoices/public-api.v1.recurring_invoices.bulk_status): `POST /v1/companies/{company}/recurring-invoices/bulk-status` — Moves up to 50 recurring invoices (by id) to `active` or `paused`, each through the same transition as `pause` and `resume`. - Returns a `BulkPartialSuccessResult`; the batch never aborts. - Not found, already in target status, cancelled or exhausted ids come back in `failures[]` with `error_code`. - [Bulk delete recurring invoices](https://docs.factuarea.com/api-reference/recurring-invoices/public-api.v1.recurring_invoices.bulk-delete): `POST /v1/companies/{company}/recurring-invoices/bulk-delete` — Delete multiple recurring invoices in a single request (POST with a body of `ids`). Returns the count of deleted resources and a list of failures with their reason. Recurring invoices that already generated invoices cannot be deleted. - [Cancel recurring invoice](https://docs.factuarea.com/api-reference/recurring-invoices/public-api.v1.recurring_invoices.cancel): `POST /v1/companies/{company}/recurring-invoices/{recurring_invoice}/cancel` — Cancel a recurring invoice. Unlike `pause`, this is a terminal, irreversible state: a cancelled recurring invoice can never be resumed or reactivated. Previously generated invoices are unaffected. - [Create a recurring invoice](https://docs.factuarea.com/api-reference/recurring-invoices/public-api.v1.recurring_invoices.create): `POST /v1/companies/{company}/recurring-invoices` — Create a recurring invoice template that auto-generates invoices on a fixed cadence (weekly, monthly, quarterly, yearly). - [Delete a recurring invoice](https://docs.factuarea.com/api-reference/recurring-invoices/public-api.v1.recurring_invoices.delete): `DELETE /v1/companies/{company}/recurring-invoices/{recurring_invoice}` — Delete a recurring invoice template. Future invoices stop being generated; existing invoices remain. - [Find a recurring invoice by external ID](https://docs.factuarea.com/api-reference/recurring-invoices/public-api.v1.recurring_invoices.find_by_external_id): `POST /v1/companies/{company}/recurring-invoices/find-by-external-id` — Look up a single recurring invoice template by its `external_id` (sent in the JSON body), the integration key that maps it to a record in a third-party system (ERP/CRM/e-commerce). Returns the matching recurring invoice or 404 `recurring_invoice_not_found` if none uses that external_id within your company. - [Generate an invoice from a recurring template](https://docs.factuarea.com/api-reference/recurring-invoices/public-api.v1.recurring_invoices.generate): `POST /v1/companies/{company}/recurring-invoices/{recurring_invoice}/generate` — Trigger immediate invoice generation from the recurring configuration, outside the scheduled cycle. The server fixes generation date and attempt identity. No public date/child/intent overrides are accepted. Current authority precedes idempotent replay; retained same-day success is returned before new presentation selection. - [List all recurring invoices](https://docs.factuarea.com/api-reference/recurring-invoices/public-api.v1.recurring_invoices.list): `GET /v1/companies/{company}/recurring-invoices` — List your recurring invoice templates with cursor-based pagination. - [List recurring invoice activity](https://docs.factuarea.com/api-reference/recurring-invoices/public-api.v1.recurring_invoices.activities): `GET /v1/companies/{company}/recurring-invoices/{recurring_invoice}/activities` — Return the cursor-paginated activity timeline (domain events: activation, pause, resume, generation, failure, cancellation, etc.) for a recurring invoice. Metadata is sanitized to never expose internal identifiers. - [List recurring invoice execution logs](https://docs.factuarea.com/api-reference/recurring-invoices/public-api.v1.recurring_invoices.logs): `GET /v1/companies/{company}/recurring-invoices/{recurring_invoice}/logs` — Return paginated history of generations, failures and other events for this recurring template. - [Pause recurring invoice](https://docs.factuarea.com/api-reference/recurring-invoices/public-api.v1.recurring_invoices.pause): `POST /v1/companies/{company}/recurring-invoices/{recurring_invoice}/pause` — Pause a recurring invoice. No new invoices will be generated until resumed. Reversible — use `resume`/`activate` to reactivate. For a permanent, irreversible stop use `cancel`. - [Preview upcoming recurring invoice dates](https://docs.factuarea.com/api-reference/recurring-invoices/public-api.v1.recurring_invoices.preview): `GET /v1/companies/{company}/recurring-invoices/{recurring_invoice}/preview` — Return the next scheduled run dates with their due dates and estimated totals. Defaults to 5 occurrences. - [Resume recurring invoice](https://docs.factuarea.com/api-reference/recurring-invoices/public-api.v1.recurring_invoices.resume): `POST /v1/companies/{company}/recurring-invoices/{recurring_invoice}/resume` — Resume a paused recurring invoice. This is a semantic alias of `POST /companies/{company}/recurring-invoices/{recurring_invoice}/activate` — both behave identically; neither is deprecated. - [Retrieve a recurring invoice](https://docs.factuarea.com/api-reference/recurring-invoices/public-api.v1.recurring_invoices.show): `GET /v1/companies/{company}/recurring-invoices/{recurring_invoice}` — Retrieve a recurring invoice template by its `id`. - [Retrieve recurring invoice stats](https://docs.factuarea.com/api-reference/recurring-invoices/public-api.v1.recurring_invoices.stats): `GET /v1/companies/{company}/recurring-invoices/stats` — Aggregate KPIs for your recurring invoices: counts by status, due today / this week, generated and failed this month, breakdown by frequency, next scheduled runs and estimated revenue this month. - [Skip the next recurring invoice generation](https://docs.factuarea.com/api-reference/recurring-invoices/public-api.v1.recurring_invoices.skip): `POST /v1/companies/{company}/recurring-invoices/{recurring_invoice}/skip` — Advance the recurring invoice to its following scheduled run without generating an invoice for the current cycle. The skipped occurrence is not counted against any occurrence limit. Cancelled or completed recurring invoices return 422. - [Update a recurring invoice](https://docs.factuarea.com/api-reference/recurring-invoices/public-api.v1.recurring_invoices.update): `PATCH /v1/companies/{company}/recurring-invoices/{recurring_invoice}` — Partially update a recurring invoice template: every field is optional and an omitted one keeps its current value; `lines`, when sent, replaces the whole set of lines. The cadence and lines apply to invoices generated after the update; previously generated invoices are unaffected. ## API Reference — Purchases - [Attach a file to an expense](https://docs.factuarea.com/api-reference/purchase-invoices/public-api.v1.purchase_invoices.attach_file): `POST /v1/companies/{company}/purchase-invoices/{purchase_invoice}/attach-file` — Upload the original PDF document for an expense as `multipart/form-data`. Replaces any previously attached file. Returns the updated expense. - [Bulk change expense status](https://docs.factuarea.com/api-reference/purchase-invoices/public-api.v1.purchase_invoices.bulk_status): `POST /v1/companies/{company}/purchase-invoices/bulk-status` — Transition up to 50 expenses (by id) to `paid` in one call, each through the document state guard. The required `payment_date` is propagated as-is to every expense (never `now()`). Returns a `BulkPartialSuccessResult`; expenses that could not transition (not found or already paid) come back in `failures[]`. - [Bulk delete expenses](https://docs.factuarea.com/api-reference/purchase-invoices/public-api.v1.purchase_invoices.bulk_delete): `POST /v1/companies/{company}/purchase-invoices/bulk-delete` — Delete up to 100 expenses by UUID in a single request. Returns a `BulkPartialSuccessResult` with `total`, `successful` and `failed` counts plus a `failures` list (`id` + `error_code` + Spanish `error_message`) for each entry that could not be deleted. - [Create an expense](https://docs.factuarea.com/api-reference/purchase-invoices/public-api.v1.purchase_invoices.create): `POST /v1/companies/{company}/purchase-invoices` — Record an invoice received from a supplier. - With `supplier_offer_id`, cost, purchase unit and base conversion are frozen; `unit_price` is optional. - `pending` registers inbound stock once; `draft` leaves stock untouched until marked as paid. - [Delete an expense](https://docs.factuarea.com/api-reference/purchase-invoices/public-api.v1.purchase_invoices.delete): `DELETE /v1/companies/{company}/purchase-invoices/{purchase_invoice}` — Delete an expense. - [Download the original expense file](https://docs.factuarea.com/api-reference/purchase-invoices/public-api.v1.purchase_invoices.file): `GET /v1/companies/{company}/purchase-invoices/{purchase_invoice}/file` — Stream the original file attached to the expense when it was uploaded — a PDF or a scanned image (`image/jpeg`, `image/png`), the formats accepted on upload. Returns 404 if no attachment is present. - [Download the receipt PDF of an expense payment](https://docs.factuarea.com/api-reference/purchase-invoices/public-api.v1.purchase_invoices.payment_receipt): `GET /v1/companies/{company}/purchase-invoices/{purchase_invoice}/payment-receipt` — Stream the PDF receipt of one payment of an expense, partial payments included. - Without `payment_id`, returns the receipt of the most recent active payment. - Returns 422 without active payments or if reversed; 404 if the expense or `payment_id` is unknown. - [Find an expense by external ID](https://docs.factuarea.com/api-reference/purchase-invoices/public-api.v1.purchase_invoices.find_by_external_id): `POST /v1/companies/{company}/purchase-invoices/find-by-external-id` — Look up a single expense by its `external_id` (sent in the JSON body), the integration key that maps it to a record in a third-party system (ERP/CRM/e-commerce). Orthogonal to the supplier-provided `external_invoice_number` (the vendor's fiscal number). Returns the matching expense or 404 `purchase_invoice_not_found` if none uses that external_id within your company. - [Get expense stats](https://docs.factuarea.com/api-reference/purchase-invoices/public-api.v1.purchase_invoices.stats): `GET /v1/companies/{company}/purchase-invoices/stats` — Aggregated KPIs for your expenses: total count and amount, counts per status, pending and overdue totals, and amounts by supplier. Returned as `{ "data": PurchaseInvoiceStats }`. - [List all expenses](https://docs.factuarea.com/api-reference/purchase-invoices/public-api.v1.purchase_invoices.list): `GET /v1/companies/{company}/purchase-invoices` — List expenses recorded from suppliers with cursor-based pagination. - [List expense categories](https://docs.factuarea.com/api-reference/purchase-invoices/public-api.v1.purchase_invoices.expense_categories): `GET /v1/companies/{company}/purchase-invoices/expense-categories` — List the expense categories available to your company. Use the returned `id` as the scanner review field `expense_category`. The complete catalog is returned in `data`, without pagination. - [List expense payments](https://docs.factuarea.com/api-reference/purchase-invoices/public-api.v1.purchase_invoices.list_payments): `GET /v1/companies/{company}/purchase-invoices/{purchase_invoice}/payments` — Return the full payment ledger of an expense as `{ "data": [...] }`, ordered by payment date descending. The ledger of a single expense is bounded, so the complete set is returned without cursor pagination. An expense with no payments returns an empty array, never a `404`; a `404` here means the expense does not exist or belongs to another company. - [List overdue expenses](https://docs.factuarea.com/api-reference/purchase-invoices/public-api.v1.purchase_invoices.overdue): `GET /v1/companies/{company}/purchase-invoices/overdue` — Return expenses whose due date has passed and are still unpaid. - [List pending expenses](https://docs.factuarea.com/api-reference/purchase-invoices/public-api.v1.purchase_invoices.pending): `GET /v1/companies/{company}/purchase-invoices/pending` — Return expenses in pending payment status, paginated. - [Mark expense as paid](https://docs.factuarea.com/api-reference/purchase-invoices/public-api.v1.purchase_invoices.mark_paid): `POST /v1/companies/{company}/purchase-invoices/{purchase_invoice}/mark-paid` — Record payment of an expense, using the optional `paid_on` date (defaults to today, never later than today). - A draft expense with stock-managed lines registers its inbound stock exactly once on this transition. - A pending expense already registered it, so marking it paid never duplicates stock. - [Register an expense payment](https://docs.factuarea.com/api-reference/purchase-invoices/public-api.v1.purchase_invoices.register_payment): `POST /v1/companies/{company}/purchase-invoices/{purchase_invoice}/payments` — Record a partial or total payment against an expense and append it to its ledger; returns `201` with a `Location` header. - Returns `422` if amount is zero or above the balance, `paid_on` is future, or the expense is cancelled. - When payments cover the total the expense settles on its own; no `mark_paid` call is needed. - [Remove an expense file](https://docs.factuarea.com/api-reference/purchase-invoices/public-api.v1.purchase_invoices.delete_file): `DELETE /v1/companies/{company}/purchase-invoices/{purchase_invoice}/file` — Delete the original file attached to an expense and release its storage. Idempotent: succeeds even when no file was attached. - [Retrieve an expense](https://docs.factuarea.com/api-reference/purchase-invoices/public-api.v1.purchase_invoices.show): `GET /v1/companies/{company}/purchase-invoices/{purchase_invoice}` — Retrieve an expense by its `id`. - [Update an expense](https://docs.factuarea.com/api-reference/purchase-invoices/public-api.v1.purchase_invoices.update): `PATCH /v1/companies/{company}/purchase-invoices/{purchase_invoice}` — Update an expense. ## Migrating from other platforms - [Migrate from Holded](https://docs.factuarea.com/guides/migration-from-holded): Holded → Factuarea resource mapping, naming, equivalent endpoints and Python script. ## Optional - [A receipt for every payment](https://docs.factuarea.com/changelog/payment-receipts-per-payment): Payment receipts are issued per payment, partial payments included: the receipt operations of invoices and expenses accept an optional payment_id, and their MCP tools return the receipt number. Document PDFs show the issuer's IBAN only with bank payment methods and use a 9 pt base size by default. Two operations and two MCP tools updated. - [A terminated employee is read-only](https://docs.factuarea.com/changelog/terminated-employees-read-only): Clocking in, assigning a schedule or an absence policy, approving an absence that runs past the termination date and inviting a terminated employee to the portal now return 422 with the employee_inactive subcode. The team summary lists every employee employed during the month, with or without a schedule. - [Account contract adjustments](https://docs.factuarea.com/changelog/account-contract-adjustments): Fixes to the v1 contract after the review of 6 October, durable purchases moved to the company axis, and the final shape of managed accounts, additional tax IDs and the user cap. - [Account model](https://docs.factuarea.com/changelog/account-model): Accounts, tax IDs, members, granted access, managed accounts, bulk import, account webhooks and the operations and fields they add or rename. - [Account usage: generic error message](https://docs.factuarea.com/changelog/storage-quota-generic-message): The storage_quota_exceeded message and guidance now direct you to support without usage figures. - [Active automation rule limit](https://docs.factuarea.com/changelog/automation-active-rules-cap): The active-rule cap, the activation error and active_rules usage in API and MCP. - [Advance payments and payment date validation](https://docs.factuarea.com/changelog/payment-date-advance-payments): A payment date earlier than the issue date is now accepted as an advance payment, and a payment date later than today answers 422. It applies to sales and expenses, to marking as paid and to registering a payment. - [Annual document limit across API and MCP](https://docs.factuarea.com/changelog/document-annual-quota): The annual document limit, the affected API operations (14 in total), MCP errors and automatic issuance. - [API and MCP included in every plan](https://docs.factuarea.com/changelog/api-included-in-plans): Public API and MCP access are included in every Factuarea plan. Request limits follow the active plan and access is also available during the trial. - [Automations](https://docs.factuarea.com/changelog/automations): Build event-driven rules, preview their effects and inspect each execution. Eighteen operations cover rules, versions, runs, replay and usage. - [Bulk-send MCP tools now enforce the 200-id batch limit](https://docs.factuarea.com/changelog/mcp-bulk-send-limit): MCP bulk-send tools now reject batches larger than 200 IDs with a clear error. REST behavior is unchanged. - [Canonical contacts API](https://docs.factuarea.com/changelog/canonical-contacts): Manage one identity with cumulative customer, supplier and lead roles. The canonical API now covers bulk creation and archival, direct identifier lookup, AEAT census verification, statistics, activity and imports. - [Company-owned taxes](https://docs.factuarea.com/changelog/company-taxes): Create, edit and delete your own taxes next to the read-only Factuarea catalog, tell them apart with the new ownership field, and set defaults for your company only. Two new MCP tools, a new OAuth scope and two new error codes. - [Complete product catalog and price-list coverage](https://docs.factuarea.com/changelog/catalog-price-lists): Manage product presentations, variants, supplier offers and price lists. Documents keep price snapshots and make repricing explicit. - [Configurable catalog selections and exact prices](https://docs.factuarea.com/changelog/catalog-selections): Configure which product combinations can be sold and resolve exact negotiated prices. The API adds selection lookup, stock auditing and bulk price resolution. - [Configurable note on automatic invoices](https://docs.factuarea.com/changelog/automatic-invoice-note): Connected accounts and stores accept an invoice_note that Factuarea writes in the notes of the invoices it issues automatically, and those invoices are due 30 days after issue by default. Seven updated operations and two updated MCP tools. - [Contact import tracking and reliable row results](https://docs.factuarea.com/changelog/contact-import-integrity-and-tracking): Preview contact files, track confirmed row results and download authorized error reports. - [Contracted seats, offer packages and the trial](https://docs.factuarea.com/changelog/contracted-seats-offers-and-trial): The bill follows the seats you contract: creating an employee takes a free seat, reducing takes effect at renewal with no credit and you choose who is deactivated. Four new operations set and preview the seats, the REST API and MCP buy the missing seats on their own, offer packages keep their prices while their minimums hold, and the trial answers its own reason. - [Control document templates have their own kind](https://docs.factuarea.com/changelog/transport-control-templates): PDF templates and their revisions report document_kind (commercial or transport-document). Create and duplicate accept it, the list filters by it, and the control documents default in PATCH /v1/companies/{company}/pdf-templates/defaults only accepts templates of the transport-document kind. - [Control documents use the PDF template library](https://docs.factuarea.com/changelog/transport-document-pdf-templates): The PDF of the transport control document (DeCA) takes its design from the template library. New control documents default in PATCH /v1/companies/{company}/pdf-templates/defaults and in the MCP tool, and every version of the DeCA reports the design it was painted with in versions[].presentation. - [Counted units, weight by pieces and base unit replacement](https://docs.factuarea.com/changelog/product-units-and-base-unit-change): Sell in packs, boxes or pieces over a product measured in kilos or litres, record the pieces on variable-weight lines, replace a product by one with a different base unit with a preview and an irreversible execution, and read the real unit in FacturaE and UBL. Two new operations, two MCP tools, the product.replaced event and new fields on products and document lines. - [Delete and archive contacts](https://docs.factuarea.com/changelog/contact-delete-and-archive): Breaking change: DELETE /v1/contacts/{id} and POST /v1/contacts/bulk-delete now delete instead of archiving, and the deletion cannot be undone through the API. Archiving moves to POST /v1/contacts/{id}/archive, is always allowed and stays reversible. A contact.deleted webhook event is published and the contact_has_commercial_references subcode disappears. - [Edit numbering series](https://docs.factuarea.com/changelog/series-update): Update a series with PUT /v1/series/{series} and the MCP tool update_series, under the same fiscal guards as the web app. - [Email each automatic invoice to the payer](https://docs.factuarea.com/changelog/stripe-email-invoice-to-payer): Connected Stripe accounts accept email_invoice_to_payer, which emails every invoice Factuarea issues automatically to the address that comes with the charge. Three updated operations and one updated MCP tool. - [Employee batches and private seat offers](https://docs.factuarea.com/changelog/durable-customer-purchases): New durable operations for employee batches and company-specific employee or managed-company seat offers. - [Employee seats charged whenever the plan bills](https://docs.factuarea.com/changelog/employee-seat-charges): Creating or reactivating an employee charges a seat whenever the plan bills, including past_due and granted plans; trial employees are deactivated when billing starts, a new 503 applies when batches are enabled, and seat offers on an active subscription start at the next renewal. Eight updated operations. - [Exemption cause coherence and recurring generation conflict](https://docs.factuarea.com/changelog/exemption-cause-coherence-and-recurring-conflict): Three operations change: the invoice preview accepts an optional exemption_reason, saving or issuing an invoice with a VAT-free header cause and taxed lines answers 422 exemption_cause_contradicts_taxed_lines, and generating a recurring invoice can answer a retryable 409 recurring_presentation_activation_changed. - [Existing Stripe accounts and charge rules](https://docs.factuarea.com/changelog/stripe-existing-accounts-and-charge-rules): Connect a Stripe account you already have, decide per account which charges are invoiced and which are not, and read the charges that were left out. Six new operations, three new fields on connected accounts and five new inbox reasons. - [Expenses and Invoices: new product names](https://docs.factuarea.com/changelog/invoice-product-terminology): Purchase invoices are now Expenses and sales invoices are Invoices. Existing integrations keep the same interfaces. - [Fill in contact templates before importing](https://docs.factuarea.com/changelog/contact-import-template-roundtrip): Preview empty templates with their columns intact and handle empty_import before applying an import. - [Import results, task import retries and new read fields](https://docs.factuarea.com/changelog/import-tracking-and-task-idempotency): Contact imports report updated rows, warnings and why each row was skipped; task imports retry safely; invoices expose origin; quotes and proformas expose operation_regime. - [Invoice activity: AEAT results, email and payments](https://docs.factuarea.com/changelog/invoice-activity-events): The invoice activity timeline adds the result of every AEAT submission, undelivered emails, the first daily visit to the public link and payment events, each with an exact metadata contract. - [Issued is not sent: API version 2026-10-01](https://docs.factuarea.com/changelog/invoice-issued-vocabulary): Invoices separate issuing from delivering. Opt-in version 2026-10-01 publishes status issued with issued_at, is_sent and sent_via; new POST /v1/invoices/{invoice}/issue; mark-sent records a manual delivery from that version on; new events invoice.issued, invoice.marked_sent and invoice.unsent, with invoice.sent kept as a deprecated alias; webhook payloads versioned per endpoint; recurring invoices gain generation_mode. The default version does not change. - [Layout options for PDF templates](https://docs.factuarea.com/changelog/pdf-template-layout-options): PDF template configuration gains the schema_version 2 keys: header layout and logo side, lines table style and concept, legal footer, page density, font size per zone, highlight and surface colors, privacy text, general terms, optional block titles, the xl brand size and the total with tax column. Revisions report schema_version. - [Legal name and trade name of a company](https://docs.factuarea.com/changelog/company-legal-and-trade-name): name is the name a company is known by and business_name its legal name when it differs. Responses now follow that contract for every company, partial updates resolve against the current names and both fields accept up to 100 characters. - [MCP: clearer errors, ChatGPT sign-in and steadier tool lists](https://docs.factuarea.com/changelog/mcp-real-clients-compatibility): MCP tools report business errors again, OAuth accepts private_key_jwt for clients like ChatGPT, tools/list cursors last 24 hours and four old contact tool names are retired on 15 November 2026. - [Measured purchase lines](https://docs.factuarea.com/changelog/purchase-measurements): Purchase invoice lines now record the packages received, the unit the supplier cost applies to and the real measured quantity. The contract adds a measurement block, persists line discounts, resolves the cost from the supplier offer and duplicates a purchase from an authorised source. - [OAuth consent: account, level and permissions no longer granted](https://docs.factuarea.com/changelog/mcp-consent-account-and-level): The MCP consent screen asks you to choose an account and a company, does not grant write access with View level or the permissions of modules blocked in Test, and the request expires after 5 minutes. - [One breaking window: axis and payload](https://docs.factuarea.com/changelog/axis-and-payload-breaking-window): Company and account resources move into the URL, amounts travel as decimal strings, the collection date is renamed, X-Active-Profile is rejected and the account becomes the customer. Every operation the window touches — 519 of them — listed resource by resource. - [Packs and a common storefront for products](https://docs.factuarea.com/changelog/packs-and-storefront): Packs get their own API with images and a web view, products can be published to the web with prices with and without VAT, and invoices accept pack lines with the price charged. - [Pause and resume recurring invoices in bulk](https://docs.factuarea.com/changelog/recurring-invoice-bulk-status): New operation POST /v1/recurring_invoices/bulk-status moves up to 50 recurring invoices to active or paused with partial success, mirrored by the MCP tool bulk_change_recurring_invoice_status. Resuming a completed recurrence now answers 422 recurring_invoice_completed_cannot_resume. - [Payment reversal](https://docs.factuarea.com/changelog/payment-reversal): Reverse a payment while preserving the original record and its audit trail. The invoice balance reflects the reversal and integrations receive the corresponding event. - [PDF capabilities on the account](https://docs.factuarea.com/changelog/pdf-capabilities): The Account resource and the templates endpoint expose a read-only capabilities block: what the plan allows in document branding, which templates can be set and which plan unlocks the editor. Personalization updates outside the plan now return 403. - [PDF template library and structured invoices](https://docs.factuarea.com/changelog/document-templates-and-structured-invoices): Manage PDF templates and brand identities, choose the presentation of each document, prepare exact PDF artifacts, and carry payment schedules, references and DIR3 centres on invoices. Fifty new operations, the pdf_templates scopes and a pdf_output_state block on every document. - [People with operate access can be assigned tasks](https://docs.factuarea.com/changelog/tasks-people-from-granted-access): The user list and the current user now include people of other accounts who reach the company with operate access, and a task can be assigned to them. Three updated operations; no field changes. - [Personalization applies to the main template](https://docs.factuarea.com/changelog/personalization-main-template): For companies already on the PDF template library, PATCH /v1/companies/{company}/personalization and update_account_personalization apply the design and accent color to the main template, and personalization reads its effective values. The contract does not change; the new error is 409 pdf_main_template_required. - [Plan ladder: Esencial, Profesional, Avanzado and Enterprise](https://docs.factuarea.com/changelog/plan-ladder): New commercial names and Avanzado in the account contract, with API capacity included in each plan. - [Platform launch](https://docs.factuarea.com/changelog/platform-launch): The public platform brings together REST API v1, official TypeScript and PHP SDKs, the CLI and MCP, with an isolated sandbox for testing integrations. - [Projects and tasks](https://docs.factuarea.com/changelog/tasks): The task module reaches the API: projects with their board, tasks, labels, timers, users, notifications and the agenda — 80 new endpoints, 21 events, 80 MCP tools and four automation actions. - [Promotions and previous price](https://docs.factuarea.com/changelog/promotions): Put products and packs on offer with dates and channels. Reads expose the offer and the legal previous price, and price resolution takes a date, a channel and the customer of the web. - [Promotions on a variant and a presentation together](https://docs.factuarea.com/changelog/promotion-variant-and-presentation): A promotion item can target a presentation sold with its variant, as its own item with its own price and previous price. Five updated promotions operations and two updated MCP tools. - [Provisioning preview and account details](https://docs.factuarea.com/changelog/accounts-provisioning-preview-and-details): One new operation, the preview of what a new managed account would cost, new fields on companies, tax ID transfers, managed accounts, plan changes, bulk imports and the consolidated workforce, and a voucher expiry that is now always returned on reissue. - [Purchase scanner: public API and MCP](https://docs.factuarea.com/changelog/purchase-scanner-api): Upload, review, resolve duplicates and convert purchase scans through the public API and MCP. Thirteen operations cover the full flow, the scanner mailbox and expense categories. - [Purchase scans: bounded history, deferred OCR and supplier facet](https://docs.factuarea.com/changelog/purchase-scan-detail-history): The scan detail now returns the 50 most recent attempts and audit events with their totals, scans waiting for the daily OCR quota say so, and the stats add a per-supplier facet. - [Purchase scans: unavailable source error](https://docs.factuarea.com/changelog/purchase-scan-source-unavailable): Retry, convert and restore now identify when the original scan file is no longer retained. - [Recent operations join the axis](https://docs.factuarea.com/changelog/axis-for-recent-operations): The operations released since 21 September — projects and tasks, the purchase scanner, notifications, users, VeriFactu representation, issuing without sending and series editing — live under /v1/companies/{company}, and eight partial updates move from PUT to PATCH. - [Refunds and net amount of non-invoiced charges](https://docs.factuarea.com/changelog/non-invoiced-charges-refunds): Non-invoiced Stripe charges carry their refunds and the net amount the merchant keeps, can be filtered by date, and travel to the accountant in the quarterly package as a CSV. Four updated operations and three updated MCP tools. - [Stores, MCP and complete response examples](https://docs.factuarea.com/changelog/stores-mcp-responses): Connect WooCommerce and Shopify stores, work with order snapshots and use the updated MCP transport. Every documented response now has an explicit example or the appropriate download representation. - [Stripe Connect in white label](https://docs.factuarea.com/changelog/stripe-connect-white-label): Four new operations and four new error codes to let your clients connect their own Stripe account from your product, with return domains you control. - [Stripe fees as expenses and a fuller payout breakdown](https://docs.factuarea.com/changelog/stripe-platform-account-and-fee-expenses): Connected Stripe accounts can record their monthly Stripe fees as an expense, payouts now break down every movement they settle, and expenses that self-assess their VAT no longer count it in the total. Nine operations updated, three new account fields, three new payout fields and a new connection method. - [Tasks refinements](https://docs.factuarea.com/changelog/tasks-review-fixes): Tighter limits and clearer errors in Projects and Tasks: a 400,000-character task description, a 99,999,999.99 hourly rate, entity links that respect scopes, the task id in notifications, deletes blocked by invoiced hours and idempotent time invoicing. users:read becomes a sensitive scope. - [Tax reports: working workbook and agent tools](https://docs.factuarea.com/changelog/tax-report-workbooks): Tax reports use an Excel working workbook and expose nine MCP tools. Existing report endpoints now document their supported output formats precisely. - [Team, keys and logs on the account axis](https://docs.factuarea.com/changelog/account-team-keys-and-logs): One new operation, the daily usage of an API key, and new fields on API keys, members, invitations, request logs and Stripe Connect return domains, plus the correction to reactivating a disabled account webhook endpoint. - [Time tracking (control horario)](https://docs.factuarea.com/changelog/time-tracking): Manage work schedules, time entries, absences, balances and presence through the API and MCP, using the same permission model as the rest of the platform. - [Time tracking follows the employment period](https://docs.factuarea.com/changelog/time-tracking-employment-period): Breaking change: clocking before an employee's hire date or after their termination date now answers 422 with subcode clocking_outside_employment_period. Daily balances add is_unscheduled and is_outside_employment, the monthly sheet and the team summary add a to_date block for the closed days, the employee schedule accepts a date, hire_date becomes editable, and reassigning or unassigning a schedule that has not started yet cancels it. - [Transport control document (DeCA) and transport weight](https://docs.factuarea.com/changelog/transport-documents-deca): New transport_documents resource with 17 endpoints to issue, modify, share and keep the Spanish digital control document for road freight, mandatory from 5 October 2026; 15 MCP tools, 10 transport_document.* events, 24 error codes and gross transport weight on products, variants, presentations and delivery notes. - [Unattended checkout invoicing](https://docs.factuarea.com/changelog/unattended-checkout-invoicing): A paid simplified invoice from a kiosk in one idempotent call, VeriFactu remission through Factuarea, subsanación of accepted records and per-line errors. Three breaking changes: a line without a rate no longer takes 21 %, issuing is rejected when the record does not fit the AEAT schema, and in NO VERI*FACTU mode it needs a usable certificate. POST /v1/verifactu/records/{id}/retry no longer answers max_retries_exceeded. - [v1.13.0 — Contract parity](https://docs.factuarea.com/changelog/v1-13-0): Product-write semantics, expanded OAuth consent, plan-derived API capacity and multiline PDF notes. - [VeriFactu reports the real AEAT environment](https://docs.factuarea.com/changelog/verifactu-instance-environment): The VeriFactu configuration and records return the AEAT environment and automatic submission of the instance: on the production API, always the real AEAT, automatically. environment and auto_transmit are deprecated in the settings update. Four updated operations and four updated MCP tools. - [What’s changing at Factuarea.](https://docs.factuarea.com/changelog/launch): Releases, contract changes and tooling updates for your integration. ## Other pages - [FAQ](https://docs.factuarea.com/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. - [API pricing & limits](https://docs.factuarea.com/pricing): What the API costs, which tier each plan grants, and the per-tier caps on requests, API keys and webhook endpoints. - [Explore the API](https://docs.factuarea.com/reference): Find an operation or enter the domain you want to work with. - [Support](https://docs.factuarea.com/support): How to reach the Factuarea API team, what to include when reporting an issue, how API access works, the status page and the changelog. - [Agents & scripting](https://docs.factuarea.com/cli/agents): The factuarea CLI agent-first contract — stable JSON on stdout, structured errors on stderr, semantic exit codes, the commands --json manifest, local scope-check and typed confirmation for irreversible operations. - [Devloop](https://docs.factuarea.com/cli/devloop): Test Factuarea webhooks locally without deploying or ngrok — factuarea listen forwards the events of one tax ID to localhost with a signed body, factuarea trigger produces real sandbox events. - [CLI overview](https://docs.factuarea.com/cli): Install and authenticate the official factuarea CLI — drive the v1 REST API from your terminal with brew, npm or a curl installer. Agent-first, Stripe-inspired. - [Usage](https://docs.factuarea.com/cli/usage): The factuarea command tree — list, show, create, domain actions, PDF templates, conditional writes, binary downloads, multipart uploads, the generic api escape hatch and the commands --json manifest. - [Claude Code plugin](https://docs.factuarea.com/mcp/claude-code-plugin): Two official plugins in one marketplace — factuarea-mcp connects Claude Code to the Factuarea MCP server, and factuarea-api ships five skills for building the integration itself. - [Connecting a client](https://docs.factuarea.com/mcp/connect): Connect any MCP client over Streamable HTTP, or through the local npm server, and authenticate with OAuth or an API key. - [Errors & rate limits](https://docs.factuarea.com/mcp/errors): JSON-RPC error shapes mapped from the v1 contract, the full code table, and per-token / per-plan throttling with Retry-After. - [MCP overview](https://docs.factuarea.com/mcp): Connect AI agents to Factuarea over the Model Context Protocol — tools across invoicing, catalog, pricing, compliance, time tracking, projects and tasks, automations, webhooks and the account model, with OAuth 2.1 and API-key auth. - [MCP protocol and transport](https://docs.factuarea.com/mcp/protocol): Revision 2026-07-28 with stateless discovery, support for 2025-11-25 and 2025-06-18 clients, explicit request headers and scoped pagination. - [Resources and prompts](https://docs.factuarea.com/mcp/resources-and-prompts): Read fiscal guardrails and use the five guided workflows before calling business tools. - [Scopes & permissions](https://docs.factuarea.com/mcp/scopes): The OAuth consent scope catalog, how it maps to the fine-grained scopes tools enforce, the account and privileged scopes, the super-scope, and plan/module gating. - [Tool catalog](https://docs.factuarea.com/mcp/tools): All Factuarea MCP tools grouped by domain, plus the ten privileged managed-account tools, with the scope each one requires and its rate-limit category. - [GoCardless](https://docs.factuarea.com/payments/gocardless): Status of the GoCardless integration — not released yet, what already exists behind the flag, and the exact v1 and MCP surface that appears the day it is switched on. - [Integration event inbox](https://docs.factuarea.com/payments/integration-events-inbox): Why a charge did not become an invoice — the typed discard reasons, which ones notify you, which ones park the event so you can replay it, and how the 30-day retention window works. - [Reconciling with system metadata](https://docs.factuarea.com/payments/metadata-reconciliation): The metadata keys Factuarea writes on invoices auto-issued from a Stripe subscription cycle, and how to use the metadata filter to pull every invoice of a subscription or of a billing period. - [MONEI](https://docs.factuarea.com/payments/monei): Status of the MONEI integration — not released yet, what already exists behind the flag, why it has no mandates resource, and the exact v1 and MCP surface that appears on release. - [Payouts & bank reconciliation](https://docs.factuarea.com/payments/payouts-reconciliation): How Factuarea ingests Stripe payouts, links them to the charges they group, reconciles them against your Norma 43 bank statement, and emits the payout.reconciled event. - [Stripe auto-invoicing](https://docs.factuarea.com/payments/stripe-autoinvoicing): Auto-issue invoices from Stripe Connect charges — NIF capture in Checkout, the simplified-invoice threshold, requiring a NIF, and which charges are routed to manual review. - [Connect Stripe in white label](https://docs.factuarea.com/payments/stripe-connect-white-label): Let your clients connect their own Stripe account to a tax ID from your product. Register your return domains, start the authorization, send the person to Stripe and read the result when they come back. - [Stripe fees as expenses](https://docs.factuarea.com/payments/stripe-fee-expenses): Record the fees Stripe charges your connected account as a monthly expense, with the tax treatment you choose, and recover the months you have already lived through. - [SDKs overview](https://docs.factuarea.com/sdks): Official TypeScript and PHP SDKs for the Factuarea API — install @factuarea/sdk or factuarea/factuarea-php and get retries, idempotency, cursor pagination, typed errors and webhook verification out of the box. - [PHP](https://docs.factuarea.com/sdks/php): Install factuarea/factuarea-php with Composer, authenticate, and create your first invoice. PSR-4, Guzzle-based, PHP 8.2+. - [TypeScript](https://docs.factuarea.com/sdks/typescript): Install @factuarea/sdk for Node.js, authenticate, and create your first invoice. Dual ESM + CommonJS, full type declarations, Node 20+. - [Tools for building](https://docs.factuarea.com/tools): Choose your SDK, work from the terminal or generate a client from OpenAPI. - [The contract, ready for your tools.](https://docs.factuarea.com/tools/openapi): Use OpenAPI to explore the API or generate a client. Official SDKs are the first choice for TypeScript and PHP. - [Absences](https://docs.factuarea.com/guides/absences): Configure absence types and policies, handle requests, and read balances and the team calendar over the v1 API. - [Account personalization](https://docs.factuarea.com/guides/account-personalization): Set the invoice-emission language, PDF template and accent color of your account — and read them back from the Account resource. - [Account webhooks](https://docs.factuarea.com/guides/account-webhooks): Receive the events of your account and its tax IDs at one endpoint, with the equivalence table against company webhooks. - [Accounts and tax IDs](https://docs.factuarea.com/guides/accounts-and-nifs): Your account is the customer: its tax IDs, its team with owner, admin and member roles, per-tax-ID grants, tax ID transfers and how to introspect it with GET /v1/me. - [Reach a tax ID through the company segment](https://docs.factuarea.com/guides/acting-on-behalf): Work on any tax ID your credential reaches by naming it in the company segment of the path — your own, granted access and managed accounts — with how to resolve its id, the answers you get and the retired X-Active-Profile header. - [Additional tax ID seats](https://docs.factuarea.com/guides/additional-nifs): Contract seats for the additional tax IDs of your account: buy and reduce them, what each write uses, the trial rule, the cap and the previews. - [Amounts & dates](https://docs.factuarea.com/guides/amounts-and-dates): How the API represents document money, precise catalog prices and quantities, dates, timestamps and Europe/Madrid boundaries. - [Annul or correct](https://docs.factuarea.com/guides/annul-vs-correct): Four operations look like "undo an invoice" and only one is right for each case — delete, cancel, annul and corrective. Pick wrong and you either lose a fiscal document or file a declaration you did not intend. - [API keys (self-service)](https://docs.factuarea.com/guides/api-keys): Issue, list, narrow, rotate and revoke the API keys of your account over the v1 API — who can issue them, live and test environments, the scopes you can assign and the level ceiling per tax ID. - [Automations](https://docs.factuarea.com/guides/automations): The when, if and do model of the rule engine — versions, the dry run that materialises nothing, run history and steps, replay, the engine limits and the portfolio rules of an account. - [Bulk import of managed accounts](https://docs.factuarea.com/guides/bulk-import): Preview and apply a CSV of clients in one go: columns, modes, row statuses, limits and what a re-import does. - [Bulk operations](https://docs.factuarea.com/guides/bulk-operations): Partial-success contract for bulk endpoints — total, successful, failed and a per-row failures list. - [Catalog and pricing](https://docs.factuarea.com/guides/catalog-overview): Organize products, variants and price lists, and understand how they reach your documents. - [AEAT census verification](https://docs.factuarea.com/guides/census-verification): Check your company's — and your clients' — name + NIF pair against the AEAT census before issuing VeriFactu invoices — deterministic states, sandbox magic NIFs and fail-open behavior. - [API keys scoped to part of your account](https://docs.factuarea.com/guides/child-api-keys): Issue, narrow, rotate and revoke API keys that reach only some of the tax IDs of your account — scoped_company_ids, the level ceiling per tax ID and what happens when the person who issued a key loses access. - [Tax ID portfolio](https://docs.factuarea.com/guides/companies): Register, follow and manage the tax IDs of your account over the v1 API — the contracted seat an additional tax ID takes, provisioning, the active, inactive and archived state, statistics and issuing readiness. - [Contact imports](https://docs.factuarea.com/guides/contact-imports): Preview contact files, track confirmed row results and download authorized error reports. - [Unified contacts](https://docs.factuarea.com/guides/contact-migration): Migrate client and supplier integrations without losing fiscal identity or history. - [Corrective invoices](https://docs.factuarea.com/guides/corrective-invoices): R1 to R5, substitution versus differences, and how the lines of a corrective are built — the four decisions that determine what the AEAT and the VAT return actually receive. - [Private billing offers](https://docs.factuarea.com/guides/customer-billing-offers): Redeem a company-specific discount, negotiated price or trial extension with a reviewed, recoverable quote. - [Disbursements](https://docs.factuarea.com/guides/disbursements): Money you pay on behalf of your customer — court fees, registry duties, visas — is not your revenue. How to invoice it so it stays out of your taxable base, your VAT and your annual third-party return. - [Document presentations](https://docs.factuarea.com/guides/document-presentations): Choose the PDF template of an invoice, quote, pro-forma or delivery note, read what each document retained, revise it after issuing, and recover from ETag, CAS and precondition errors. - [Document scanner](https://docs.factuarea.com/guides/document-scanner): Upload supplier invoices and receipts, review extracted data and create linked expense drafts. - [PDF template library](https://docs.factuarea.com/guides/document-templates): Manage your company's PDF templates, brand identities and defaults — revisions, impact, per-contact defaults, asset uploads, precedence, ETag concurrency and idempotency. - [Ecommerce stores](https://docs.factuarea.com/guides/ecommerce-stores): Connect stores, configure order invoicing and diagnose orders and refunds through REST and MCP. - [Employee batches and a single seat checkout](https://docs.factuarea.com/guides/employee-batches): Create or reactivate up to 100 employees with one durable operation and a reviewed seat quote. - [Employee seat billing](https://docs.factuarea.com/guides/employee-seats): The per-employee billing add-on — a dedicated monthly subscription of the account that pays, whose quantity is the contracted seats; creating or reactivating an employee takes a free seat at no charge, and only buying seats charges. - [Export and import](https://docs.factuarea.com/guides/export-and-import): Export invoices to XLSX or CSV and import unified contacts with explicit roles, field mapping and a preview. - [External advisor](https://docs.factuarea.com/guides/external-advisor): The one outside person your account can give access to in any plan: how to mark them, the limit of one and why they take no seat. - [FACe invoicing (B2G)](https://docs.factuarea.com/guides/face-invoicing): Submit FacturaE 3.2.2 invoices to FACe — DIR3 codes, signed XAdES-EPES XML retained per attempt, processing states, uncertain transmissions and how to recover, cancellation, sandbox simulation and the facturae:write scope. - [Fiscal cookbook](https://docs.factuarea.com/guides/fiscal-cookbook): Six end-to-end recipes — issue and wait for AEAT acceptance, correct an amount, substitute simplified invoices, pass on a disbursement, invoice outside the EU, and repair a rejected record. - [Fiscal invoice examples](https://docs.factuarea.com/guides/fiscal-invoice-examples): The 21 Spanish tax scenarios for invoicing, which four of them ship as ready-to-send request examples in the API Reference, and a corrective example for each AEAT R-code (R1–R5). - [Tax compliance and VeriFactu](https://docs.factuarea.com/guides/fiscal-overview): Find the workflow for your invoice, check its status and resolve tax issues. - [Glossary](https://docs.factuarea.com/guides/glossary): Spanish fiscal and domain terms used across the Factuarea API — NIF, VeriFactu, AEAT, FacturaE, Modelo 303/347, series, rectificativa, huella, CSV, DeCA — plus the account model: additional tax IDs, granted access, managed accounts and tax ID transfers. - [Granted access between accounts](https://docs.factuarea.com/guides/granted-access): Let another account reach some or all of your tax IDs with view or operate level, and what that account can and cannot do. - [Integrations](https://docs.factuarea.com/guides/integrations): Choose an integration and understand its setup, credentials and public API coverage. - [Compliance of the integrator's component](https://docs.factuarea.com/guides/integrator-component-compliance): What the software of a terminal that calls the Factuarea API must do and declare under Order HAC/1177/2024 and the AEAT developers' FAQ, with an orientative model of the component's own responsible declaration. - [International customers](https://docs.factuarea.com/guides/international-customers): Identifying a non-Spanish recipient with the AEAT alternative-ID catalogue, and the scenario-to-qualification map for intra-EU supplies, reverse charge, exports and one-stop-shop sales. - [Invoice business data](https://docs.factuarea.com/guides/invoice-business-data): Payment schedule, header and line references, invoicing period, legal literals and DIR3 administrative centres on an invoice — omit versus null, versions, and how to change them after issuing. - [Working with invoices](https://docs.factuarea.com/guides/invoicing): From your first document to payment: issuing, sending, recurring invoices and bulk operations. - [Line tax classification and exemptions](https://docs.factuarea.com/guides/line-tax-classification-and-exemptions): E1–E6 and N1–N2 per line, IRPF withholding that subtracts, and the closed matrix of legal VAT-to-equivalence-surcharge pairs — the four fields that decide what the AEAT breakdown says. - [Managed account pricing and payer change](https://docs.factuarea.com/guides/managed-accounts-billing): What you pay for each managed account, how a plan change is charged and what happens when the client takes over the payment. - [Test managed accounts with fact_test_](https://docs.factuarea.com/guides/managed-accounts-testing): Run the whole provisioning flow with a test key: test accounts, import, reads and events, with no charge and no claim. - [Managed accounts](https://docs.factuarea.com/guides/managed-accounts): Provision accounts for your clients over the API: create them, claim voucher, access level, end of management and the routes a managed account opens. - [Monthly time-record close](https://docs.factuarea.com/guides/monthly-time-close): Freeze the immutable monthly register, seal it with a digital signature, and export the report or the payroll incidents file. - [n8n workflows](https://docs.factuarea.com/guides/n8n): Install the official trigger, subscribe to events and recover webhook delivery safely. - [Packs](https://docs.factuarea.com/guides/packs): Sell several products or services as one item. Read the catalog from your server, sync it with webhooks, show prices with and without VAT and map it to schema.org. - [Recording payments](https://docs.factuarea.com/guides/payments): Register partial payments, read the running balance from the ledger, and revert a payment that came back — without ever issuing a corrective invoice you did not mean to. - [PDF previews and artifacts](https://docs.factuarea.com/guides/pdf-template-previews): Preview a template before using it, prepare and render the exact PDF of a document, download it with ETag and 304, and read pdf_output_state with a correct retry loop. - [Presence](https://docs.factuarea.com/guides/presence): Read who is working right now and who is in office or remote — a derived, read-only view over the time-tracking ledger, schedules and roster. - [Price lists](https://docs.factuarea.com/guides/price-lists): Create customer-specific EUR prices, resolve catalog precedence and reprice draft documents without rewriting history. - [Product catalog](https://docs.factuarea.com/guides/product-catalog): Model products and services with UNECE units, presentations, variants, supplier offers and immutable document snapshots. - [Promotions and previous price](https://docs.factuarea.com/guides/promotions): Put products and packs on offer for a few days, read the offer from your web, and announce the reduction with the previous price that the law requires. - [Quickstart](https://docs.factuarea.com/guides/quickstart): Your first invoice in 5 minutes — verify your key, grab a series and a tax, create a contact, issue an invoice and send it. One copy-paste sequence against a fact_test_ key. - [Recurring invoices](https://docs.factuarea.com/guides/recurring-invoices): Skip a cycle, create a recurrence from an invoice, choose whether each run issues or emails the invoice, fix or follow the PDF template, generate an invoice now, configure auto-delivery, preview the next document and set per-line fiscal fields. - [Regime keys](https://docs.factuarea.com/guides/regime-keys): Three different things are called "regime" in Spanish invoicing. This is which one you set, which one is derived, and the closed AEAT catalogue of seventeen codes a line may declare. - [Scope and limitations](https://docs.factuarea.com/guides/scope-and-limitations): What the Factuarea API deliberately does not do, what it does not do yet, and the equivalent way to get each job done — plus six capabilities you may assume are missing and are not. - [Scopes & irreversibility](https://docs.factuarea.com/guides/scopes-and-irreversibility): How to read the required scope and irreversibility of each endpoint from the OpenAPI spec — the x-required-scope and x-irreversible extensions — and the catalog of irreversible operations. - [Sending documents](https://docs.factuarea.com/guides/sending-documents): Send documents by email, verify sender identity and distinguish identity errors from delivery budgets. - [Shopify integration](https://docs.factuarea.com/guides/shopify): Authorize Shopify, configure order invoicing and interpret credentials and API-version failures. - [Simplified or full invoices](https://docs.factuarea.com/guides/simplified-vs-full-invoices): F1, F2 and F3 — when a simplified invoice is legal, the 3.000 € cap that is actually enforced, how to issue one through the API, the qualified simplified invoice that names its recipient, and the one-call substitution that turns a batch of tickets into a complete invoice. - [Your store with Factuarea](https://docs.factuarea.com/guides/storefront): Show products and packs in your web store, keep prices and availability in sync, and invoice each paid order with the price the customer paid. - [Tags & custom fields](https://docs.factuarea.com/guides/tags-and-custom-fields): Classify documents with tags and attach typed custom_fields. Filter lists by tag. How they differ from metadata. - [iCal feed](https://docs.factuarea.com/guides/tasks-calendar-feed): Subscribe to the tasks of a project, or your own, from any calendar app through a secret read-only iCal URL — how the URL works, rotation and revocation, privacy and what the feed includes. - [Time logged on tasks](https://docs.factuarea.com/guides/tasks-time-tracking): Log time on tasks by hand or with a timer, read the time summary of a project and turn billable hours into a draft invoice — and why it is not the working-day clock-in. - [Projects and tasks](https://docs.factuarea.com/guides/tasks): Projects with keys and board columns, tasks with positions, labels, comments, relations, custom fields, links to documents and attachments — the work-management API under /v1/companies/{company}/projects and /v1/companies/{company}/tasks. - [Tax reports](https://docs.factuarea.com/guides/tax-reports): Generate Modelo 303, 347 and 130, choose the right output format, and tell the file you submit apart from the workbook you review. - [Territorial taxes — VAT, IGIC and IPSI](https://docs.factuarea.com/guides/territorial-taxes): Spain has three indirect taxes, not one. Which rates are legal in each, how the regime is chosen per document, what the AEAT breakdown declares, and why IGIC and IPSI never appear in the quarterly VAT return. - [Test mode & sandbox](https://docs.factuarea.com/guides/test-mode): 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. - [Time clock](https://docs.factuarea.com/guides/time-clock): Clock in and out, pauses, retroactive entries and the correction workflow over the append-only time-record ledger. - [Transport control document (DeCA)](https://docs.factuarea.com/guides/transport-documents): Issue the Spanish electronic administrative control document for road freight from the API — scope and exemptions, the issue → driver copy → modify → close flow, the permanent public URL for the inspection, delivery notes and gross weight. - [Unattended checkout invoicing](https://docs.factuarea.com/guides/unattended-checkout): Issue a paid simplified invoice from a self-service terminal or vending machine in ONE idempotent call, print the VERI*FACTU QR that comes back, and know exactly what to do when a call fails, repeats or is rejected. - [VeriFactu auto-submission](https://docs.factuarea.com/guides/verifactu-auto-submission): There is no "send to AEAT" button. Registration is created when the invoice leaves draft — the gates that decide whether it happens, how the records reach the AEAT in batches and without a retry cap, who remits them, and the manual levers that exist afterwards. - [VeriFactu submission states](https://docs.factuarea.com/guides/verifactu-submission-states): The lifecycle of a VeriFactu billing record — pending, submitted, accepted, rejected, error — what csv and huella mean, how retries and blocked records work, and when to retry, release or subsanar. - [VeriFactu record subsanación](https://docs.factuarea.com/guides/verifactu-subsanacion): Correct a VeriFactu billing record — rejected or accepted by the AEAT — with a NEW record that follows it. When subsanación applies, when you need an annulment or a corrective instead, and the exact API flow. - [Deduplicate webhook deliveries](https://docs.factuarea.com/guides/webhook-deduplication): The same event keeps the same id in the company and the account envelope: how to store it and skip repeats. - [WooCommerce integration](https://docs.factuarea.com/guides/woocommerce): Configure the store connector and official plugin, including checkout tax IDs and connection diagnostics. - [Work schedules](https://docs.factuarea.com/guides/work-schedules): Define weekly work patterns, their compliance mode, and effective-dated assignments to employees over the v1 API. - [Time tracking overview](https://docs.factuarea.com/guides/workforce-overview): The workforce system over the v1 API — the immutable time-record ledger (RD-ley 8/2019), the portal-only employee role, the per-seat add-on and the eight domains that make it up. - [access_level_raise_forbidden](https://docs.factuarea.com/errors/access_level_raise_forbidden): Someone tried to raise the access level on a managed account whose holder has already claimed it. Since the claim only the holder can raise that level; the provider can only lower it. - [account_not_found](https://docs.factuarea.com/errors/account_not_found): The account behind the key could not be resolved, which usually means the key no longer points at a live company. - [account_probation_limit_exceeded](https://docs.factuarea.com/errors/account_probation_limit_exceeded): The 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. - [account_webhook_endpoint_limit_reached](https://docs.factuarea.com/errors/account_webhook_endpoint_limit_reached): The account reached the number of account webhook endpoints its tier allows in that environment. The cap is counted per account and per environment (live or test) and includes disabled endpoints: only deleting an endpoint frees a slot. - [additional_nif_charge_failed](https://docs.factuarea.com/errors/additional_nif_charge_failed): The immediate charge for the additional tax ID was declined: the card was refused, it needs authentication, or the payment provider was unreachable. When the charge fails, the tax ID is not added or activated and no charge remains. - [additional_nif_not_in_plan](https://docs.factuarea.com/errors/additional_nif_not_in_plan): The account holds a live plan, but that plan does not include additional tax IDs: only Empresario and Enterprise (trials included) allow them. Nothing was charged and no change was written. - [additional_nif_plan_required](https://docs.factuarea.com/errors/additional_nif_plan_required): The account has no live plan, so there is no subscription on which to charge the additional tax ID. Nothing was charged and no change was written. - [addon_not_active](https://docs.factuarea.com/errors/addon_not_active): The functionality belongs to an add-on that is not active for the company right now. - [addon_required](https://docs.factuarea.com/errors/addon_required): Creating webhook endpoints requires a plan that includes them: for company endpoints, the Developer API add-on of the company; for account endpoints, the plan of the payer of the account. That subscription is missing here — the free tier allows zero endpoints. - [administrator_key_not_grantable](https://docs.factuarea.com/errors/administrator_key_not_grantable): One of the sections in `grants` is an Administrator key (user management, plan and subscription, API and developers or digital certificate) and those sections are never granted to a member. - [alta_record_not_found](https://docs.factuarea.com/errors/alta_record_not_found): The invoice has no registration record, so the operation that depends on it has nothing to work with. - [alternative_id_type_invalid](https://docs.factuarea.com/errors/alternative_id_type_invalid): The alternative identifier type is outside the catalogue `nif_iva`, `passport`, `country_id`, `residence_certificate`, `other_document`, `not_registered`. - [amount_reconciliation_failed](https://docs.factuarea.com/errors/amount_reconciliation_failed): The amounts with VAT included cannot be split into line amounts that add up to exactly the amount charged, so nothing was issued rather than alter the total. A withholding or an equivalence surcharge that moves the total by more than a rounding difference causes it. - [anulacion_record_already_exists](https://docs.factuarea.com/errors/anulacion_record_already_exists): The invoice already carries an annulment record in the chain, and annulment is reported only once. - [api_key_already_revoked](https://docs.factuarea.com/errors/api_key_already_revoked): The key was already revoked, and a revoked key admits no further operations: revocation is terminal. - [api_key_expired](https://docs.factuarea.com/errors/api_key_expired): The key passed its expiry date. - [api_key_not_found](https://docs.factuarea.com/errors/api_key_not_found): The identifier does not match any API key of the authenticated company. - [api_key_revoked](https://docs.factuarea.com/errors/api_key_revoked): The key was revoked, and a revoked key never authenticates again — revocation is the way to cut off a leaked credential. - [api_version_invalid_format](https://docs.factuarea.com/errors/api_version_invalid_format): The payload version of the endpoint is not a `YYYY-MM-DD` date. - [api_version_unsupported](https://docs.factuarea.com/errors/api_version_unsupported): The payload version is well formed but is not among the ones the platform serves. - [attachment_invalid_filename](https://docs.factuarea.com/errors/attachment_invalid_filename): The file name is not usable: it is empty, it carries path components, or it exceeds 200 characters. - [attachment_mime_not_allowed](https://docs.factuarea.com/errors/attachment_mime_not_allowed): The file type is outside the accepted set: PDF, PNG, JPEG, XML and HTML. - [attachment_missing](https://docs.factuarea.com/errors/attachment_missing): The expense exists but carries no attached file, so there is nothing to download. - [attachment_too_large](https://docs.factuarea.com/errors/attachment_too_large): The file exceeds the maximum size allowed for a document attachment. - [automation_action_order_invalid](https://docs.factuarea.com/errors/automation_action_order_invalid): The 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_missing](https://docs.factuarea.com/errors/automation_action_parameter_missing): A 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_unknown](https://docs.factuarea.com/errors/automation_action_parameter_unknown): A 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_invalid](https://docs.factuarea.com/errors/automation_action_parameter_value_invalid): A parameter of the action carries a value outside the set its schema accepts. - [automation_action_parameters_invalid](https://docs.factuarea.com/errors/automation_action_parameters_invalid): The 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_invalid](https://docs.factuarea.com/errors/automation_action_type_invalid): One of the steps declares an action type with no adapter behind it, so nothing would run at that position. - [automation_active_rules_limit_exceeded](https://docs.factuarea.com/errors/automation_active_rules_limit_exceeded): The company already has all the active automation rules its plan allows. - [automation_chain_depth_exceeded](https://docs.factuarea.com/errors/automation_chain_depth_exceeded): One 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_invalid](https://docs.factuarea.com/errors/automation_condition_combinator_invalid): A 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_exceeded](https://docs.factuarea.com/errors/automation_condition_depth_exceeded): The condition nests more levels than the evaluator walks, so the rule cannot be evaluated end to end. - [automation_condition_expression_invalid](https://docs.factuarea.com/errors/automation_condition_expression_invalid): The 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_evaluable](https://docs.factuarea.com/errors/automation_condition_field_not_evaluable): The 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_invalid](https://docs.factuarea.com/errors/automation_condition_operator_invalid): A comparison of the condition names an operator outside the accepted set. - [automation_condition_operator_not_applicable](https://docs.factuarea.com/errors/automation_condition_operator_not_applicable): The 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_unsupported](https://docs.factuarea.com/errors/automation_condition_operator_unsupported): The 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_missing](https://docs.factuarea.com/errors/automation_condition_payload_field_missing): The 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_mismatch](https://docs.factuarea.com/errors/automation_condition_payload_type_mismatch): The 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_mismatch](https://docs.factuarea.com/errors/automation_dry_run_event_type_mismatch): The 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_unresolvable](https://docs.factuarea.com/errors/automation_event_company_unresolvable): The 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_resolvable](https://docs.factuarea.com/errors/automation_event_payload_not_resolvable): The 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_exhausted](https://docs.factuarea.com/errors/automation_monthly_budget_exhausted): The 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_action](https://docs.factuarea.com/errors/automation_portfolio_scope_forbids_action): One of the actions acts on the data of a single company, and under portfolio scope every run has a different tax ID of the portfolio as its subject. Only actions that notify the account owner, or that touch no entity at all, are admitted. - [automation_portfolio_scope_not_available](https://docs.factuarea.com/errors/automation_portfolio_scope_not_available): This company cannot create automations over a portfolio: either it has not been granted the accounting-practice module, or it is not the owner of its account. The portfolio is represented by the account owner, so an additional tax ID of the account never has a portfolio of its own. - [automation_rate_limit_exceeded](https://docs.factuarea.com/errors/automation_rate_limit_exceeded): The 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_allowed](https://docs.factuarea.com/errors/automation_replay_not_allowed): The 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_empty](https://docs.factuarea.com/errors/automation_rule_actions_empty): The rule declares no actions, so there would be nothing to run when its trigger fired. - [automation_rule_actions_limit_exceeded](https://docs.factuarea.com/errors/automation_rule_actions_limit_exceeded): The 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_deleted](https://docs.factuarea.com/errors/automation_rule_already_deleted): The 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_mismatch](https://docs.factuarea.com/errors/automation_rule_company_mismatch): The 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_invalid](https://docs.factuarea.com/errors/automation_rule_name_invalid): The 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_found](https://docs.factuarea.com/errors/automation_rule_not_found): No 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_immutable](https://docs.factuarea.com/errors/automation_rule_scope_immutable): The 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_invalid](https://docs.factuarea.com/errors/automation_rule_scope_invalid): The scope you sent is not in the automation catalogue. There are only two: the company that creates the rule, and the portfolio of its account (its other tax IDs and the ones another account cedes to it with operate level). - [automation_rule_status_transition_invalid](https://docs.factuarea.com/errors/automation_rule_status_transition_invalid): The 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_invalid](https://docs.factuarea.com/errors/automation_rule_uuid_invalid): The 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_found](https://docs.factuarea.com/errors/automation_rule_version_not_found): The 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_invalid](https://docs.factuarea.com/errors/automation_rule_version_number_invalid): The version number is below 1. Versions are numbered from one upwards, in the order they were published. - [automation_rule_version_snapshot_not_found](https://docs.factuarea.com/errors/automation_rule_version_snapshot_not_found): The 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_found](https://docs.factuarea.com/errors/automation_run_not_found): No 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_invalid](https://docs.factuarea.com/errors/automation_run_status_transition_invalid): The 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_found](https://docs.factuarea.com/errors/automation_run_step_not_found): The 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_invalid](https://docs.factuarea.com/errors/automation_run_uuid_invalid): The run identifier is not a valid UUID v7. - [automation_step_index_invalid](https://docs.factuarea.com/errors/automation_step_index_invalid): A step index cannot be negative: no run addresses a step that way. - [automation_step_status_transition_invalid](https://docs.factuarea.com/errors/automation_step_status_transition_invalid): The 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_mismatch](https://docs.factuarea.com/errors/automation_step_subject_company_mismatch): The 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_verified](https://docs.factuarea.com/errors/automation_subject_company_ownership_not_verified): While preparing the run it could not be proven that the company behind the event is still in the portfolio of the account of whoever created the automation, reachable with operate level and active. The tax ID may have been archived, deactivated or transferred to another account, the relation that ceded it may have been revoked, ended or lowered to read-only, or the run reached this point with mismatched data. - [automation_trigger_not_found](https://docs.factuarea.com/errors/automation_trigger_not_found): The 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_unknown](https://docs.factuarea.com/errors/automation_trigger_payload_contract_unknown): The trigger publishes no contract of evaluable fields, so there is no catalogue against which to resolve a condition. - [automation_trigger_type_invalid](https://docs.factuarea.com/errors/automation_trigger_type_invalid): The write carries a trigger that is not in the catalogue available to your company, so the rule would never receive an event. - [bank_account_usage_required](https://docs.factuarea.com/errors/bank_account_usage_required): The 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. - [billing_managed_by_provider](https://docs.factuarea.com/errors/billing_managed_by_provider): This account's billing is paid by another account, so it cannot contract an additional tax ID on its own. Nothing was charged and no change was written. - [bulk_task_selection_too_large](https://docs.factuarea.com/errors/bulk_task_selection_too_large): The bulk operation includes more tasks than a single batch allows (200 by default; the message states the current ceiling). It is not a request limit or a plan limit: it bounds what is processed at once. - [business_rule_violation](https://docs.factuarea.com/errors/business_rule_violation): A domain invariant rejected the operation. This code carries the family; `error.subcode` names the concrete rule and `error.message` explains it. - [cannot_archive_last_default_series](https://docs.factuarea.com/errors/cannot_archive_last_default_series): The 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. - [cannot_attach_to_cancelled_purchase_invoice](https://docs.factuarea.com/errors/cannot_attach_to_cancelled_purchase_invoice): The expense is cancelled, and attaching documents to a cancelled record would alter closed documentation. - [cannot_have_both_tax_id_and_alternative_id](https://docs.factuarea.com/errors/cannot_have_both_tax_id_and_alternative_id): The 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_id](https://docs.factuarea.com/errors/census_requires_tax_id): Census verification checks the pair name plus tax id against AEAT, and one of the two is missing. - [certificate_expired](https://docs.factuarea.com/errors/certificate_expired): The certificate is outside its validity window: it has expired, or it is not valid yet. - [certificate_nif_mismatch](https://docs.factuarea.com/errors/certificate_nif_mismatch): The 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_found](https://docs.factuarea.com/errors/certificate_not_found): The company has no FNMT certificate matching the identifier, or none uploaded at all. - [certificate_too_large](https://docs.factuarea.com/errors/certificate_too_large): The file exceeds the 100 KB limit, while a real FNMT certificate weighs a few kilobytes. - [chain_position_conflict](https://docs.factuarea.com/errors/chain_position_conflict): Two records of the same company tried to take the same position in the fingerprint chain at the same time, and the automatic retries could not resolve the collision. - [charge_rule_invalid](https://docs.factuarea.com/errors/charge_rule_invalid): The rule is inconsistent: the condition, the outcome, the not-invoiced reason, the concept or the VAT rate do not fit together or are not valid. The conflicting field is reported in `param`. - [charge_rule_limit_reached](https://docs.factuarea.com/errors/charge_rule_limit_reached): The Stripe account already has the maximum number of charge treatment rules. - [charge_rule_not_found](https://docs.factuarea.com/errors/charge_rule_not_found): The charge treatment rule does not exist on the given Stripe account or does not belong to your company. - [client_has_documents](https://docs.factuarea.com/errors/client_has_documents): The 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_large](https://docs.factuarea.com/errors/client_import_too_large): The CSV exceeds the row limit the synchronous import accepts, since the whole file is processed within the request. - [client_not_found](https://docs.factuarea.com/errors/client_not_found): The identifier does not resolve to any client of the authenticated company. - [client_requires_tax_identity](https://docs.factuarea.com/errors/client_requires_tax_identity): The client carries no fiscal identity: neither `tax_id` nor an alternative identifier, and an invoice cannot be issued to an unidentified party. - [clock_drift_exceeded](https://docs.factuarea.com/errors/clock_drift_exceeded): The 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. - [clocking_outside_employment_period](https://docs.factuarea.com/errors/clocking_outside_employment_period): The clocking instant falls before the employee's hire date or after their termination date, so nothing was written to the time record. Both the hire day and the termination day accept clockings. Approving a correction checks the current employment period again, and a rejected approval leaves the request pending. - [column_has_tasks](https://docs.factuarea.com/errors/column_has_tasks): The column you are trying to delete still holds tasks and the request does not say where to move them. To avoid leaving tasks without a place on the board, the deletion is rejected and nothing was changed. - [column_slug_in_use](https://docs.factuarea.com/errors/column_slug_in_use): Another column of the same project already has an equivalent name. The comparison uses the identifier derived from the name, so two names that differ only in case or punctuation still collide. - [column_slug_reserved](https://docs.factuarea.com/errors/column_slug_reserved): The column name translates into the identifier `planned` or `archived`, which are reserved for the statuses of tasks that sit outside the board. Such a column would be indistinguishable from those statuses. - [company_inactive](https://docs.factuarea.com/errors/company_inactive): The company named by the `{company}` path segment is within the credential's scope, but it is deactivated and cannot be operated until it comes back. - [company_monthly_quota_exceeded](https://docs.factuarea.com/errors/company_monthly_quota_exceeded): The company used up the monthly volume its plan grants to all of its keys together. - [company_rate_limit_exceeded](https://docs.factuarea.com/errors/company_rate_limit_exceeded): The company exceeded the per-minute rate its plan grants to all of its keys together, not the rate of a single key. - [company_read_only](https://docs.factuarea.com/errors/company_read_only): The person who issued the credential has read-only access (level `view`) to the effective company: their role in the account lets them see that tax ID, not write to it. The effective level is the lower of the one stored on the credential and the one the person holds today. - [conflicting_pagination_params](https://docs.factuarea.com/errors/conflicting_pagination_params): `starting_after` and `ending_before` travelled in the same request. They walk the collection in opposite directions, so only one of them can apply. - [connect_return_domain_already_exists](https://docs.factuarea.com/errors/connect_return_domain_already_exists): The host you are trying to add is already one of the return domains of your account. It is compared normalized (lower case, no port or path), so `App.Example.com` and `app.example.com` are the same domain. - [connect_return_domain_limit_reached](https://docs.factuarea.com/errors/connect_return_domain_limit_reached): Your account already has the maximum number of return domains it allows, and the new one was not saved. The cap is per account and counts every registered domain. - [connect_return_domain_not_found](https://docs.factuarea.com/errors/connect_return_domain_not_found): The return domain named in the path does not exist in your account, or belongs to another one: both answers are identical on purpose so the domains of other accounts are never revealed. - [connect_return_url_not_allowed](https://docs.factuarea.com/errors/connect_return_url_not_allowed): The host of the `return_url` is not among the return domains of the account of the key you use to start the Stripe connection. Only `https` addresses whose exact host (no wildcards) is registered on that account are accepted, so nobody can send the person to a site you do not control. - [contact_not_found](https://docs.factuarea.com/errors/contact_not_found): The identifier does not resolve to any business contact of the authenticated company. - [corrective_client_change_requires_substitution](https://docs.factuarea.com/errors/corrective_client_change_requires_substitution): The corrective is issued to a client other than the original invoice's (for instance, after an error in the client data): it can only be a substitution, because by differences the amount would be attributed to someone who never received the invoice. - [corrective_full_cancellation_with_lines](https://docs.factuarea.com/errors/corrective_full_cancellation_with_lines): Voiding the whole invoice by differences (`correction_type: full` with `correction_nature: I`) takes no lines: the corrective copies every original line back negated. - [corrective_invoice_inanulable](https://docs.factuarea.com/errors/corrective_invoice_inanulable): The invoice is itself a corrective, and correctives are never annulled: the correction chain has to stay auditable end to end. - [corrective_substitution_negative_amount](https://docs.factuarea.com/errors/corrective_substitution_negative_amount): In a substitution corrective (`correction_nature: S`, or `full` with `lines` and no nature) each line carries the FINAL amount of the correct invoice, so no quantity can be negative (art. 15.5 RD 1619/2012; VERI*FACTU does not accept a negative base in a substitution). The unit price is never negative: the sign goes in the quantity. - [corrective_substitution_requires_full](https://docs.factuarea.com/errors/corrective_substitution_requires_full): A substitution corrective (`correction_nature: S`) replaces the whole invoice; there is no partial substitution. - [custom_header_blocklisted](https://docs.factuarea.com/errors/custom_header_blocklisted): One 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_long](https://docs.factuarea.com/errors/custom_header_value_too_long): The value of a custom header exceeds 1024 characters. - [customer_offer_benefit_invalid](https://docs.factuarea.com/errors/customer_offer_benefit_invalid): The offer conditions are invalid. Review the indicated fields. - [customer_offer_billing_state_conflict](https://docs.factuarea.com/errors/customer_offer_billing_state_conflict): The billing state has changed or needs review. Check the operation before continuing. - [customer_offer_catalog_unavailable](https://docs.factuarea.com/errors/customer_offer_catalog_unavailable): The billing catalog is not configured or cannot be verified; this is not a restriction on the customer plan. - [customer_offer_collection_not_restorable](https://docs.factuarea.com/errors/customer_offer_collection_not_restorable): The purchase cannot be collected or its balance safely restored. No debt is left for another invoice. - [customer_offer_combination_invalid](https://docs.factuarea.com/errors/customer_offer_combination_invalid): Extra trial days can only combine with a permanent plan discount or price. - [customer_offer_discount_conflict](https://docs.factuarea.com/errors/customer_offer_discount_conflict): An offer or discount already applies to the same product. Benefits do not stack automatically. - [customer_offer_forbidden](https://docs.factuarea.com/errors/customer_offer_forbidden): The operation does not satisfy the current conditions or permissions. - [customer_offer_gateway_unavailable](https://docs.factuarea.com/errors/customer_offer_gateway_unavailable): The payment provider is unavailable. Check this operation before retrying. - [customer_offer_idempotency_conflict](https://docs.factuarea.com/errors/customer_offer_idempotency_conflict): This attempt already belongs to different conditions. Keep the operation and check its status. - [customer_offer_invalid_terms](https://docs.factuarea.com/errors/customer_offer_invalid_terms): The offer conditions are invalid. Review the indicated fields. - [customer_offer_legacy_outcome_unknown](https://docs.factuarea.com/errors/customer_offer_legacy_outcome_unknown): A previous billing operation is still awaiting verification. - [customer_offer_negotiated_price_invalid](https://docs.factuarea.com/errors/customer_offer_negotiated_price_invalid): Review the agreed net price, product, interval and number of billing cycles. - [customer_offer_not_eligible](https://docs.factuarea.com/errors/customer_offer_not_eligible): This offer is incompatible with the company, product or current status. - [customer_offer_operation_in_progress](https://docs.factuarea.com/errors/customer_offer_operation_in_progress): An operation is already in progress for this product. Check its status before continuing. - [customer_offer_payment_method_required](https://docs.factuarea.com/errors/customer_offer_payment_method_required): This purchase needs a payment method. Add one and refresh the terms before confirming. - [customer_offer_phase_incompatible](https://docs.factuarea.com/errors/customer_offer_phase_incompatible): The subscription has an incompatible scheduled change. It has not been overwritten. - [customer_offer_price_mapping_conflict](https://docs.factuarea.com/errors/customer_offer_price_mapping_conflict): The billing state has changed or needs review. Check the operation before continuing. - [customer_offer_purchase_failed](https://docs.factuarea.com/errors/customer_offer_purchase_failed): Payment failed and this purchase was verified as not applied. Check the operation before trying again. - [customer_offer_quote_changed](https://docs.factuarea.com/errors/customer_offer_quote_changed): The conditions have changed. Refresh the quote before confirming. - [customer_offer_quote_expired](https://docs.factuarea.com/errors/customer_offer_quote_expired): The quote has expired. Refresh it and review the conditions. - [customer_offer_quote_unavailable](https://docs.factuarea.com/errors/customer_offer_quote_unavailable): The amount cannot be verified. Confirmation is blocked. - [customer_offer_state_conflict](https://docs.factuarea.com/errors/customer_offer_state_conflict): The billing state has changed or needs review. Check the operation before continuing. - [customer_offer_trial_baseline_changed](https://docs.factuarea.com/errors/customer_offer_trial_baseline_changed): The trial has changed. Refresh the quote to see the current end date. - [customer_offer_trial_limit_exceeded](https://docs.factuarea.com/errors/customer_offer_trial_limit_exceeded): This extension would exceed the maximum 180 trial days. - [customer_offer_trial_not_eligible](https://docs.factuarea.com/errors/customer_offer_trial_not_eligible): You can only extend an active trial of the agreed plan. An expired trial cannot restart. - [customer_offer_unavailable](https://docs.factuarea.com/errors/customer_offer_unavailable): This offer is unavailable, expired or has no redemptions left. - [declaracion_already_exists](https://docs.factuarea.com/errors/declaracion_already_exists): The company already filed its SIF responsibility statement for that period. - [declaracion_not_found](https://docs.factuarea.com/errors/declaracion_not_found): The company has no SIF responsibility statement filed for the requested period. - [delivery_note_cancelled](https://docs.factuarea.com/errors/delivery_note_cancelled): One of the delivery notes sent to pre-fill the transport document is cancelled, and a cancelled delivery note cannot be the source of a shipment. Nothing was created. - [delivery_note_cannot_be_sent](https://docs.factuarea.com/errors/delivery_note_cannot_be_sent): The delivery note is already invoiced or cancelled: delivering it now would hand the customer a superseded document. - [delivery_note_not_found](https://docs.factuarea.com/errors/delivery_note_not_found): The identifier does not resolve to any delivery note of the authenticated company. - [delivery_note_section_not_editable_in_status](https://docs.factuarea.com/errors/delivery_note_section_not_editable_in_status): The logistics section — carrier, vehicle, driver — is frozen because the delivery note is already delivered, invoiced or cancelled. - [dependency_unavailable](https://docs.factuarea.com/errors/dependency_unavailable): An external service the operation relies on did not answer in time. - [direct_debit_requires_default_bank_account](https://docs.factuarea.com/errors/direct_debit_requires_default_bank_account): Direct debit was selected as the payment method, but the client has no default bank account to charge. - [document_type_required_for_ambiguous_code](https://docs.factuarea.com/errors/document_type_required_for_ambiguous_code): That series code exists for more than one document type, so on its own it does not identify a single series. - [driver_tax_id_requires_name](https://docs.factuarea.com/errors/driver_tax_id_requires_name): The driver tax id was sent without the driver name, and an identifier with no name identifies nobody on the delivery document. - [duplicate_override_reason_required](https://docs.factuarea.com/errors/duplicate_override_reason_required): A valid reason to proceed despite the duplicate is missing. - [duplicate_pack_component](https://docs.factuarea.com/errors/duplicate_pack_component): The same product, variant, presentation or configuration appears more than once in the pack. - [duplicate_price_list_name](https://docs.factuarea.com/errors/duplicate_price_list_name): Another price list in the company already uses that name, which must be unique within the tenant. - [duplicate_promotion_item](https://docs.factuarea.com/errors/duplicate_promotion_item): The same article appears more than once in the offer, and each article can have only one price rule. - [duplicate_resolution_required](https://docs.factuarea.com/errors/duplicate_resolution_required): A possible duplicate requires review. - [duplicate_tax_default_for_document_type](https://docs.factuarea.com/errors/duplicate_tax_default_for_document_type): Another tax of the same type is already the default for that document type, and the pair (tax type, document type) admits a single default. - [email_delivery_circuit_open](https://docs.factuarea.com/errors/email_delivery_circuit_open): Email 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_exceeded](https://docs.factuarea.com/errors/email_recipient_budget_exceeded): The 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. - [emitter_capability_restricted](https://docs.factuarea.com/errors/emitter_capability_restricted): The person who issued the credential has the section or action required by the operation withdrawn in the effective company. It is the same per-module restriction the company administrator set for them in the web app, and it applies even if their access level to the tax ID is `operate`. - [employee_batch_billing_state_conflict](https://docs.factuarea.com/errors/employee_batch_billing_state_conflict): Billing needs review before this operation can continue. - [employee_batch_forbidden](https://docs.factuarea.com/errors/employee_batch_forbidden): You no longer have permission for this operation. Check its status before starting another. - [employee_batch_idempotency_conflict](https://docs.factuarea.com/errors/employee_batch_idempotency_conflict): This request belongs to different details. Review the operation before preparing a new batch. - [employee_batch_quote_changed](https://docs.factuarea.com/errors/employee_batch_quote_changed): The conditions changed. Refresh the quote and accept the new amount. - [employee_batch_quote_expired](https://docs.factuarea.com/errors/employee_batch_quote_expired): This quote expired. Refresh it and review the amount. - [employee_batch_quote_unavailable](https://docs.factuarea.com/errors/employee_batch_quote_unavailable): A reliable amount is unavailable. Retry without starting another payment. - [employee_batch_state_conflict](https://docs.factuarea.com/errors/employee_batch_state_conflict): This action is no longer available. Check the current operation status. - [employee_inactive](https://docs.factuarea.com/errors/employee_inactive): The employee has been terminated: they are read-only and accept no new operations, such as clocking in, being assigned a schedule or an absence policy, having an absence that runs past their termination date approved, or being invited to the portal. Nothing was written. - [employee_not_found](https://docs.factuarea.com/errors/employee_not_found): The employee does not exist or is not accessible in this company. - [employee_seat_charge_failed](https://docs.factuarea.com/errors/employee_seat_charge_failed): The 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_mutation_outcome_unknown](https://docs.factuarea.com/errors/employee_seat_mutation_outcome_unknown): A previous employee operation is still awaiting verification. Do not repeat the charge. - [employee_seat_operation_in_progress](https://docs.factuarea.com/errors/employee_seat_operation_in_progress): A seat operation is in progress. Recover it before starting another. - [employee_seat_payment_method_required](https://docs.factuarea.com/errors/employee_seat_payment_method_required): Adding or reactivating an employee charges a seat immediately, and the company operates in live mode with no payment method on file. - [employee_seat_phase_incompatible](https://docs.factuarea.com/errors/employee_seat_phase_incompatible): The subscription has scheduled terms that this seat mutation cannot preserve. - [employee_seats_not_in_plan](https://docs.factuarea.com/errors/employee_seats_not_in_plan): The account's plan does not include time tracking (the `control_horario` module, by plan or by a manual grant), so employee seats cannot be bought. Nothing was charged and no change was written; lowering or keeping the contracted seats stays allowed. - [enterprise_contract_transition_required](https://docs.factuarea.com/errors/enterprise_contract_transition_required): The managed account has an enterprise contract and, on ending the management, its payment would move to the holder before Factuarea has set the plan it continues on. A subscription is never created without a price, so nothing was changed. - [event_already_processed](https://docs.factuarea.com/errors/event_already_processed): That SIF event is already recorded in the event chain, and each event is processed exactly once. - [event_not_found](https://docs.factuarea.com/errors/event_not_found): The identifier does not match any event of the authenticated company, or the event was purged by the 30-day retention policy. - [exemption_cause_contradicts_taxed_lines](https://docs.factuarea.com/errors/exemption_cause_contradicts_taxed_lines): The invoice carries a header exemption cause that declares the operation VAT-free (exemption, non-subject or reverse charge) and an operation line has a VAT rate above zero. - [export_budget_exceeded](https://docs.factuarea.com/errors/export_budget_exceeded): The 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_exceeded](https://docs.factuarea.com/errors/export_byte_cap_exceeded): The 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_exceeded](https://docs.factuarea.com/errors/export_document_cap_exceeded): The 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. - [export_limit_exceeded](https://docs.factuarea.com/errors/export_limit_exceeded): The filtered selection exceeds the 5,000-invoice cap of the export, so the file is refused up front instead of being silently truncated. - [external_advisor_already_assigned](https://docs.factuarea.com/errors/external_advisor_already_assigned): The account already has an external advisor marked: there can only be one per account. - [external_id_already_exists](https://docs.factuarea.com/errors/external_id_already_exists): The `external_id` you use to reconcile with your own system is already assigned to another object of the same type in this company. - [face_submission_attempt_conflict](https://docs.factuarea.com/errors/face_submission_attempt_conflict): Another request changed the FACe submission attempt (claim or reconciliation) while you were acting on it. - [face_submission_completion_failed](https://docs.factuarea.com/errors/face_submission_completion_failed): FACe answered the submission but the platform could not store the result locally. - [face_submission_rejected](https://docs.factuarea.com/errors/face_submission_rejected): FACe analysed the submission and rejected it with its own error code (for example a wrong DIR3 code, an invalid signature or a duplicate). Unlike an uncertain transmission, FACe did not register the invoice. - [face_transmission_failed](https://docs.factuarea.com/errors/face_transmission_failed): The FACe platform — the public administration entry point — was unreachable or answered with a fault. The failure is upstream, not in your request. - [face_transmission_uncertain](https://docs.factuarea.com/errors/face_transmission_uncertain): The invoice was sent to FACe but its outcome is unknown, so FACe may or may not have registered it. - [facturae_artifact_unavailable](https://docs.factuarea.com/errors/facturae_artifact_unavailable): The Facturae file retained for that submission cannot be read from storage because it is missing or damaged. The failure is on our side. - [facturae_operation_forbidden](https://docs.factuarea.com/errors/facturae_operation_forbidden): The actor cannot perform that Facturae operation; `details.reason` tells whether it is a matter of the actor's permissions, the issuer's authority, access to the invoice or the right to send it. - [facturae_signing_failed](https://docs.factuarea.com/errors/facturae_signing_failed): The XAdES signature of the Facturae file could not be produced, usually because the signing certificate is unusable at that moment. - [feature_not_available_in_plan](https://docs.factuarea.com/errors/feature_not_available_in_plan): The feature is not included in the company plan. - [forbidden_action](https://docs.factuarea.com/errors/forbidden_action): The action is refused even though the scope is right. The usual reasons are: your credential reaches the tax ID through an account relation (access granted to your account, or a managed account) and the operation belongs to the account that owns the tax ID — request logs, events, webhook endpoints, account billing, automation usage and writes of connected payment credentials are never available through a relation; the tax ID belongs to a managed account whose holder already pays for it, so its provider can read it and edit its data but can no longer activate, deactivate or archive it; the person who issued the credential is not an owner or admin of the account, or the credential does not reach every tax ID of the account; or the resource belongs to a shared catalogue, or the change travels through a different endpoint. - [forge_account_link_rejected](https://docs.factuarea.com/errors/forge_account_link_rejected): Only personal GitHub accounts can be linked. GitLab and Gitea do not use linked accounts: they connect with the access token of the project integration. - [forge_account_not_linked](https://docs.factuarea.com/errors/forge_account_not_linked): The operation acts on your behalf in the forge —for example, to list your GitHub repositories— and you have not linked your account on that forge to your user yet. - [forge_credentials_rejected](https://docs.factuarea.com/errors/forge_credentials_rejected): The GitLab or Gitea instance rejects the given address or credential. The `subcode` says why: `not_a_forge_instance`, `redirected`, `repository_not_found`, `insufficient_permissions` or `unauthorized`. - [forge_oauth_state_invalid](https://docs.factuarea.com/errors/forge_oauth_state_invalid): The forge link could not be completed: the authorisation state has expired, was already used, is not valid or belongs to another user or company. - [forge_repository_access_denied](https://docs.factuarea.com/errors/forge_repository_access_denied): Your linked GitHub account does not allow connecting that repository, or the repository does not exist; the answer is the same in both cases so that other people's repositories are not revealed. - [forge_repository_bound_elsewhere](https://docs.factuarea.com/errors/forge_repository_bound_elsewhere): The repository is already connected to another active project of the company. A repository feeds a single project, so that each issue or pull request ends up in a single task. - [forge_secret_rotation_not_supported](https://docs.factuarea.com/errors/forge_secret_rotation_not_supported): This integration has no webhook secret of its own to rotate: GitHub integrations sign with the GitHub App secret, and rotation only exists for GitLab and Gitea integrations. - [forge_token_required](https://docs.factuarea.com/errors/forge_token_required): The forge instance URL is being changed without a new token. The stored token is never sent to an address other than the one it was issued for, so that it does not end up on a foreign server. - [forge_webhook_signature_invalid](https://docs.factuarea.com/errors/forge_webhook_signature_invalid): The forge webhook delivery could not be authenticated: the signature does not match the integration secret, or the integration does not exist. No event was processed. - [forge_workflow_rule_column_invalid](https://docs.factuarea.com/errors/forge_workflow_rule_column_invalid): The rule's target column does not belong to the integration's project; a non-existent column, one from another project or one from another company all answer the same. - [forge_workflow_rule_not_found](https://docs.factuarea.com/errors/forge_workflow_rule_not_found): The rule that moves tasks between columns on a forge event (for example, when a pull request is merged) does not exist or belongs to another company; both cases answer the same. - [gestoria_seat_preview_unavailable](https://docs.factuarea.com/errors/gestoria_seat_preview_unavailable): The managed-company seat charge could not be verified; this does not mean the purchase is contractually free. - [github_app_not_configured](https://docs.factuarea.com/errors/github_app_not_configured): The GitHub integration is not available on this server because its administrator has not configured the GitHub App. It is not a problem with your account or your permissions. - [global_tax_read_only](https://docs.factuarea.com/errors/global_tax_read_only): The tax belongs to the Factuarea catalogue, which is read-only for companies: you can only change or delete the taxes your own company created. - [grant_company_not_in_account](https://docs.factuarea.com/errors/grant_company_not_in_account): The grant's tax ID is not a real tax ID of the account, or it is outside the credential's tax ID scope. Both cases get the same answer, without telling which. - [grants_only_for_member](https://docs.factuarea.com/errors/grants_only_for_member): Only a member with the `member` role can hold per tax ID permissions (grants). The owner (`owner`) and the administrators (`admin`) reach every tax ID of the account, so a grant on them would mean nothing. - [gross_weight_not_allowed](https://docs.factuarea.com/errors/gross_weight_not_allowed): This item cannot carry a gross transport weight: services have no weight, products and variants whose base unit is a mass unit (`KGM`, `GRM`) already weigh their quantity, and a variable-measure presentation is weighed on each line. - [idempotency_key_in_use](https://docs.factuarea.com/errors/idempotency_key_in_use): Another request with the same `Idempotency-Key` is still in flight, and the result is not known yet. - [idempotency_key_invalid](https://docs.factuarea.com/errors/idempotency_key_invalid): The `Idempotency-Key` does not fit the accepted format: it must be 1 to 255 printable ASCII characters. - [idempotency_key_required](https://docs.factuarea.com/errors/idempotency_key_required): The 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_reused](https://docs.factuarea.com/errors/idempotency_key_reused): That `Idempotency-Key` was already used with a different payload. The key identifies one specific operation, so reusing it for another would make replay meaningless. An `external_id` already issued that is resent with a different type or total in `POST /v1/companies/{company}/invoices` does not return this error but the 409 `unattended_replay_mismatch`. - [import_credentials_rejected](https://docs.factuarea.com/errors/import_credentials_rejected): The import source system rejected the supplied credentials with an unauthorised or forbidden response. Nothing was imported. - [import_file_invalid](https://docs.factuarea.com/errors/import_file_invalid): One of the import files cannot be read with the template format: it is not a readable CSV, its header does not appear within its first 20 lines, it lacks a required column or it has a broken line. `param` says which file fails (`accounts_file` or `customers_file`) and the message names the column or the line. Nothing was written. - [import_file_too_large](https://docs.factuarea.com/errors/import_file_too_large): One of the import files exceeds 5 MB. The size is checked before reading any row, so nothing was processed or written. `param` says which file fails (`accounts_file` or `customers_file`). - [import_in_progress](https://docs.factuarea.com/errors/import_in_progress): A bulk import of this provider account is already in progress. Imports of the same account are applied one at a time so that no account, charge or tax ID is created twice, so this one was not applied and nothing was written. - [import_not_found](https://docs.factuarea.com/errors/import_not_found): The contact import or its report is unavailable in the authenticated company. - [import_row_limit_exceeded](https://docs.factuarea.com/errors/import_row_limit_exceeded): One of the import files carries more rows than a single import accepts: 100 in the accounts file (`accounts_file`) and 1,000 in the customers file (`customers_file`). Rows are counted before being read, so nothing was processed or written. `param` says which file fails. - [import_row_quota_exceeded](https://docs.factuarea.com/errors/import_row_quota_exceeded): The newly admitted import rows would exceed the plan’s monthly row allowance. - [import_run_already_active](https://docs.factuarea.com/errors/import_run_already_active): An import from the same source into the same target is already running. Two simultaneous imports would create duplicate tasks, so the second one is not started. - [inactive_price_list](https://docs.factuarea.com/errors/inactive_price_list): The price list is inactive and may only be read to explain historical documents, not selected for a new operation. - [Account error codes](https://docs.factuarea.com/errors/index-account): Every public API error code emitted by Account, with its HTTP status, its type and a page per code. - [Authentication error codes](https://docs.factuarea.com/errors/index-authentication): Every public API error code emitted by Authentication, with its HTTP status, its type and a page per code. - [Authorization error codes](https://docs.factuarea.com/errors/index-authorization): Every public API error code emitted by Authorization, with its HTTP status, its type and a page per code. - [Automations error codes](https://docs.factuarea.com/errors/index-automations): Every public API error code emitted by Automations, with its HTTP status, its type and a page per code. - [Billing error codes](https://docs.factuarea.com/errors/index-billing): Every public API error code emitted by Billing, with its HTTP status, its type and a page per code. - [Companies error codes](https://docs.factuarea.com/errors/index-companies): Every public API error code emitted by Companies, with its HTTP status, its type and a page per code. - [Contacts error codes](https://docs.factuarea.com/errors/index-contacts): Every public API error code emitted by Contacts, with its HTTP status, its type and a page per code. - [Delivery Notes error codes](https://docs.factuarea.com/errors/index-delivery-notes): Every public API error code emitted by Delivery Notes, with its HTTP status, its type and a page per code. - [Employees error codes](https://docs.factuarea.com/errors/index-employees): Every public API error code emitted by Employees, with its HTTP status, its type and a page per code. - [Events error codes](https://docs.factuarea.com/errors/index-events): Every public API error code emitted by Events, with its HTTP status, its type and a page per code. - [Exports error codes](https://docs.factuarea.com/errors/index-exports): Every public API error code emitted by Exports, with its HTTP status, its type and a page per code. - [Managed companies error codes](https://docs.factuarea.com/errors/index-gestoria): Every public API error code emitted by Managed companies, with its HTTP status, its type and a page per code. - [Idempotency error codes](https://docs.factuarea.com/errors/index-idempotency): Every public API error code emitted by Idempotency, with its HTTP status, its type and a page per code. - [Integration error codes](https://docs.factuarea.com/errors/index-integration): Every public API error code emitted by Integration, with its HTTP status, its type and a page per code. - [Invoices error codes](https://docs.factuarea.com/errors/index-invoices): Every public API error code emitted by Invoices, with its HTTP status, its type and a page per code. - [MCP error codes](https://docs.factuarea.com/errors/index-mcp): Every public API error code emitted by MCP, with its HTTP status, its type and a page per code. - [Notifications error codes](https://docs.factuarea.com/errors/index-notifications): Every public API error code emitted by Notifications, with its HTTP status, its type and a page per code. - [Payments error codes](https://docs.factuarea.com/errors/index-payments): Every public API error code emitted by Payments, with its HTTP status, its type and a page per code. - [PDF error codes](https://docs.factuarea.com/errors/index-pdf): Every public API error code emitted by PDF, with its HTTP status, its type and a page per code. - [Pricing error codes](https://docs.factuarea.com/errors/index-pricing): Every public API error code emitted by Pricing, with its HTTP status, its type and a page per code. - [Products error codes](https://docs.factuarea.com/errors/index-products): Every public API error code emitted by Products, with its HTTP status, its type and a page per code. - [Proformas error codes](https://docs.factuarea.com/errors/index-proformas): Every public API error code emitted by Proformas, with its HTTP status, its type and a page per code. - [Expenses error codes](https://docs.factuarea.com/errors/index-purchase-invoices): Every public API error code emitted by Expenses, with its HTTP status, its type and a page per code. - [Expense scanner error codes](https://docs.factuarea.com/errors/index-purchase-scans): Every public API error code emitted by Expense scanner, with its HTTP status, its type and a page per code. - [Quotes error codes](https://docs.factuarea.com/errors/index-quotes): Every public API error code emitted by Quotes, with its HTTP status, its type and a page per code. - [Rate Limit error codes](https://docs.factuarea.com/errors/index-rate-limit): Every public API error code emitted by Rate Limit, with its HTTP status, its type and a page per code. - [Recurring Invoices error codes](https://docs.factuarea.com/errors/index-recurring-invoices): Every public API error code emitted by Recurring Invoices, with its HTTP status, its type and a page per code. - [Request error codes](https://docs.factuarea.com/errors/index-request): Every public API error code emitted by Request, with its HTTP status, its type and a page per code. - [Series error codes](https://docs.factuarea.com/errors/index-series): Every public API error code emitted by Series, with its HTTP status, its type and a page per code. - [Server error codes](https://docs.factuarea.com/errors/index-server): Every public API error code emitted by Server, with its HTTP status, its type and a page per code. - [Storage error codes](https://docs.factuarea.com/errors/index-storage): Every public API error code emitted by Storage, with its HTTP status, its type and a page per code. - [Task Integrations error codes](https://docs.factuarea.com/errors/index-taskintegrations): Every public API error code emitted by Task Integrations, with its HTTP status, its type and a page per code. - [Tasks error codes](https://docs.factuarea.com/errors/index-tasks): Every public API error code emitted by Tasks, with its HTTP status, its type and a page per code. - [Tax Reports error codes](https://docs.factuarea.com/errors/index-tax-reports): Every public API error code emitted by Tax Reports, with its HTTP status, its type and a page per code. - [Taxes error codes](https://docs.factuarea.com/errors/index-taxes): Every public API error code emitted by Taxes, with its HTTP status, its type and a page per code. - [Time Tracking error codes](https://docs.factuarea.com/errors/index-time-tracking): Every public API error code emitted by Time Tracking, with its HTTP status, its type and a page per code. - [Transport Documents error codes](https://docs.factuarea.com/errors/index-transport-documents): Every public API error code emitted by Transport Documents, with its HTTP status, its type and a page per code. - [VeriFactu error codes](https://docs.factuarea.com/errors/index-verifactu): Every public API error code emitted by VeriFactu, with its HTTP status, its type and a page per code. - [Webhooks error codes](https://docs.factuarea.com/errors/index-webhooks): Every public API error code emitted by Webhooks, with its HTTP status, its type and a page per code. - [Error codes by category](https://docs.factuarea.com/errors): Every public API error code grouped by category, with a page per code covering its cause and what to do. - [indirect_tax_regime_invalid](https://docs.factuarea.com/errors/indirect_tax_regime_invalid): The indirect regime is outside the catalogue `iva`, `igic`, `ipsi`. - [insufficient_data_for_report](https://docs.factuarea.com/errors/insufficient_data_for_report): The period has no data to file, or an invoice of the period lacks a mandatory field for this model — typically the customer tax id. - [insufficient_scope](https://docs.factuarea.com/errors/insufficient_scope): The 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. - [integration_destination_not_allowed](https://docs.factuarea.com/errors/integration_destination_not_allowed): The company egress policy does not allow connecting to that address: for security, private or internal destinations are blocked unless the company has allowed them. The error does not repeat the rejected URL. - [internal_error](https://docs.factuarea.com/errors/internal_error): Something broke on our side while processing the request. The condition is not caused by your payload. - [invalid_aeat_code](https://docs.factuarea.com/errors/invalid_aeat_code): The AEAT operation code is outside the closed catalogue `S1`, `S2`, `S3`, `E1`-`E6`, `N1`, `N2` used by VeriFactu and SII. - [invalid_api_key](https://docs.factuarea.com/errors/invalid_api_key): The 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. - [invalid_cargo_measure](https://docs.factuarea.com/errors/invalid_cargo_measure): The declared measure of a shipment is not valid: its `type` is not `weight` or `other`, the weight or value is missing or not greater than zero, or the free unit is not between 1 and 30 characters. - [invalid_certificate_format](https://docs.factuarea.com/errors/invalid_certificate_format): The 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_password](https://docs.factuarea.com/errors/invalid_certificate_password): The password does not open the certificate file. - [invalid_connection_method](https://docs.factuarea.com/errors/invalid_connection_method): The connection method does not exist for this provider. - [invalid_correction_nature](https://docs.factuarea.com/errors/invalid_correction_nature): `correction_nature` only accepts `I` (by differences: the corrective carries the amount of the rectification, with its sign) or `S` (substitution: it carries the invoice as it ends up, with the final lines). - [invalid_correction_reason](https://docs.factuarea.com/errors/invalid_correction_reason): The 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_country_aeat_zone](https://docs.factuarea.com/errors/invalid_country_aeat_zone): The AEAT territorial zone is outside the catalogue `peninsula`, `canarias`, `ceuta`, `melilla`. - [invalid_country_code](https://docs.factuarea.com/errors/invalid_country_code): The country code is not exactly two characters, so it is not a valid ISO 3166-1 alpha-2 code. - [invalid_custom_field_definition](https://docs.factuarea.com/errors/invalid_custom_field_definition): The custom field definition is not valid: name outside 1 to 60 characters, unknown type, required field without a default value, options on a type that does not accept them, type change after creation, removing an option that tasks use, or an incomplete reordering. `error.param` points at the exact item. - [invalid_custom_field_value](https://docs.factuarea.com/errors/invalid_custom_field_value): The value does not fit the custom field type —for example, text in a numeric field or an option that is not in the list— or the field does not belong to the task's project. - [invalid_customer_visible_label](https://docs.factuarea.com/errors/invalid_customer_visible_label): The label shown to the customer on the document exceeds the allowed length. - [invalid_delivery_channel](https://docs.factuarea.com/errors/invalid_delivery_channel): The delivery channel is outside the catalogue, which has only two values: `email` (recorded automatically when the mail server accepts the message) and `manual` (a delivery you made by your own means). - [invalid_description](https://docs.factuarea.com/errors/invalid_description): The description exceeds the maximum length allowed for the field. - [invalid_document_type](https://docs.factuarea.com/errors/invalid_document_type): The document type is outside the catalogue: `invoice`, `quote`, `delivery_note`, `proforma`, `purchase_invoice`, `recurring_invoice`. - [invalid_expiry_date](https://docs.factuarea.com/errors/invalid_expiry_date): The expiry date is earlier than the issue date, or more than 365 days after it. - [invalid_facturae_structured_data](https://docs.factuarea.com/errors/invalid_facturae_structured_data): The structured data needed to build the Facturae file is not valid: a value is wrong, the totals do not match the lines, or the generated XML fails the schema. - [invalid_frequency_interval](https://docs.factuarea.com/errors/invalid_frequency_interval): The interval is lower than 1, so the recurrence would never advance to a next run. - [invalid_frequency_type](https://docs.factuarea.com/errors/invalid_frequency_type): The frequency is outside the catalogue `daily`, `weekly`, `biweekly`, `monthly`, `bimonthly`, `quarterly`, `semiannual`, `annual`, `custom`. - [invalid_gross_weight](https://docs.factuarea.com/errors/invalid_gross_weight): The gross transport weight is not a number, is zero or negative, has more than 4 decimals or exceeds the column ceiling. On a goods line of a transport control document, also when the quantity times the weight per unit gives a line weight that rounds to 0 kg or exceeds that ceiling. - [invalid_hire_date](https://docs.factuarea.com/errors/invalid_hire_date): The employee's hire date would fall after their termination date: either `hire_date` was changed to a date later than the recorded termination, or the employee was deactivated with a `termination_date` earlier than the hire date. The employee is left unchanged. - [invalid_holiday_handling](https://docs.factuarea.com/errors/invalid_holiday_handling): The holiday policy is outside the catalogue `skip`, `before`, `after`, `same`. - [invalid_inbound_signature](https://docs.factuarea.com/errors/invalid_inbound_signature): The inbound email signature could not be authenticated. - [invalid_invoice_business_data](https://docs.factuarea.com/errors/invalid_invoice_business_data): The business data of the invoice (line references, administrative centres or their roles) contains an invalid value. - [invalid_invoice_id](https://docs.factuarea.com/errors/invalid_invoice_id): The 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_number](https://docs.factuarea.com/errors/invalid_invoice_number): The invoice number does not follow the numbering format of its series (by default `SERIES-YYYY-NNN`; correctives carry the correlative number of their own series, e.g. `R-2026-001`). - [invalid_invoice_payment_terms](https://docs.factuarea.com/errors/invalid_invoice_payment_terms): The payment schedule of the invoice breaks a rule, for example installments that do not add up to the total, invalid dates or a missing contractual bank account. - [invalid_invoice_status](https://docs.factuarea.com/errors/invalid_invoice_status): The value sent as invoice status is outside the document lifecycle catalogue (`draft`, `scheduled`, `issued`, `overdue`, `cancelled`, `annulled`). Before API version `2026-10-01` `issued` is published as `sent`, and wherever the API reads a status as input (the status filters, the bulk status change) `sent` is taken as `issued`. `paid` is a valid value to read and to filter by, but not to write: register a payment instead. - [invalid_invoice_uuid](https://docs.factuarea.com/errors/invalid_invoice_uuid): The invoice identifier in the path or in the payload is not a valid UUID. - [invalid_move_target_column](https://docs.factuarea.com/errors/invalid_move_target_column): The column given to receive the tasks is not a valid target: it does not exist, belongs to another project or is the very column being deleted. The deletion was not performed. - [invalid_pack_component](https://docs.factuarea.com/errors/invalid_pack_component): A component cannot be part of a pack, for example a product sold by real weight, whose price is only known at the scale. - [invalid_pack_image](https://docs.factuarea.com/errors/invalid_pack_image): The uploaded file is not a usable pack image: it is not a JPG, PNG, WebP or GIF image, it exceeds the maximum size or it could not be read. - [invalid_pack_pricing](https://docs.factuarea.com/errors/invalid_pack_pricing): The pack price is not valid for its mode: a missing or out-of-range value, more than two decimals, or a discount that equals or exceeds the price of the products separately. - [invalid_pack_status_transition](https://docs.factuarea.com/errors/invalid_pack_status_transition): The requested status change is not allowed from the current pack status, for example activating a pack without sales channels or restoring one whose composition is blocked. - [invalid_param_format](https://docs.factuarea.com/errors/invalid_param_format): A 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_value](https://docs.factuarea.com/errors/invalid_param_value): A legacy form request rejected the value of a field. Migrated endpoints report the same situation as `parameter_invalid_enum` or `parameter_invalid_range`. - [invalid_payment_date](https://docs.factuarea.com/errors/invalid_payment_date): The payment date cannot be later than today. A date before the issue date is accepted and recorded as an advance payment. - [invalid_payment_method](https://docs.factuarea.com/errors/invalid_payment_method): The payment method is outside the closed allowlist: `bank_transfer`, `cash`, `credit_card`, `sepa_direct_debit`, `paypal`, `bizum`, `other`. - [invalid_pdf_artifact_fingerprint](https://docs.factuarea.com/errors/invalid_pdf_artifact_fingerprint): The PDF artifact fingerprint is invalid. - [invalid_pdf_template_configuration](https://docs.factuarea.com/errors/invalid_pdf_template_configuration): A value of the template configuration breaks a rule of the template model; `param` gives the path of the offending field. - [invalid_period](https://docs.factuarea.com/errors/invalid_period): The 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. - [invalid_price_list_item](https://docs.factuarea.com/errors/invalid_price_list_item): The price-list entry has an incompatible target, amount or unit, or duplicates the same product, variant and presentation within the list. - [invalid_proforma_id](https://docs.factuarea.com/errors/invalid_proforma_id): The pro forma reference received is not a valid identifier, usually because an internal value replaced the public `id`. - [invalid_proforma_number](https://docs.factuarea.com/errors/invalid_proforma_number): The pro forma number does not follow the canonical numbering format of its series. - [invalid_proforma_status](https://docs.factuarea.com/errors/invalid_proforma_status): The value sent as status is outside the catalogue `draft`, `accepted`, `rejected`, `expired`, `invoiced`, `cancelled`. - [invalid_proforma_uuid](https://docs.factuarea.com/errors/invalid_proforma_uuid): The pro forma identifier in the path or in the payload is not a valid UUID. - [invalid_promotion](https://docs.factuarea.com/errors/invalid_promotion): A field of the offer breaks one of its rules: the name, the text shown on the web, the dates, the time zone, the channels or the list of articles. - [invalid_promotion_item](https://docs.factuarea.com/errors/invalid_promotion_item): An article of the offer is not valid: its target, its mode, its basis or its value breaks a rule. - [invalid_purchase_invoice_id](https://docs.factuarea.com/errors/invalid_purchase_invoice_id): The expense reference received is not a valid identifier, usually because an internal value replaced the public `id`. - [invalid_purchase_invoice_number](https://docs.factuarea.com/errors/invalid_purchase_invoice_number): The invoice number is empty or does not fit the accepted format. On a supplier invoice the number is the one the supplier printed, not one Factuarea generates. - [invalid_purchase_invoice_uuid](https://docs.factuarea.com/errors/invalid_purchase_invoice_uuid): The expense identifier in the path or in the payload is not a valid UUID. - [invalid_purchase_scan_transition](https://docs.factuarea.com/errors/invalid_purchase_scan_transition): The current scan status does not allow this transition. - [invalid_rate_for_tax_regime](https://docs.factuarea.com/errors/invalid_rate_for_tax_regime): The 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_recurring_invoice_id](https://docs.factuarea.com/errors/invalid_recurring_invoice_id): The recurrence reference received is not a valid identifier, usually because an internal value replaced the public `id`. - [invalid_recurring_invoice_uuid](https://docs.factuarea.com/errors/invalid_recurring_invoice_uuid): The recurrence identifier in the path or in the payload is not a valid UUID. - [invalid_recurring_payment_terms_template](https://docs.factuarea.com/errors/invalid_recurring_payment_terms_template): The payment schedule template of the recurrence, applied to every invoice it generates, is not valid. - [invalid_recurring_presentation_policy](https://docs.factuarea.com/errors/invalid_recurring_presentation_policy): The presentation policy of the recurrence, which sets how the invoices it generates are presented, has an invalid value. - [invalid_representation](https://docs.factuarea.com/errors/invalid_representation): The representation breaks a rule: the signed Annex I or the power-of-attorney evidence is missing, the document is not a valid PDF or exceeds 5 MB, `signer_name`, `power_of_attorney_reference` or the revocation reason (`reason`, 3 to 500 characters) do not respect their length, `valid_until` is earlier than `granted_on` or more than 5 years after it, or the representation is already revoked (or there is no current one to revoke). - [invalid_series_code](https://docs.factuarea.com/errors/invalid_series_code): The series code is empty, too long, or carries characters that do not belong in a fiscal prefix. - [invalid_series_name](https://docs.factuarea.com/errors/invalid_series_name): The series name is empty or exceeds the allowed length. - [invalid_series_number](https://docs.factuarea.com/errors/invalid_series_number): The 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_template_assignment](https://docs.factuarea.com/errors/invalid_series_template_assignment): The PDF template assignment sent for the series is inconsistent: the selection or its version is not valid. - [invalid_series_uuid](https://docs.factuarea.com/errors/invalid_series_uuid): The series identifier in the path or in the payload is not a valid UUID. - [invalid_series_year](https://docs.factuarea.com/errors/invalid_series_year): The fiscal year is not a valid four-digit year for a numbering series. - [invalid_status_transition](https://docs.factuarea.com/errors/invalid_status_transition): The requested state is not reachable from the state the document is in right now. - [invalid_task_key](https://docs.factuarea.com/errors/invalid_task_key): The task key is not shaped `KEY-N` —project key, hyphen and number, such as `WEB-42`— or the task number is not a positive integer. - [invalid_task_reference](https://docs.factuarea.com/errors/invalid_task_reference): A task referenced in the request body does not exist or belongs to another company; both cases answer the same. `error.param` names the field that held the reference. - [invalid_task_schedule](https://docs.factuarea.com/errors/invalid_task_schedule): The task dates are not consistent: the start date is later than the due date, or one of them does not exist in the calendar (for example, 30 February). - [invalid_task_status](https://docs.factuarea.com/errors/invalid_task_status): The task target is not valid: the status does not exist, the transition is not allowed, a column and a status are sent together, the column is not in the task's project, or a column is given for a planned or archived task. A task on the board always has a column and one outside it never does. - [invalid_tax_code](https://docs.factuarea.com/errors/invalid_tax_code): The tax code is empty or longer than 50 characters. - [invalid_tax_name](https://docs.factuarea.com/errors/invalid_tax_name): The tax name is empty or longer than 255 characters. - [invalid_tax_rate](https://docs.factuarea.com/errors/invalid_tax_rate): The 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_filter](https://docs.factuarea.com/errors/invalid_tax_type_filter): The `type` filter of the by-type listing carries a value outside the enum `vat`, `retention`, `surcharge`, `other`. - [invalid_time_entry_period](https://docs.factuarea.com/errors/invalid_time_entry_period): The time entry period is not valid: the end is before the start, it lasts more than 24 hours, the start is more than one day in the future, a date is invalid, the end of a closed entry is being removed, or the times of a still-running entry are being changed. - [invalid_transport_tax_id](https://docs.factuarea.com/errors/invalid_transport_tax_id): The tax ID of a party is not valid: a Spanish NIF, NIE or CIF with a wrong control character, or a foreign identifier outside 2 to 20 alphanumeric characters. - [invalid_url_target](https://docs.factuarea.com/errors/invalid_url_target): The 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. - [invalid_validity_window](https://docs.factuarea.com/errors/invalid_validity_window): The validity window is inverted: `valid_until` falls before `valid_from`. - [invalid_vehicle_plate](https://docs.factuarea.com/errors/invalid_vehicle_plate): A vehicle plate does not match a Spanish format (current, old provincial, trailer `R`, special `E` or historic `H`; Spanish plates have no vowels) nor a foreign plate of 2 to 12 alphanumeric characters with its country. - [invitation_expired](https://docs.factuarea.com/errors/invitation_expired): The invitation exists and belongs to this company, but its acceptance window already closed, so the person who received it can no longer redeem it. - [invitation_not_found](https://docs.factuarea.com/errors/invitation_not_found): The identifier matches no pending invitation of the authenticated company: it may have been cancelled, already accepted, or issued by a different company. - [invoice_administrative_precondition_required](https://docs.factuarea.com/errors/invoice_administrative_precondition_required): The change to the administrative routing did not state which version it is based on. - [invoice_administrative_version_conflict](https://docs.factuarea.com/errors/invoice_administrative_version_conflict): The administrative routing of the invoice (its administrative centres) changed after you read it. - [invoice_already_annulled](https://docs.factuarea.com/errors/invoice_already_annulled): The invoice was already annulled. Annulment is terminal and, with VeriFactu active, its annulment record has already reached AEAT. - [invoice_already_paid](https://docs.factuarea.com/errors/invoice_already_paid): The 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_rectified_in_full](https://docs.factuarea.com/errors/invoice_already_rectified_in_full): The invoice is already voided in full (a full corrective by differences), so it admits no further corrective; or it is replaced in full, so it admits no second full correction. - [invoice_already_sent](https://docs.factuarea.com/errors/invoice_already_sent): The 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_number](https://docs.factuarea.com/errors/invoice_cannot_assign_number): A 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_marked_as_sent](https://docs.factuarea.com/errors/invoice_cannot_be_marked_as_sent): The delivery mark records that an issued invoice reached the customer, so it only applies to `issued` or `overdue` invoices. A draft or a scheduled invoice is not the fiscal invoice yet, and a cancelled or annulled one no longer is. - [invoice_cannot_be_sent](https://docs.factuarea.com/errors/invoice_cannot_be_sent): The invoice is voided or cancelled: it no longer represents a valid operation, so its PDF is not delivered to the recipient. - [invoice_due_date_not_last_instalment](https://docs.factuarea.com/errors/invoice_due_date_not_last_instalment): The invoice has a payment schedule and its due date (`due_on`) is missing or is not the date of the last installment, which is when the invoice falls due. - [invoice_invalid_status_transition](https://docs.factuarea.com/errors/invoice_invalid_status_transition): The target status is unreachable from the current one. The document lifecycle is directed: `draft` moves to `scheduled`, `issued` or `cancelled`, `scheduled` back to `draft` or on to `issued`, `issued` to `overdue` or `annulled`, `overdue` to `annulled`, and `cancelled` and `annulled` are terminal. The lifecycle is the same in every API version; before `2026-10-01` the `issued` status is published as `sent`. Being paid is not a step of that lifecycle: it is read from the payment ledger. - [invoice_not_cancellable_in_current_state](https://docs.factuarea.com/errors/invoice_not_cancellable_in_current_state): Cancelling withdraws a draft that is not yet fiscally binding, so it only applies while the invoice is `draft`. - [invoice_not_correctable_in_current_state](https://docs.factuarea.com/errors/invoice_not_correctable_in_current_state): A corrective invoice can only be issued against an invoice that is already issued, paid or not: `issued` or `overdue` (an issued invoice is published as `sent` before API version `2026-10-01`). A draft, a scheduled, a cancelled or an annulled invoice has nothing to correct. - [invoice_not_deletable_in_current_state](https://docs.factuarea.com/errors/invoice_not_deletable_in_current_state): Only `draft` and `cancelled` invoices can be deleted. A numbered invoice never disappears: the correlative sequence must stay auditable. - [invoice_not_editable_in_current_state](https://docs.factuarea.com/errors/invoice_not_editable_in_current_state): Only a draft admits editing. Once issued, the invoice is immutable and its content is frozen along with its fiscal record. - [invoice_not_eligible_for_action](https://docs.factuarea.com/errors/invoice_not_eligible_for_action): The requested action does not apply to this invoice: its type or its current state leaves it outside the scope of the operation. - [invoice_not_found](https://docs.factuarea.com/errors/invoice_not_found): The 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_state](https://docs.factuarea.com/errors/invoice_not_modifiable_in_current_state): The field you are changing is frozen for the current state — for instance the tax regime of an annulled invoice. - [invoice_not_paid](https://docs.factuarea.com/errors/invoice_not_paid): A payment receipt was requested for an invoice with no settled payment, so there is nothing to certify. - [invoice_not_reschedulable_in_current_state](https://docs.factuarea.com/errors/invoice_not_reschedulable_in_current_state): Rescheduling moves the issuing date of an invoice that is waiting in `scheduled`, and this invoice is not waiting. - [invoice_not_schedulable_in_current_state](https://docs.factuarea.com/errors/invoice_not_schedulable_in_current_state): Only a draft can be scheduled: scheduling reserves a future issuing moment without consuming a series number yet. - [invoice_not_unschedulable_in_current_state](https://docs.factuarea.com/errors/invoice_not_unschedulable_in_current_state): Unscheduling returns an invoice from `scheduled` to `draft`, so it only applies while it is still waiting to be issued. - [invoice_not_unsendable_in_current_state](https://docs.factuarea.com/errors/invoice_not_unsendable_in_current_state): Undoing the delivery mark only applies to an issued invoice (`issued` or `overdue`; published as `sent` before API version `2026-10-01`) with no active payments: it clears `sent_at` and `sent_via` and keeps its fiscal status. - [invoice_payment_terms_precondition_required](https://docs.factuarea.com/errors/invoice_payment_terms_precondition_required): The change to the payment schedule did not state which version it is based on. - [invoice_payment_terms_version_conflict](https://docs.factuarea.com/errors/invoice_payment_terms_version_conflict): The payment schedule of the invoice changed after you read it. - [invoice_requires_at_least_one_line](https://docs.factuarea.com/errors/invoice_requires_at_least_one_line): The 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_type_change_not_allowed](https://docs.factuarea.com/errors/invoice_type_change_not_allowed): Only a draft can switch between a complete invoice (`F1`) and a simplified one (`F2`). A corrective invoice, a substitute invoice (`F3`) or a corrective invoice of a simplified one (`R5`) keep their type, and a simplified invoice without a client cannot become a complete one until you set the recipient. - [invoice_without_retained_presentation](https://docs.factuarea.com/errors/invoice_without_retained_presentation): An invoice of the quarter has no retained document presentation (it predates capture or was never initialized), so it cannot be included in the quarterly package. It appears as `error_code` in the `failures` of the quarterly ZIP manifest, where the invoice is left out, and as the subcode of a business rule violation in the quarterly email. - [invoice_year_required_for_ambiguous_number](https://docs.factuarea.com/errors/invoice_year_required_for_ambiguous_number): That 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). - [ip_not_allowed](https://docs.factuarea.com/errors/ip_not_allowed): The key restricts the addresses it accepts, and the request came from one outside that list. - [length_required](https://docs.factuarea.com/errors/length_required): A 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. - [limit_exceeded](https://docs.factuarea.com/errors/limit_exceeded): The company has reached its plan limit of invoices or annual documents; the message says which. In the v1 API it is emitted by time invoicing (`POST /v1/companies/{company}/projects/{project}/time-invoices`), which checks it before creating anything: no draft invoice was generated and no hours were marked as invoiced. - [line_total_checksum_mismatch](https://docs.factuarea.com/errors/line_total_checksum_mismatch): The `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_invalid](https://docs.factuarea.com/errors/line_type_invalid): The 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). - [linked_entity_not_found](https://docs.factuarea.com/errors/linked_entity_not_found): The entity to link does not exist, belongs to another company or belongs to a module the company has not subscribed to; all three cases answer the same. It happens when linking (`POST /v1/companies/{company}/tasks/{task}/entity-links`) and also when creating a task with `entity_link` in `POST /v1/companies/{company}/tasks`: in that case the task is NOT created. - [live_credential_required](https://docs.factuarea.com/errors/live_credential_required): A test key tried to change a live account. It only happens on the operations that change the account —members, invitations, ownership, tax ID transfers, NIF portfolio, keys and seats—: a test key cannot alter real data. - [maintenance](https://docs.factuarea.com/errors/maintenance): The platform is in a maintenance window and writes are held back on purpose. - [managed_account_external_ref_in_other_environment](https://docs.factuarea.com/errors/managed_account_external_ref_in_other_environment): The external reference is already used by a managed account of the other environment (live or test). The reference is unique across both environments, and the answer does not name that account because this environment does not list it. Nothing was written. - [managed_account_not_claimable](https://docs.factuarea.com/errors/managed_account_not_claimable): The managed account is a test one, and a test account is never claimed: it has no claim voucher to issue or reissue. - [managed_account_plan_not_self_serve](https://docs.factuarea.com/errors/managed_account_plan_not_self_serve): The `enterprise` plan was requested for a managed account. A managed account is created or changed on emprendedor or empresario; enterprise is only assigned by Factuarea under contract. - [managed_account_provider_in_trial](https://docs.factuarea.com/errors/managed_account_provider_in_trial): The provider account is on its trial period and requested a live managed account, which is charged. During the trial only test managed accounts can be created. - [managed_accounts_limit_reached](https://docs.factuarea.com/errors/managed_accounts_limit_reached): The provider account already has as many live managed accounts under active management as its cap allows. Test managed accounts do not count towards that cap. - [mapping_header_not_found](https://docs.factuarea.com/errors/mapping_header_not_found): A column in the import mapping does not exist in the uploaded file headers. - [max_api_keys_exceeded](https://docs.factuarea.com/errors/max_api_keys_exceeded): The company reached the number of API keys its plan allows. - [max_retries_exceeded](https://docs.factuarea.com/errors/max_retries_exceeded): It only applies to the EVENTS of the NO VERI*FACTU mode (`POST /v1/companies/{company}/verifactu/events/{id}/retry`): the event exhausted its transmission attempts. Billing records have NO retry limit — art. 16.4 of Order HAC/1177/2024 requires retrying at least once an hour while the incident lasts — so no record retry returns this code any more. - [max_webhook_endpoints_exceeded](https://docs.factuarea.com/errors/max_webhook_endpoints_exceeded): The company reached the number of webhook endpoints its add-on tier allows. - [mcp_guardrail_violation](https://docs.factuarea.com/errors/mcp_guardrail_violation): The 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`). - [member_is_last_owner](https://docs.factuarea.com/errors/member_is_last_owner): The operation would leave the NIF with nobody able to administer it: the member being removed, or demoted to a role without administration, is the last one holding the `owner` or `admin` role in that NIF. - [member_not_found](https://docs.factuarea.com/errors/member_not_found): The identifier matches nobody on the account team: either that person was never a member of the authenticated company, or they belong to a different one. The account surface answers both cases alike. - [metadata_too_many_keys](https://docs.factuarea.com/errors/metadata_too_many_keys): The `metadata` object exceeds the limit of 50 keys per resource. - [metadata_value_too_long](https://docs.factuarea.com/errors/metadata_value_too_long): One value of `metadata` exceeds 500 characters once serialised to text. - [method_not_allowed](https://docs.factuarea.com/errors/method_not_allowed): The path exists but does not accept the HTTP verb used. - [missing_api_key](https://docs.factuarea.com/errors/missing_api_key): The request carries no credentials: neither the `Authorization` header nor `X-API-Key`. - [missing_required_param](https://docs.factuarea.com/errors/missing_required_param): A legacy form request found a required field missing. Endpoints already migrated to the canonical parsers report the same situation as `parameter_missing`. It is also returned for an invoice, quote, proforma, delivery note or recurring invoice line sent without `tax_rate` when neither its product has an assigned tax nor your company has a default VAT for that document type: `error.param` is `lines.N.tax_rate` and `error.line_index` is the zero-based position of that line. `POST /v1/companies/{company}/invoices` also returns it when you ask for the email sending (`options.send_automatically`) and there is no possible recipient — no client, or a client with no email, and no `options.send_to`: `error.param` is `options.send_to` and no invoice is created. - [mode_switch_blocked_until_year_end](https://docs.factuarea.com/errors/mode_switch_blocked_until_year_end): VeriFactu 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. - [module_not_available_in_sandbox](https://docs.factuarea.com/errors/module_not_available_in_sandbox): The resource belongs to a module vetoed in test mode. Sandbox never touches AEAT, banks or real billing, so those modules stay out on purpose. - [module_not_grantable](https://docs.factuarea.com/errors/module_not_grantable): One of the sections in `grants` cannot be granted: it is not an administrator-only section (a member already reaches it with normal permissions) or the company does not have it in its plan. - [module_upgrade_required](https://docs.factuarea.com/errors/module_upgrade_required): The current plan does not include the requested OCR capability. - [monthly_quota_exceeded](https://docs.factuarea.com/errors/monthly_quota_exceeded): The company exhausted the monthly call quota its plan includes. - [monthly_requires_month_segmented_format](https://docs.factuarea.com/errors/monthly_requires_month_segmented_format): The 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. - [nif_transfer_expired](https://docs.factuarea.com/errors/nif_transfer_expired): The tax ID transfer was genuinely issued, but its validity period ran out. Unlike an unrecognised transfer, this answer only reaches whoever already held a real one, so it reveals nothing new. - [nif_transfer_invalid](https://docs.factuarea.com/errors/nif_transfer_invalid): The tax ID transfer presented authorizes nothing: its secret is mistyped, truncated, already consumed, or was never issued. All of those answer alike on purpose, so the operation cannot be used to probe which transfers exist. - [no_invoices_in_period](https://docs.factuarea.com/errors/no_invoices_in_period): The quarterly operation found no invoices in the requested period, so there is nothing to package or send. - [notification_not_found](https://docs.factuarea.com/errors/notification_not_found): The identifier does not match any notification of the authenticated company, or the notification fell out of the retention window. - [ocr_company_daily_quota_exceeded](https://docs.factuarea.com/errors/ocr_company_daily_quota_exceeded): The company has exhausted its daily OCR quota. - [ocr_company_quota_exceeded](https://docs.factuarea.com/errors/ocr_company_quota_exceeded): The company has exhausted its monthly OCR quota. - [operation_date_after_issue_date](https://docs.factuarea.com/errors/operation_date_after_issue_date): `operation_on` is later than `issued_on`. An operation date after the issue date is only valid for advance payments (regime key 14 or 15). - [operation_regime_invalid](https://docs.factuarea.com/errors/operation_regime_invalid): The operation regime is outside the catalogue `general`, `intracomunitaria`, `importacion_exportacion`, `isp`. - [origin_not_allowed](https://docs.factuarea.com/errors/origin_not_allowed): The request comes from a browser origin that the key does not accept. - [owner_transfer_forbidden](https://docs.factuarea.com/errors/owner_transfer_forbidden): The caller is not allowed to transfer ownership of the account: either they are not the current owner, or the proposed recipient cannot hold it. This is a matter of permission, not of a malformed payload. - [pack_composition_too_small](https://docs.factuarea.com/errors/pack_composition_too_small): A pack needs at least two components, or a single counted product with a quantity of 2 or more. - [pack_group_not_contiguous](https://docs.factuarea.com/errors/pack_group_not_contiguous): The lines of the same pack are not consecutive in the document. Another line sits between them. - [pack_image_limit_reached](https://docs.factuarea.com/errors/pack_image_limit_reached): The pack already has the maximum of 5 images. - [pack_in_use](https://docs.factuarea.com/errors/pack_in_use): The pack is referenced by issued documents, so deleting it would break their composition. - [pack_line_locked](https://docs.factuarea.com/errors/pack_line_locked): A line that belongs to a pack group cannot change its product, quantity, unit price or discount. - [pack_lines_must_be_expanded](https://docs.factuarea.com/errors/pack_lines_must_be_expanded): The lines of a pack cannot be built by hand. The server splits the price among the components of the pack and sets the group data itself. - [pack_not_found](https://docs.factuarea.com/errors/pack_not_found): The identifier does not resolve to any pack of the authenticated company. - [pack_not_sellable](https://docs.factuarea.com/errors/pack_not_sellable): The pack cannot be added to a document: it is archived, inactive, out of its availability dates, or one of its components is inactive. - [pack_price_allocation_impossible](https://docs.factuarea.com/errors/pack_price_allocation_impossible): The pack price cannot be split among its components because they have no price when bought separately. - [pack_price_unreachable](https://docs.factuarea.com/errors/pack_price_unreachable): The requested price including VAT cannot be reached exactly because VAT is rounded line by line. - [pack_print_mode_not_allowed](https://docs.factuarea.com/errors/pack_print_mode_not_allowed): The only print mode is `full_breakdown`: every product of the pack is printed as a regular line with the pack name. - [pack_return_invalid](https://docs.factuarea.com/errors/pack_return_invalid): The return of a pack component in a corrective invoice breaks the rules of returns. The pack is not in the invoice being corrected, the product is not one of its components, the quantity is not negative, the price differs from the original split price or more units are returned than were sold. - [pack_snapshot_invalid](https://docs.factuarea.com/errors/pack_snapshot_invalid): The pack snapshot sent with the document line is unsigned, altered or malformed. - [parameter_invalid](https://docs.factuarea.com/errors/parameter_invalid): A 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_boolean](https://docs.factuarea.com/errors/parameter_invalid_boolean): A parameter that must be a boolean received a value outside the accepted representations (`true`/`false`, `1`/`0`). - [parameter_invalid_cursor](https://docs.factuarea.com/errors/parameter_invalid_cursor): The `starting_after` or `ending_before` cursor is not a valid UUID, so it cannot point at any row of the collection. - [parameter_invalid_empty](https://docs.factuarea.com/errors/parameter_invalid_empty): A 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_enum](https://docs.factuarea.com/errors/parameter_invalid_enum): The 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`, and it is the main code (400). On operations that validate a form or a query parameter with rules (for example `format` on the invoice PDFs) it arrives as an entry of `error.errors[]`, with its `allowed_values`, inside a 422 `invalid_param_value`. - [parameter_invalid_format](https://docs.factuarea.com/errors/parameter_invalid_format): The 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_integer](https://docs.factuarea.com/errors/parameter_invalid_integer): A parameter that must be a whole number received something that cannot be parsed as one, such as `limit=abc`. - [parameter_invalid_iso8601](https://docs.factuarea.com/errors/parameter_invalid_iso8601): A range filter (`gte`, `lte`, `gt`, `lt`) received a value that is neither numeric nor an ISO 8601 date. - [parameter_invalid_range](https://docs.factuarea.com/errors/parameter_invalid_range): A numeric parameter fell outside its accepted bounds. The usual case is `limit`, which must be between 1 and 100. - [parameter_invalid_string](https://docs.factuarea.com/errors/parameter_invalid_string): A parameter that must be text received an array, an object or a value that cannot be read as a string. - [parameter_invalid_url](https://docs.factuarea.com/errors/parameter_invalid_url): A 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_uuid](https://docs.factuarea.com/errors/parameter_invalid_uuid): An identifier field received a value that is not a valid UUID. Every v1 resource id is a UUID. - [parameter_invalid_value](https://docs.factuarea.com/errors/parameter_invalid_value): The 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_missing](https://docs.factuarea.com/errors/parameter_missing): The endpoint requires a parameter that the request did not carry. `error.param` names it. - [parameter_unknown](https://docs.factuarea.com/errors/parameter_unknown): The request carries a parameter the endpoint does not accept: a filter outside its allowlist, a `sort` field that is not sortable, the offset-style `page` — v1 paginates by cursor — or a header that has been retired from v1. - [payload_too_large](https://docs.factuarea.com/errors/payload_too_large): The request body exceeds the accepted size: 1 MB as a rule, 6 MB on the endpoints that accept files. - [payment_already_reversed](https://docs.factuarea.com/errors/payment_already_reversed): The 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_method_invalid](https://docs.factuarea.com/errors/payment_method_invalid): Same closed allowlist as `invalid_payment_method`, reported when the value is rejected while reading the payment method field of the payload. - [payment_method_required](https://docs.factuarea.com/errors/payment_method_required): Adding or activating an additional tax ID charges its fee immediately, and the account operates in live mode with no payment method on file. Nothing was charged and no change was written. - [payment_reversal_invalid](https://docs.factuarea.com/errors/payment_reversal_invalid): The reversal note is longer than the 500 characters allowed. - [payment_reversal_reason_invalid](https://docs.factuarea.com/errors/payment_reversal_reason_invalid): The 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_mismatch](https://docs.factuarea.com/errors/payout_reconciliation_amount_mismatch): The confirmed amount does not match the net amount of the payout, so the reconciliation would close with a difference nobody accounts for. - [pdf_artifact_not_found](https://docs.factuarea.com/errors/pdf_artifact_not_found): The PDF artifact does not exist for this company, or it was a preview that has expired. - [pdf_artifact_not_ready](https://docs.factuarea.com/errors/pdf_artifact_not_ready): The PDF is still being prepared. - [pdf_commercial_identity_not_found](https://docs.factuarea.com/errors/pdf_commercial_identity_not_found): The commercial identity does not exist in this company. - [pdf_commercial_identity_required](https://docs.factuarea.com/errors/pdf_commercial_identity_required): The brand mode of the template (logo or image) needs a commercial identity and the company has no default one to fall back on. - [pdf_commercial_identity_unavailable](https://docs.factuarea.com/errors/pdf_commercial_identity_unavailable): The commercial identity exists but is archived or incompatible with this operation. - [pdf_engine_profile_unavailable](https://docs.factuarea.com/errors/pdf_engine_profile_unavailable): The PDF rendering profile is unavailable. - [pdf_engine_unreachable](https://docs.factuarea.com/errors/pdf_engine_unreachable): The PDF engine did not answer (down, restarting or in the middle of a deployment). It is transient: the same request works when the engine is back, and nothing was created or changed. - [pdf_generation_budget_exceeded](https://docs.factuarea.com/errors/pdf_generation_budget_exceeded): The 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). - [pdf_generation_failed](https://docs.factuarea.com/errors/pdf_generation_failed): The rendering service could not produce the PDF. The document and its data are intact — what failed is the file. - [pdf_image_resource_unavailable](https://docs.factuarea.com/errors/pdf_image_resource_unavailable): The PDF image resource is unavailable. - [pdf_legal_source_changed](https://docs.factuarea.com/errors/pdf_legal_source_changed): The current legal source no longer matches this retained presentation. - [pdf_library_association_coverage_incomplete](https://docs.factuarea.com/errors/pdf_library_association_coverage_incomplete): The platform could not verify every default, series or recurrence that uses the template, so the impact of the operation cannot be guaranteed. The failure is on our side. - [pdf_library_impact_conflict](https://docs.factuarea.com/errors/pdf_library_impact_conflict): The defaults, series or recurrences affected by the operation changed after you reviewed its impact. - [pdf_main_template_required](https://docs.factuarea.com/errors/pdf_main_template_required): The company already works with the PDF template library, where the design (`pdf_template`) and accent colour (`accent_color`) of the personalization are applied to its main template, and it has no main template to apply them to. - [pdf_original_corrupt](https://docs.factuarea.com/errors/pdf_original_corrupt): The integrity of the original PDF cannot be verified. - [pdf_original_layout_unavailable](https://docs.factuarea.com/errors/pdf_original_layout_unavailable): The layout the original PDF was generated with is no longer available in this version of Factuarea. - [pdf_original_unavailable](https://docs.factuarea.com/errors/pdf_original_unavailable): The original PDF is unavailable. - [pdf_payload_resource_unavailable](https://docs.factuarea.com/errors/pdf_payload_resource_unavailable): The resources required to prepare the PDF are unavailable. - [pdf_presentation_conflict](https://docs.factuarea.com/errors/pdf_presentation_conflict): The presentation changed after you read it, so the `expected_version` you sent is stale. - [pdf_presentation_context_changed](https://docs.factuarea.com/errors/pdf_presentation_context_changed): The data the preview was built from (document, company or template context) changed after the preview was produced. - [pdf_presentation_etag_mismatch](https://docs.factuarea.com/errors/pdf_presentation_etag_mismatch): The ETag sent in `If-Match` no longer matches the stored presentation, which was modified after you read it. - [pdf_presentation_invalid](https://docs.factuarea.com/errors/pdf_presentation_invalid): The presentation does not satisfy a field or content rule. - [pdf_presentation_not_found](https://docs.factuarea.com/errors/pdf_presentation_not_found): The document presentation does not exist for this company or does not belong to the document you queried. - [pdf_presentation_not_ready](https://docs.factuarea.com/errors/pdf_presentation_not_ready): The revisioned presentation is not available for this company yet: its activation is pending. - [pdf_presentation_precondition_required](https://docs.factuarea.com/errors/pdf_presentation_precondition_required): The change to the presentation did not state which version it is based on. - [pdf_signature_personal_data_forgotten](https://docs.factuarea.com/errors/pdf_signature_personal_data_forgotten): Personal signature data for this presentation has been erased. - [pdf_template_access_denied](https://docs.factuarea.com/errors/pdf_template_access_denied): The credential or user does not have permission to perform this operation on the PDF template library. - [pdf_template_archived](https://docs.factuarea.com/errors/pdf_template_archived): The PDF template is archived, and an archived template cannot be assigned or edited. - [pdf_template_asset_conflict](https://docs.factuarea.com/errors/pdf_template_asset_conflict): A template asset with that identifier already exists, so the upload would overwrite it. - [pdf_template_asset_not_found](https://docs.factuarea.com/errors/pdf_template_asset_not_found): The template asset (logo, image or font) does not exist in this company or was removed. - [pdf_template_default_replacement_required](https://docs.factuarea.com/errors/pdf_template_default_replacement_required): Archiving the template would leave defaults or associations without a template, and no replacement was given for them. - [pdf_template_not_found](https://docs.factuarea.com/errors/pdf_template_not_found): The PDF template does not exist in this company. - [pdf_template_precondition_failed](https://docs.factuarea.com/errors/pdf_template_precondition_failed): The ETag sent in `If-Match` no longer matches the stored template, which was modified after you read it. - [pdf_template_precondition_required](https://docs.factuarea.com/errors/pdf_template_precondition_required): Changing the template requires stating the version it is based on, and none was sent. - [pdf_template_version_conflict](https://docs.factuarea.com/errors/pdf_template_version_conflict): The template was modified after you read it, so the `expected_version` you sent is stale. - [permissions_not_applicable_to_administrator](https://docs.factuarea.com/errors/permissions_not_applicable_to_administrator): The member is an `owner` or `admin` of the account: they hold every permission of their plan and take neither restrictions nor section grants. - [permissions_not_applicable_to_employee](https://docs.factuarea.com/errors/permissions_not_applicable_to_employee): The person is an employee of the employee portal: their access is governed by the portal, not by the section matrix, so they take neither restrictions nor grants. - [plan_limit_exceeded](https://docs.factuarea.com/errors/plan_limit_exceeded): The company has reached a resource limit for its plan. - [platform_account_subscriptions_owned_by_billing](https://docs.factuarea.com/errors/platform_account_subscriptions_owned_by_billing): The connected Stripe account is the platform's own account: Factuarea's subscription fees are invoiced by Billing directly, so that account does not support subscription autoinvoicing (`subscription_autoinvoicing_enabled`). - [portfolio_max_api_keys_exceeded](https://docs.factuarea.com/errors/portfolio_max_api_keys_exceeded): The account already holds the maximum number of ACTIVE credentials that a portfolio allows. The cap applies once the account has two or more real tax IDs and is counted over all the active credentials of the account, not per tax ID, so adding another tax ID to mint its credential will not let you create this one either. - [portfolio_monthly_quota_exceeded](https://docs.factuarea.com/errors/portfolio_monthly_quota_exceeded): The portfolio MONTHLY quota is exhausted. It is counted over the whole account — all its tax IDs together — so one tax ID's consumption exhausts everyone's. - [portfolio_rate_limit_exceeded](https://docs.factuarea.com/errors/portfolio_rate_limit_exceeded): The per-minute ceiling you hit belongs to the PORTFOLIO — an account with two or more real tax IDs, where the requests of all its credentials add up whichever tax ID they reach — not to this credential nor to this company. That is why neither spreading traffic across credentials nor adding another tax ID to the account changes anything: everything keeps counting in the same bucket. - [preparation_required](https://docs.factuarea.com/errors/preparation_required): Prepare the PDF for this presentation before requesting it. - [price_list_in_use](https://docs.factuarea.com/errors/price_list_in_use): The price list is assigned to clients or drafts, and deleting it would leave those price references without their source. - [price_list_item_not_found](https://docs.factuarea.com/errors/price_list_item_not_found): The item does not exist in the price list: it was already removed or the identifier belongs to another price list. - [price_list_not_found](https://docs.factuarea.com/errors/price_list_not_found): The identifier does not resolve to any price list of the authenticated company. - [privileged_scope_required](https://docs.factuarea.com/errors/privileged_scope_required): The operation requires the account provider privilege (`accounts:read` or `accounts:write`) and it is not met: either the key's account has not been granted it, or the person who issued the key is no longer an owner or administrator of the account. Both causes answer alike. - [product_in_use](https://docs.factuarea.com/errors/product_in_use): The product is referenced by issued documents or by other catalogue entries, and removing it would leave those references dangling. - [product_not_found](https://docs.factuarea.com/errors/product_not_found): The identifier does not resolve to any product of the authenticated company. - [profile_not_found](https://docs.factuarea.com/errors/profile_not_found): The `{company}` path segment names a company that does not exist or is not within the credential's NIF scope. Both cases answer the same so that the API never reveals companies of other accounts. - [proforma_already_accepted](https://docs.factuarea.com/errors/proforma_already_accepted): The customer already accepted the pro forma, and acceptance is registered once. - [proforma_already_rejected](https://docs.factuarea.com/errors/proforma_already_rejected): The pro forma is already marked as rejected. - [proforma_cannot_be_accepted](https://docs.factuarea.com/errors/proforma_cannot_be_accepted): Acceptance does not apply from the current state: an invoiced, cancelled or expired pro forma no longer admits it. - [proforma_cannot_be_rejected](https://docs.factuarea.com/errors/proforma_cannot_be_rejected): Rejection does not apply from the current state: once invoiced, cancelled or expired, the pro forma is closed. - [proforma_cannot_be_sent](https://docs.factuarea.com/errors/proforma_cannot_be_sent): Sending by email does not apply to a pro forma in a terminal state: there is no live offer to deliver. - [proforma_invalid_status_transition](https://docs.factuarea.com/errors/proforma_invalid_status_transition): The 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_state](https://docs.factuarea.com/errors/proforma_not_convertible_in_current_state): Converting 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_state](https://docs.factuarea.com/errors/proforma_not_deletable_in_current_state): Only a draft pro forma can be deleted. Once it has been accepted, rejected or invoiced, it is part of the commercial trail. - [proforma_not_draft](https://docs.factuarea.com/errors/proforma_not_draft): The operation only makes sense while the pro forma is a draft, and this one has already moved on. - [proforma_not_editable_in_current_state](https://docs.factuarea.com/errors/proforma_not_editable_in_current_state): Only a draft pro forma admits editing. Once it is accepted, rejected, expired, invoiced or cancelled, its content is settled. - [proforma_not_found](https://docs.factuarea.com/errors/proforma_not_found): The identifier does not resolve to any pro forma of the authenticated company. - [proforma_requires_at_least_one_line](https://docs.factuarea.com/errors/proforma_requires_at_least_one_line): The pro forma has no lines, so there is no amount to put in front of the customer. - [project_archived](https://docs.factuarea.com/errors/project_archived): The project is archived and accepts neither new tasks nor tasks being moved into it. Archiving freezes the project without deleting it. - [project_column_not_found](https://docs.factuarea.com/errors/project_column_not_found): The column does not exist, belongs to another project or belongs to another company; all three cases answer the same. A column is only addressable inside the project that contains it. - [project_has_no_columns](https://docs.factuarea.com/errors/project_has_no_columns): The task is being placed on the board, but the project has no column to put it in. An active task always lives in a column. - [project_integration_already_connected](https://docs.factuarea.com/errors/project_integration_already_connected): The project already has an integration of that type, or is already connected to another repository. Each project accepts one integration per type, so that events are not duplicated. - [project_integration_not_found](https://docs.factuarea.com/errors/project_integration_not_found): The project integration does not exist or belongs to another company; both cases answer the same. Forge and chat integrations are managed only from the web application, not from the v1 API. - [project_key_in_use](https://docs.factuarea.com/errors/project_key_in_use): The short key is already used by another project of the company, or is still reserved as the former key of a project that changed it. The key names the tasks (`WEB-42`), so it cannot repeat within the company. - [project_not_found](https://docs.factuarea.com/errors/project_not_found): There is no project with that identifier or key in the authenticated company. A project belonging to another company answers exactly the same, so the response never reveals whether it exists elsewhere. - [promotion_not_found](https://docs.factuarea.com/errors/promotion_not_found): The identifier does not resolve to any offer of the authenticated company. - [promotion_read_only](https://docs.factuarea.com/errors/promotion_read_only): The offer has ended or been cancelled, so it is read-only and accepts no further changes. - [promotion_started](https://docs.factuarea.com/errors/promotion_started): The offer has already started and is part of the price history. A started offer only allows changing its end date and cannot be deleted. - [provisioning_account_claimed](https://docs.factuarea.com/errors/provisioning_account_claimed): The holder has already claimed this managed account and runs it on their own: it can no longer be claimed again, have its claim voucher reissued or be provisioned again with the same external reference. - [public_link_expires_at_exceeds_max_days](https://docs.factuarea.com/errors/public_link_expires_at_exceeds_max_days): The requested expiry for the public link goes beyond the maximum window your plan allows for shared documents. - [purchase_invoice_already_exists](https://docs.factuarea.com/errors/purchase_invoice_already_exists): That supplier already has an expense 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_state](https://docs.factuarea.com/errors/purchase_invoice_not_deletable_in_current_state): Only draft and cancelled expenses can be deleted. A pending or paid one is part of the expense ledger. - [purchase_invoice_not_draft](https://docs.factuarea.com/errors/purchase_invoice_not_draft): The operation only applies while the expense is a draft, and this one has already been registered. - [purchase_invoice_not_editable_in_current_state](https://docs.factuarea.com/errors/purchase_invoice_not_editable_in_current_state): Only a draft expense can be edited. Once registered as pending, paid or cancelled, its content backs an accounting entry. - [purchase_invoice_not_found](https://docs.factuarea.com/errors/purchase_invoice_not_found): The identifier does not resolve to any expense of the authenticated company. - [purchase_invoice_requires_at_least_one_line](https://docs.factuarea.com/errors/purchase_invoice_requires_at_least_one_line): The expense has no lines, so there is no amount nor deductible VAT to record. - [purchase_scan_already_converted](https://docs.factuarea.com/errors/purchase_scan_already_converted): The scan is already linked to an expense. - [purchase_scan_not_found](https://docs.factuarea.com/errors/purchase_scan_not_found): The scan does not exist or does not belong to the active company. - [purchase_scan_retry_not_allowed](https://docs.factuarea.com/errors/purchase_scan_retry_not_allowed): The scan cannot be retried in its current status. - [purchase_scan_review_incomplete](https://docs.factuarea.com/errors/purchase_scan_review_incomplete): Required data is missing or the reviewed amounts do not reconcile. - [purchase_scan_source_unavailable](https://docs.factuarea.com/errors/purchase_scan_source_unavailable): The scan original was purged or is no longer available in secure storage. - [quote_already_accepted](https://docs.factuarea.com/errors/quote_already_accepted): The quote was already approved, and approval is registered once. - [quote_already_rejected](https://docs.factuarea.com/errors/quote_already_rejected): The quote is already marked as rejected. - [quote_cannot_be_sent](https://docs.factuarea.com/errors/quote_cannot_be_sent): The quote is rejected, converted, expired or cancelled: it is no longer a live offer to deliver. - [quote_expired](https://docs.factuarea.com/errors/quote_expired): The quote passed its validity date, so the offered conditions are no longer binding and it cannot be approved or converted as is. - [quote_not_found](https://docs.factuarea.com/errors/quote_not_found): The identifier does not resolve to any quote of the authenticated company. - [rate_limit_exceeded](https://docs.factuarea.com/errors/rate_limit_exceeded): The key sent more requests than its rate allows in the current window. - [receipt_not_available](https://docs.factuarea.com/errors/receipt_not_available): There is no receipt to issue because the document has no settled payment behind it. - [record_already_accepted](https://docs.factuarea.com/errors/record_already_accepted): AEAT already accepted the record. Acceptance is terminal and its content is frozen as part of the fingerprint chain. - [record_immutable](https://docs.factuarea.com/errors/record_immutable): The record belongs to an append-only ledger: once written, its fiscal content is closed to changes and to deletion. - [record_not_rejected](https://docs.factuarea.com/errors/record_not_rejected): Only an alta record that AEAT accepted (or accepted with errors) or rejected can be subsanado. This record is in another state — pending remission, submitted with no answer yet or in technical error — which the retry covers, not the subsanación. - [record_not_subsanable](https://docs.factuarea.com/errors/record_not_subsanable): The record cannot be subsanado: it is not a registration (alta) record, it is not the LAST alta of its invoice (a later subsanación replaces it), the invoice is annulled, it is a rejected record whose corrected alta is already waiting to be resent, or it has no source invoice from which its data could be regenerated. - [rectified_invoice_inanulable](https://docs.factuarea.com/errors/rectified_invoice_inanulable): This 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. - [recurring_already_active](https://docs.factuarea.com/errors/recurring_already_active): The 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_active](https://docs.factuarea.com/errors/recurring_invoice_already_active): The recurrence is already running. - [recurring_invoice_already_cancelled](https://docs.factuarea.com/errors/recurring_invoice_already_cancelled): The recurrence was already cancelled, and cancellation is terminal. - [recurring_invoice_already_paused](https://docs.factuarea.com/errors/recurring_invoice_already_paused): The recurrence is already paused, so pausing it again changes nothing. - [recurring_invoice_cancelled_cannot_resume](https://docs.factuarea.com/errors/recurring_invoice_cancelled_cannot_resume): A cancelled recurrence cannot be resumed: cancellation closes it for good, unlike a pause. - [recurring_invoice_cannot_run](https://docs.factuarea.com/errors/recurring_invoice_cannot_run): The 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_completed_cannot_resume](https://docs.factuarea.com/errors/recurring_invoice_completed_cannot_resume): A completed recurrence cannot be resumed or activated: it has already used up its occurrences or passed its end date, so no generation is left pending. - [recurring_invoice_has_generated_invoices](https://docs.factuarea.com/errors/recurring_invoice_has_generated_invoices): The recurrence already produced invoices, and those invoices depend on it for their traceability. - [recurring_invoice_not_found](https://docs.factuarea.com/errors/recurring_invoice_not_found): The identifier does not resolve to any recurrence of the authenticated company. - [recurring_invoice_requires_at_least_one_line](https://docs.factuarea.com/errors/recurring_invoice_requires_at_least_one_line): The recurrence has no lines, so every generated invoice would come out empty. - [recurring_not_active](https://docs.factuarea.com/errors/recurring_not_active): The operation needs a running recurrence and this one is paused, completed or cancelled. Legacy code kept for compatibility with older integrations. - [recurring_presentation_activation_changed](https://docs.factuarea.com/errors/recurring_presentation_activation_changed): The company switched its presentation system on or off twice in a row while the recurring invoice was being generated. The generation stopped without writing anything. - [recurring_presentation_policy_precondition_required](https://docs.factuarea.com/errors/recurring_presentation_policy_precondition_required): The change to the presentation policy did not state which version it is based on. - [recurring_presentation_policy_version_conflict](https://docs.factuarea.com/errors/recurring_presentation_policy_version_conflict): The presentation policy of the recurrence changed after you read it. - [recurring_presentation_unavailable](https://docs.factuarea.com/errors/recurring_presentation_unavailable): When a generation of the recurrence ran, the presentation it is configured to use was not available, so the invoice could not be generated. `details.reason` says what was missing. - [register_sealing_failed](https://docs.factuarea.com/errors/register_sealing_failed): The cryptographic sealing of the record did not complete, so the closure was left unsigned rather than sealed with a broken signature. - [relation_already_exists](https://docs.factuarea.com/errors/relation_already_exists): There is already a pending or active access between these two accounts, and only one can be open for each pair of accounts. - [relation_company_not_in_grantor](https://docs.factuarea.com/errors/relation_company_not_in_grantor): The list of tax IDs of the access is not valid: either it names a tax ID that does not belong to the account granting the access, or it is empty. The error points at the `company_ids` field and does not tell which tax ID fails. - [relation_invitation_expired](https://docs.factuarea.com/errors/relation_invitation_expired): The access invitation exists and is still pending, but its acceptance window ran out, so it can no longer be accepted. - [relation_invitation_invalid](https://docs.factuarea.com/errors/relation_invitation_invalid): The access invitation presented is no good: its secret does not exist, was already used, was revoked or is addressed to another account. All of those answer alike on purpose, so the operation cannot be used to probe other accounts' invitations. - [relation_self_grant_not_allowed](https://docs.factuarea.com/errors/relation_self_grant_not_allowed): The account given cannot receive the access: either it is the same account granting it, or the identifier does not match a valid account. Both cases answer alike. - [relation_transition_not_allowed](https://docs.factuarea.com/errors/relation_transition_not_allowed): The access between accounts is in a state that does not admit the requested change: for example, accepting one that is already active or resending the invitation of one that has ended. - [reminder_not_applicable](https://docs.factuarea.com/errors/reminder_not_applicable): The payment reminder does not apply: the invoice is not `issued` or `overdue` (an issued invoice is published as `sent` before API version `2026-10-01`), there is no recipient email, the public link is missing or disabled, or another reminder went out in the last 24 hours. - [replay_delivery_not_retryable](https://docs.factuarea.com/errors/replay_delivery_not_retryable): Only failed deliveries can be replayed. A delivery that succeeded, or one still in flight, has nothing to resend. - [replay_event_expired](https://docs.factuarea.com/errors/replay_event_expired): The event behind the delivery was purged by the 30-day retention policy, so there is no payload left to resend. - [report_format_invalid](https://docs.factuarea.com/errors/report_format_invalid): The format is outside the catalogue `txt_aeat`, `pdf`, `excel`. - [representation_required](https://docs.factuarea.com/errors/representation_required): The remission mode asks Factuarea to submit your records to AEAT on your behalf, and the company has no current representation — neither revoked nor expired — of the kind that mode needs (the signed Annex I for `social_collaborator`, the registered power of attorney for `power_of_attorney`). - [required_custom_field_missing](https://docs.factuarea.com/errors/required_custom_field_missing): A value is missing for a custom field that the project declares as required; the message names the field. A required field cannot be left empty. - [requires_annulment](https://docs.factuarea.com/errors/requires_annulment): The 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. - [resource_already_exists](https://docs.factuarea.com/errors/resource_already_exists): Creating 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_conflict](https://docs.factuarea.com/errors/resource_conflict): The operation collided with the current state of the resource and no more specific conflict code applies. - [resource_immutable](https://docs.factuarea.com/errors/resource_immutable): The object is closed to changes for this operation: its state or its accounting record forbids modifying it. - [resource_locked](https://docs.factuarea.com/errors/resource_locked): Another operation holds the resource until it finishes: concurrent writes on the same object are serialised instead of interleaved. On `POST /v1/companies/{company}/invoices` with `external_id`, another request with the SAME `external_id` is still in progress and had not finished after waiting 20 seconds. - [resource_not_deletable](https://docs.factuarea.com/errors/resource_not_deletable): The 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_found](https://docs.factuarea.com/errors/resource_not_found): The identifier resolves to nothing visible to the authenticated company. Objects belonging to another company answer exactly the same way, by design. - [reversal_reason_reserved](https://docs.factuarea.com/errors/reversal_reason_reserved): The reason `issued_in_error` is reserved for annulling an invoice that was issued by mistake; it cannot be used to revert a single payment. - [route_not_found](https://docs.factuarea.com/errors/route_not_found): The path does not match any v1 endpoint. It is usually a typo, a missing `/v1` prefix, a path from a different area of the API, or the flat form of a route that the breaking window moved under the company or account segment; in that last case `error.subcode` is `legacy_route_moved`. - [scan_batch_too_large](https://docs.factuarea.com/errors/scan_batch_too_large): The batch exceeds the permitted total size. - [scan_decompression_limit_exceeded](https://docs.factuarea.com/errors/scan_decompression_limit_exceeded): The file exceeds the safe decompression limit. - [scan_file_too_large](https://docs.factuarea.com/errors/scan_file_too_large): A file exceeds the 20 MiB limit. - [scan_page_limit_exceeded](https://docs.factuarea.com/errors/scan_page_limit_exceeded): The document exceeds the configured page limit. - [scan_pixel_limit_exceeded](https://docs.factuarea.com/errors/scan_pixel_limit_exceeded): The document resolution exceeds the safe processing limit. - [scan_storage_unavailable](https://docs.factuarea.com/errors/scan_storage_unavailable): Secure storage for the original is unavailable. - [scanner_admin_required](https://docs.factuarea.com/errors/scanner_admin_required): The action requires scanner administration permissions. - [scheduled_for_in_past](https://docs.factuarea.com/errors/scheduled_for_in_past): `scheduled_for` is not strictly in the future, so there is no waiting period to reserve. - [scope_not_allowed_by_plan](https://docs.factuarea.com/errors/scope_not_allowed_by_plan): One 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_sandbox](https://docs.factuarea.com/errors/scope_not_allowed_in_sandbox): A test key cannot be born with scopes of modules vetoed in sandbox. - [send_failed](https://docs.factuarea.com/errors/send_failed): The document was not delivered by email: the mail provider rejected the message or was unreachable. - [sender_identity_not_verified](https://docs.factuarea.com/errors/sender_identity_not_verified): The 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. - [series_already_archived](https://docs.factuarea.com/errors/series_already_archived): The 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_documents](https://docs.factuarea.com/errors/series_code_immutable_with_documents): Changing the prefix of a series that already issued documents would retroactively rewrite their fiscal identifier, while customers and AEAT hold the original number. - [series_default_kind_change](https://docs.factuarea.com/errors/series_default_kind_change): The series is the default one of its purpose (`invoice_kind`): the default series is per company, document type and purpose, so changing its purpose would leave that purpose without a default series. - [series_format_immutable_with_documents](https://docs.factuarea.com/errors/series_format_immutable_with_documents): The numbering mask of a series can be changed until the first document is issued: after that, the PDF and the AEAT record of the issued documents carry the number in the original format. - [series_has_documents](https://docs.factuarea.com/errors/series_has_documents): The series already numbered documents, so it cannot be removed: the correlative sequence has to stay auditable. - [series_immutable](https://docs.factuarea.com/errors/series_immutable): A series is never deleted through the API: it keeps the documents it numbered and its code is not released. `PUT` and `DELETE` are not operations on a series. - [series_initial_number_creates_gap](https://docs.factuarea.com/errors/series_initial_number_creates_gap): The 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_invoice_kind_invalid](https://docs.factuarea.com/errors/series_invoice_kind_invalid): The series purpose is outside the catalogue `complete`, `simplified`, `corrective`, `simplified_corrective`, or it was sent for a series that is not an invoice series. - [series_invoice_kind_locked](https://docs.factuarea.com/errors/series_invoice_kind_locked): The purpose of a series (`invoice_kind`) is fixed on creation and stops being editable as soon as the series has any invoice: changing it would mix invoice types in one correlative numbering. - [series_invoice_kind_mismatch](https://docs.factuarea.com/errors/series_invoice_kind_mismatch): Invoice series have a fixed purpose (`invoice_kind`): `complete` for complete invoices, `simplified` for simplified invoices, `corrective` for corrective invoices and `simplified_corrective` for corrective invoices of simplified invoices. An invoice is only numbered in a series of its own purpose (RD 1619/2012 arts. 6.1.a, 7.1.a and 15), and the series you chose has another one. - [series_locked_by_verifactu](https://docs.factuarea.com/errors/series_locked_by_verifactu): At 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_found](https://docs.factuarea.com/errors/series_not_found): The identifier does not resolve to any numbering series of the authenticated company. - [series_template_access_denied](https://docs.factuarea.com/errors/series_template_access_denied): The credential or user does not have permission to change the PDF template of this series. - [series_template_incompatible](https://docs.factuarea.com/errors/series_template_incompatible): The template does not support the document type, the purpose (`invoice_kind`) or the number format of the series. - [series_template_precondition_failed](https://docs.factuarea.com/errors/series_template_precondition_failed): The ETag sent in `If-Match` no longer matches the series template resource, which changed after you read it. - [series_template_precondition_required](https://docs.factuarea.com/errors/series_template_precondition_required): The change to the series template did not state the version or resource precondition it is based on. - [series_template_unavailable](https://docs.factuarea.com/errors/series_template_unavailable): The template is archived or otherwise not selectable for this company, so it cannot be assigned to the series. - [series_template_version_conflict](https://docs.factuarea.com/errors/series_template_version_conflict): The PDF template assignment of the series changed after you read it. - [series_type_invalid](https://docs.factuarea.com/errors/series_type_invalid): The document type of the series is outside the catalogue `invoice`, `quote`, `delivery_note`, `proforma`, `purchase_invoice`, `recurring_invoice`. - [series_year_locked](https://docs.factuarea.com/errors/series_year_locked): The 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. - [service_unavailable](https://docs.factuarea.com/errors/service_unavailable): The service, or a dependency it needs, is temporarily unable to answer. - [shopify_api_version_expired](https://docs.factuarea.com/errors/shopify_api_version_expired): The 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_rejected](https://docs.factuarea.com/errors/shopify_credentials_rejected): The 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_unreachable](https://docs.factuarea.com/errors/shopify_store_unreachable): The 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. - [signature_payload_too_large](https://docs.factuarea.com/errors/signature_payload_too_large): The signature image exceeds the accepted size for the field. - [signing_certificate_unavailable](https://docs.factuarea.com/errors/signing_certificate_unavailable): The company has VeriFactu enabled in NO VERI*FACTU mode, where every billing record is signed (Order HAC/1177/2024, arts. 6.c and 14), and there is nothing to sign it with. `error.param` says WHAT is missing, and it is stable: `certificate` = the company certificate is missing, expired or revoked, carries another company's tax id, or its `.p12` file cannot be read (damaged, or the stored password is no longer valid); `representation` = in the third-party remission modes, the representation that lets Factuarea sign on the company's behalf is not active; `system_certificate` = the Factuarea certificate is unavailable or cannot be read. Without a signature there is no valid record, and an issued or annulled invoice cannot be left without its own, so the operation is rejected before it runs. - [sii_excluded](https://docs.factuarea.com/errors/sii_excluded): The company is registered with SII, and SII filers are excluded from the VeriFactu regulation. - [simplified_invoice_cannot_be_substituted](https://docs.factuarea.com/errors/simplified_invoice_cannot_be_substituted): One 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_allowed](https://docs.factuarea.com/errors/simplified_invoice_not_allowed): The 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_invoices_disabled](https://docs.factuarea.com/errors/simplified_invoices_disabled): The company has not enabled simplified invoices, so an invoice of type F2 cannot be created. - [simplified_limit_exceeded](https://docs.factuarea.com/errors/simplified_limit_exceeded): The lines would push the simplified invoice (F2) over the absolute legal cap of EUR 3,000 VAT included. - [sku_already_exists](https://docs.factuarea.com/errors/sku_already_exists): Another product of the company already uses that SKU, and the SKU identifies the item uniquely in the catalogue. - [slug_already_exists](https://docs.factuarea.com/errors/slug_already_exists): The slug is already used, as current or previous slug, by another product or pack of the company. - [social_collaborator_unavailable](https://docs.factuarea.com/errors/social_collaborator_unavailable): The social collaboration agreement with AEAT is not yet in force on this instance, so the `social_collaborator` mode cannot be selected. - [stale_scan_version](https://docs.factuarea.com/errors/stale_scan_version): The scan has changed since it was last read. - [storage_quota_exceeded](https://docs.factuarea.com/errors/storage_quota_exceeded): The account has reached its maximum usage. - [store_already_connected](https://docs.factuarea.com/errors/store_already_connected): That 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_mismatch](https://docs.factuarea.com/errors/store_external_id_mismatch): The 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_found](https://docs.factuarea.com/errors/store_not_found): The 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_allowed](https://docs.factuarea.com/errors/store_url_not_allowed): The 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. - [stripe_account_linked_elsewhere](https://docs.factuarea.com/errors/stripe_account_linked_elsewhere): That Stripe account is already linked and active in another Factuarea company. An active Stripe account can only belong to one company. - [stripe_oauth_exchange_failed](https://docs.factuarea.com/errors/stripe_oauth_exchange_failed): Stripe did not confirm the account authorization: the authorization code expired, was already used or was denied. - [stripe_payout_already_reconciled](https://docs.factuarea.com/errors/stripe_payout_already_reconciled): The payout was already reconciled, and reconciliation is terminal: repeating it would double-count the bank entry. - [stripe_payout_not_found](https://docs.factuarea.com/errors/stripe_payout_not_found): The identifier does not resolve to any payout of the authenticated company. - [suplido_line_cannot_carry_taxes](https://docs.factuarea.com/errors/suplido_line_cannot_carry_taxes): The 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_invoice](https://docs.factuarea.com/errors/suplido_not_allowed_in_simplified_invoice): The 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_reference](https://docs.factuarea.com/errors/suplido_requires_source_invoice_reference): The 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. - [supplier_has_documents](https://docs.factuarea.com/errors/supplier_has_documents): The supplier is referenced by registered expenses, and deleting it would leave those expenses without the party that issued them. - [supplier_not_found](https://docs.factuarea.com/errors/supplier_not_found): The identifier does not resolve to any supplier of the authenticated company. - [system_certificate_unavailable](https://docs.factuarea.com/errors/system_certificate_unavailable): The Factuarea certificate that submits records in the third-party modes is missing, expired or revoked. It is a problem on our side, not in your request. - [system_tax_immutable](https://docs.factuarea.com/errors/system_tax_immutable): The 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_field](https://docs.factuarea.com/errors/system_tax_immutable_field): The update touches a field that is frozen on a system tax; `error.param` names it. - [system_tax_undeletable](https://docs.factuarea.com/errors/system_tax_undeletable): System taxes are part of the shared fiscal catalogue and cannot be removed: deleting one would break the documents that reference it. - [task_already_in_project](https://docs.factuarea.com/errors/task_already_in_project): The task is being moved to the project it is already in, so there is no move to make. - [task_assignee_not_member](https://docs.factuarea.com/errors/task_assignee_not_member): The user given as assignee is not a member of the company. A non-existent user, one from another company or one without membership all answer the same, so that other accounts are not revealed. - [task_attachment_not_found](https://docs.factuarea.com/errors/task_attachment_not_found): The attachment does not exist, belongs to another task or belongs to another company; all three cases answer the same. A deleted attachment can no longer be read or downloaded. - [task_attachment_rejected](https://docs.factuarea.com/errors/task_attachment_rejected): The file is not accepted as an attachment: it is empty, exceeds 10 MB, or its real type —detected from its content (magic bytes), not from the extension or the header— is not allowed. A `surface` other than `description` or `comment` is also rejected. - [task_calendar_feed_not_found](https://docs.factuarea.com/errors/task_calendar_feed_not_found): The calendar feed (iCal) does not exist, is revoked, belongs to another company or is another user's personal feed; all cases answer the same. Only the web application emits it when rotating or revoking feeds, not the v1 API. - [task_column_capacity_exceeded](https://docs.factuarea.com/errors/task_column_capacity_exceeded): The board scope —the column, or the planned or archived status— has run out of the position range used to order its tasks. It is not a plan limit or a permission problem, but the technical ordering ceiling of that scope. - [task_comment_not_editable](https://docs.factuarea.com/errors/task_comment_not_editable): The comment cannot be edited: only its author can change it, and comments imported or brought in by an integration are immutable to preserve what the source said. - [task_comment_not_found](https://docs.factuarea.com/errors/task_comment_not_found): The comment does not exist, belongs to another task or belongs to another company; all three cases answer the same. A comment is only addressable under the task it was written on. - [task_custom_field_not_found](https://docs.factuarea.com/errors/task_custom_field_not_found): The custom field does not exist, belongs to another project or belongs to another company; all three cases answer the same. Each project defines its own fields. - [task_description_too_large](https://docs.factuarea.com/errors/task_description_too_large): The description exceeds the maximum of 100,000 characters, counted on the submitted Markdown before it is sanitised. The ceiling does not depend on the plan: it protects the editor and storage. - [task_entity_link_not_found](https://docs.factuarea.com/errors/task_entity_link_not_found): The link between the task and a document, contact, product or employee does not exist, belongs to another task or belongs to another company; all three cases answer the same. - [task_external_link_not_found](https://docs.factuarea.com/errors/task_external_link_not_found): The external link does not exist, belongs to another task or belongs to another company. A link maintained by an integration (a forge issue or pull request) also answers this way when it is managed as if it were a manual link. - [task_import_run_not_found](https://docs.factuarea.com/errors/task_import_run_not_found): The given import does not exist or belongs to another company; both cases answer the same. Each import has its own identifier, different from the target project's. - [task_label_name_in_use](https://docs.factuarea.com/errors/task_label_name_in_use): The company already has a label with that name; the comparison is case-insensitive. Labels are shared across all the company's projects. - [task_label_not_found](https://docs.factuarea.com/errors/task_label_not_found): There is no label with that identifier in the authenticated company; a label of another company answers the same. Labels belong to the company, not to a specific project. - [task_not_found](https://docs.factuarea.com/errors/task_not_found): There is no task with that identifier or key in the authenticated company. A task of another company —or, in the employee portal, one not assigned to the caller— answers exactly the same. - [task_relation_cycle](https://docs.factuarea.com/errors/task_relation_cycle): The relation would close a cycle of subtasks or blockers: the target task already depends, directly or indirectly, on the source one, and neither could be completed first. - [task_relation_exists](https://docs.factuarea.com/errors/task_relation_exists): These two tasks already have a relation of the same type, in either direction. Repeating it would add no information, so a second one is not created. - [task_relation_not_found](https://docs.factuarea.com/errors/task_relation_not_found): There is no relation with that identifier between tasks of the authenticated company; a relation of another company, or one already deleted, answers the same. - [task_self_relation](https://docs.factuarea.com/errors/task_self_relation): The source and target tasks are the same, and a task cannot be related to itself. - [task_time_entry_invoiced](https://docs.factuarea.com/errors/task_time_entry_invoiced): The time entry is already included in an invoice. While it stays linked it cannot be edited or invoiced again, so that the invoice and the hours do not contradict each other. - [task_time_entry_not_found](https://docs.factuarea.com/errors/task_time_entry_not_found): The time entry does not exist, belongs to another task or belongs to another company; all three cases answer the same. - [task_time_not_invoiceable](https://docs.factuarea.com/errors/task_time_not_invoiceable): The requested hours cannot be invoiced and the message names the reason: the project has no billing client or that client no longer accepts invoices, there is no hourly rate or priced product, an entry is not billable, is running or belongs to another project, there are no billable entries, or the selection is ambiguous. - [task_timer_already_running](https://docs.factuarea.com/errors/task_timer_already_running): You already have a running timer in this company. Each user can have at most one at a time per company, so that recorded time does not overlap between tasks. - [task_timer_not_running](https://docs.factuarea.com/errors/task_timer_not_running): A timer stop was requested, but you have no running timer in this company; it may already have been stopped from another session or device. - [task_upload_link_expired](https://docs.factuarea.com/errors/task_upload_link_expired): The upload link no longer works. The `subcode` says why: `expired`, because the link timed out (it lives 30 minutes from creation), or `consumed`, because it was already used once and each link accepts a single submission. - [task_upload_link_not_found](https://docs.factuarea.com/errors/task_upload_link_not_found): The upload link is not valid: the token is malformed or matches no link, almost always because it was copied incompletely. An expired or already used link answers with `task_upload_link_expired` instead. - [tax_applies_to_invalid](https://docs.factuarea.com/errors/tax_applies_to_invalid): The scope of the tax is outside the catalogue `sale`, `purchase`, `both`. - [tax_code_already_exists](https://docs.factuarea.com/errors/tax_code_already_exists): Another tax of the catalogue already uses that code, and codes identify taxes unambiguously. - [tax_default_axis_disabled](https://docs.factuarea.com/errors/tax_default_axis_disabled): The tax cannot be set as the default because its category (VAT, retention or surcharge) is switched off in the company for the requested document, or in every document it would apply to when you give none. - [tax_id_already_exists](https://docs.factuarea.com/errors/tax_id_already_exists): Another client of the company already holds that tax id, and the tax id identifies the party uniquely inside a company. - [tax_id_required](https://docs.factuarea.com/errors/tax_id_required): The operation needs the tax identification number (NIF, CIF or NIE) of the party involved and the record does not carry one. - [tax_in_use](https://docs.factuarea.com/errors/tax_in_use): The tax is referenced by documents, products or suppliers. Removing it would leave historical documents without their fiscal reference. - [tax_inactive_cannot_be_default](https://docs.factuarea.com/errors/tax_inactive_cannot_be_default): A 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_defaultable_for_document](https://docs.factuarea.com/errors/tax_not_defaultable_for_document): The tax cannot be the default of that document: it is of type `other`, its scope (`applies_to`) does not cover the document, or the document is `recurring_invoice`, which inherits from invoice. - [tax_not_found](https://docs.factuarea.com/errors/tax_not_found): The identifier does not match any tax of the catalogue reachable by this company. - [tax_rate_mismatch](https://docs.factuarea.com/errors/tax_rate_mismatch): The line chooses a tax by id (`tax_rate_id`, `retention_rate_id` or `surcharge_rate_id`) and contradicts it: it declares a `tax_rate`, `retention_rate` or `surcharge_rate` different from that tax's rate, or the tax is of another class than its field (for example a withholding tax in `surcharge_rate_id`). The chosen VAT tax also qualifies the line (regime, AEAT qualification and exemption reason), so both values must match. - [tax_report_not_found](https://docs.factuarea.com/errors/tax_report_not_found): The identifier does not resolve to any tax report of the authenticated company. - [tax_report_type_invalid](https://docs.factuarea.com/errors/tax_report_type_invalid): The report type is outside the catalogue `modelo_303`, `modelo_347`, `modelo_130`. - [tax_type_invalid](https://docs.factuarea.com/errors/tax_type_invalid): The tax type is outside the catalogue `vat`, `retention`, `surcharge`, `other`. - [timeout_seconds_out_of_range](https://docs.factuarea.com/errors/timeout_seconds_out_of_range): `timeout_seconds` falls outside the range 1 to 30 seconds. - [too_many_auth_failures](https://docs.factuarea.com/errors/too_many_auth_failures): Too many failed authentication attempts arrived from the same address, so it is temporarily locked out to stop credential guessing. - [too_many_custom_headers](https://docs.factuarea.com/errors/too_many_custom_headers): The endpoint declares more than 20 custom headers. - [transport_date_in_past](https://docs.factuarea.com/errors/transport_date_in_past): A transport control document must be issued before the transport starts, and one of the transport dates is earlier than today (Europe/Madrid). A draft admits any date; issuing does not. - [transport_document_cannot_be_cancelled](https://docs.factuarea.com/errors/transport_document_cannot_be_cancelled): Only an issued transport document in progress can be cancelled; a draft is deleted instead, and a closed, cancelled or superseded one cannot be cancelled. - [transport_document_cannot_be_closed](https://docs.factuarea.com/errors/transport_document_cannot_be_closed): Only an issued transport document can be closed; this one is a draft, already closed, cancelled or superseded. - [transport_document_cannot_be_deleted](https://docs.factuarea.com/errors/transport_document_cannot_be_deleted): Only a draft can be deleted: an issued transport document is kept as legal evidence for its whole retention period. - [transport_document_cannot_be_edited](https://docs.factuarea.com/errors/transport_document_cannot_be_edited): Only a draft transport document can be edited or partially updated; this one is already issued, closed, cancelled or superseded. - [transport_document_cannot_be_modified](https://docs.factuarea.com/errors/transport_document_cannot_be_modified): Only an issued transport document can be modified, and the modification must leave it with every mandatory datum and at least one shipment. - [transport_document_cannot_be_reopened](https://docs.factuarea.com/errors/transport_document_cannot_be_reopened): Only a manually closed transport document can be reopened, and only before its automatic-close deadline; after an automatic close it stays closed. - [transport_document_cannot_be_superseded](https://docs.factuarea.com/errors/transport_document_cannot_be_superseded): Only an issued transport document in progress can be marked as superseded by the carrier document. - [transport_document_file_unavailable](https://docs.factuarea.com/errors/transport_document_file_unavailable): The PDF files of this transport document were purged when its retention period ended (one year after closing, cancelling or superseding it, and only because the account is closed). The document and its data are kept. - [transport_document_no_changes](https://docs.factuarea.com/errors/transport_document_no_changes): The modification carries exactly the same data as the current version, so there is no new version to publish. - [transport_document_not_found](https://docs.factuarea.com/errors/transport_document_not_found): The identifier does not resolve to any transport control document of the authenticated company, or the public token does not exist. - [transport_document_not_issuable](https://docs.factuarea.com/errors/transport_document_not_issuable): The document cannot be issued: it is not a draft, or it lacks mandatory data of art. 6 of Orden FOM/2861/2012 (parties, tax IDs, shipper address, shipments with origin, destination, goods and declared measure, tractor plate or transport date). - [transport_document_not_sendable](https://docs.factuarea.com/errors/transport_document_not_sendable): The document cannot be emailed: it is not issued or closed, there is no recipient (no `to` and the carrier contact has no email), or `to`, `cc` and `bcc` add up to more than 5 addresses. - [transport_document_parties_immutable](https://docs.factuarea.com/errors/transport_document_parties_immutable): After issuing, the contractual shipper and the effective carrier are fixed: the regulation does not allow changing them in a modification. - [transport_document_pdf_too_large](https://docs.factuarea.com/errors/transport_document_pdf_too_large): The PDF of the version would exceed the 5 MB (5,000,000 bytes) allowed by the regulation because of the amount of data in the document: shipments, goods lines, descriptions or notes. Nothing was saved. - [transport_document_version_limit_reached](https://docs.factuarea.com/errors/transport_document_version_limit_reached): A transport control document holds at most 50 versions and the last one is reserved for cancelling or superseding it, so it accepts no more modifications. Nothing was saved. - [transport_document_version_not_found](https://docs.factuarea.com/errors/transport_document_version_not_found): The transport document exists, but it has no version with the number requested in `version`: its versions go from 1 to the current one (`current_version`). - [transport_outside_spain](https://docs.factuarea.com/errors/transport_outside_spain): The control document only covers domestic transport, and a shipment starts or ends outside Spain. International transport is documented with the CMR consignment note. - [unattended_replay_mismatch](https://docs.factuarea.com/errors/unattended_replay_mismatch): An invoice with that `external_id` was already issued with a different type or total, so the request cannot be treated as a resend of the same sale. It is answered with 409, `code` and `subcode` `unattended_replay_mismatch` and `param=external_id`: the `external_id` identifies ONE operation and does not expire. It is not `idempotency_key_reused`, the 422 of an `Idempotency-Key` reused with a different payload. - [unknown_filter](https://docs.factuarea.com/errors/unknown_filter): A 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. - [unsafe_scan_file](https://docs.factuarea.com/errors/unsafe_scan_file): The original failed security inspection. - [unsupported_api_version](https://docs.factuarea.com/errors/unsupported_api_version): The `Factuarea-Version` header is well formed but names a version outside the supported set. - [unsupported_format](https://docs.factuarea.com/errors/unsupported_format): The requested format is not available for this model: not every filing produces every output. - [unsupported_media_type](https://docs.factuarea.com/errors/unsupported_media_type): A request with a body declared a `Content-Type` other than `application/json`. - [unsupported_purchase_currency](https://docs.factuarea.com/errors/unsupported_purchase_currency): The document currency is not supported for conversion. - [unsupported_purchase_document_type](https://docs.factuarea.com/errors/unsupported_purchase_document_type): The original is a delivery note, order, quote, proforma or another document that does not substantiate a fiscal expense. - [unsupported_scan_format](https://docs.factuarea.com/errors/unsupported_scan_format): The actual file format is unsupported. - [upload_in_flight_budget_exceeded](https://docs.factuarea.com/errors/upload_in_flight_budget_exceeded): The 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. - [validation_failed](https://docs.factuarea.com/errors/validation_failed): The scan data does not meet the stated constraints. - [verifactu_already_submitted](https://docs.factuarea.com/errors/verifactu_already_submitted): The 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_invalid](https://docs.factuarea.com/errors/verifactu_mode_invalid): The mode is outside the catalogue `verifactu` / `no_verifactu`. - [verifactu_not_eligible](https://docs.factuarea.com/errors/verifactu_not_eligible): The 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. When issuing or annulling, the same code with the subcode `signing_certificate_unavailable` means the company, with VeriFactu enabled in NO VERI*FACTU mode, has nothing to sign the record with (`error.param`: `certificate`, `representation` or `system_certificate`, depending on what is missing), and with other `error.param` values that a field of the invoice does not fit the alta record (read `error.param` and `error.message`). - [verifactu_record_not_found](https://docs.factuarea.com/errors/verifactu_record_not_found): The identifier does not match any billing record of the authenticated company. - [verifactu_transmission_failed](https://docs.factuarea.com/errors/verifactu_transmission_failed): The transmission of the record to AEAT did not complete: the endpoint was unreachable or answered with an incident. - [webhook_delivery_not_found](https://docs.factuarea.com/errors/webhook_delivery_not_found): The identifier does not match any delivery attempt, or the delivery falls outside the retention window kept for the history. - [webhook_endpoint_degraded](https://docs.factuarea.com/errors/webhook_endpoint_degraded): The endpoint is degraded after repeated delivery failures, so test pings are refused while it stays in that state. - [webhook_endpoint_not_found](https://docs.factuarea.com/errors/webhook_endpoint_not_found): The identifier does not resolve to any webhook endpoint of the authenticated company. - [webhook_secret_recently_rotated](https://docs.factuarea.com/errors/webhook_secret_recently_rotated): The 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. It answers as a 422 `business_rule_violation` with `error.subcode` `webhook_secret_recently_rotated`; it is not a request limit and consumes no rate-limit bucket. - [woocommerce_credentials_rejected](https://docs.factuarea.com/errors/woocommerce_credentials_rejected): The 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_missing](https://docs.factuarea.com/errors/woocommerce_rest_route_missing): The 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_unreachable](https://docs.factuarea.com/errors/woocommerce_store_unreachable): The 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. - [List all absence balances](https://docs.factuarea.com/api-reference/absence-balances/public-api.v1.absence-balances.list): `GET /v1/companies/{company}/absence-balances` — List your company’s absence balances with cursor-based pagination. - Each balance is accrued, carried-over and consumed days per employee, absence type and year, plus `available_days`. - Filter by `employee_id`, `absence_type_id` (UUID v7) and `year`. - Ledger amounts are decimal strings; `available_days` is rounded up to a whole day. - [Retrieve an absence balance](https://docs.factuarea.com/api-reference/absence-balances/public-api.v1.absence-balances.show): `GET /v1/companies/{company}/absence-balances/{absence_balance}` — Retrieve a single absence balance by its `id` (UUID v7), including its accrued, carried-over, consumed and available days for the employee, absence type and year. A balance belonging to another company returns 404 `absence_balance_not_found` (anti-enumeration). - [Get the team absence calendar](https://docs.factuarea.com/api-reference/absence-calendar/public-api.v1.absence-calendar.show): `GET /v1/companies/{company}/absence-calendar` — Return the monthly absence calendar of your team for a given `year` and `month`: every active employee with their approved absences of that month (each coloured by its absence type) and the public holidays that apply, kept separate from the absences. Optionally scoped to a single `employee_id` (UUID v7). A computed resource: it exposes `employee_id` per member, never an `id`. - [Approve an absence request](https://docs.factuarea.com/api-reference/absence-requests/public-api.v1.absence-requests.approve): `POST /v1/companies/{company}/absence-requests/{absence_request}/approve` — Approve a pending absence request (transition `pending` → `approved`), consuming the employee’s balance. No request body (an optional `note` is accepted). A reviewer cannot approve the request they themselves created (422). For a terminated employee, an absence that ends after their termination date returns 422 `business_rule_violation` (`employee_inactive`) and stays pending. Returns the updated request. - [Cancel an absence request](https://docs.factuarea.com/api-reference/absence-requests/public-api.v1.absence-requests.cancel): `POST /v1/companies/{company}/absence-requests/{absence_request}/cancel` — Cancel an absence request. If it was approved, the consumed balance is released back. No request body. A request belonging to another company returns 404 `absence_request_not_found` (anti-enumeration). Returns the updated request. - [Create an absence request](https://docs.factuarea.com/api-reference/absence-requests/public-api.v1.absence-requests.create): `POST /v1/companies/{company}/absence-requests` — Create an absence request for an employee; returns it with its generated `id` (UUID v7). - Required: `employee_id`, `absence_type_id`, and `start_date`/`end_date` (`YYYY-MM-DD`, end on or after start); `note` is optional. - The amount is working days minus public holidays. - A type that does not require approval is auto-approved and consumes the balance. - [List all absence requests](https://docs.factuarea.com/api-reference/absence-requests/public-api.v1.absence-requests.list): `GET /v1/companies/{company}/absence-requests` — List your company’s absence requests with cursor-based pagination. Supports filtering by `employee_id` (UUID v7), `absence_type_id` (UUID v7), `status` (`pending`/`approved`/`rejected`/`cancelled`) and by date range (`from`/`to`, `YYYY-MM-DD`). - [Reject an absence request](https://docs.factuarea.com/api-reference/absence-requests/public-api.v1.absence-requests.reject): `POST /v1/companies/{company}/absence-requests/{absence_request}/reject` — Reject a pending absence request (transition `pending` → `rejected`). A `reason` is required (422 without it); rejecting neither consumes nor releases balance. Returns the updated request. - [Retrieve an absence request](https://docs.factuarea.com/api-reference/absence-requests/public-api.v1.absence-requests.show): `GET /v1/companies/{company}/absence-requests/{absence_request}` — Retrieve a single absence request by its `id` (UUID v7), including its type, date range, requested amount, lifecycle status and review fields. A request belonging to another company returns 404 `absence_request_not_found` (anti-enumeration). - [Archive an absence policy](https://docs.factuarea.com/api-reference/absence-policies/public-api.v1.absence-policies.archive): `POST /v1/companies/{company}/absence-policies/{absence_policy}/archive` — Archive an absence policy (transition `active` → `archived`), retiring it from use while preserving it. No request body. Returns 422 if it is already archived. Reversible via unarchive. - [Assign a policy to employees](https://docs.factuarea.com/api-reference/absence-policies/public-api.v1.absence-policies.assign): `POST /v1/companies/{company}/absence-policies/{absence_policy}/assign` — Assign the absence policy to one or more employees. `employee_ids` (a non-empty list of UUID v7, each belonging to your company) is required; an unknown employee returns 422, and a terminated employee returns 422 `business_rule_violation` (`employee_inactive`) without assigning anyone. Returns the policy with its updated assigned-employee count. - [List a policy’s assigned employees](https://docs.factuarea.com/api-reference/absence-policies/public-api.v1.absence-policies.assignments): `GET /v1/companies/{company}/absence-policies/{absence_policy}/assignments` — List the employees assigned to this absence policy (their `employee_id` UUID v7 and name), as a flat list under `{ "data": [ … ] }`. - [Configure a policy’s year-end carryover](https://docs.factuarea.com/api-reference/absence-policies/public-api.v1.absence-policies.carryover): `POST /v1/companies/{company}/absence-policies/{absence_policy}/carryover` — Configure how much unused balance carries over at year-end for an absence policy; returns the policy. - `carryover_type` (`none`/`capped`/`unlimited`) is required; `carryover_max_days` is required only when `capped`. - Optional `carryover_expiry_month` (1..12) and `carryover_expiry_day`. - Another company’s policy returns 404 `absence_policy_not_found`. - [Create an absence policy](https://docs.factuarea.com/api-reference/absence-policies/public-api.v1.absence-policies.create): `POST /v1/companies/{company}/absence-policies` — Create an absence policy for the company resolved from the API key; returns it with its generated `id` (UUID v7). - Required: `name`, `allowance_type` (`limited`/`unlimited`), `accrual_method` (`annual`/`monthly`); `allowance_days` is required and positive only when `limited`. - `absence_type_ids` lists covered types (may be empty); a type of another company returns 422. - [List all absence policies](https://docs.factuarea.com/api-reference/absence-policies/public-api.v1.absence-policies.list): `GET /v1/companies/{company}/absence-policies` — List your company’s absence policies with cursor-based pagination. Supports filtering by `status` (`active`/`archived`) and `accrual_method` (`annual`/`monthly`), plus free-text `search` over the policy name. - [Retrieve an absence policy](https://docs.factuarea.com/api-reference/absence-policies/public-api.v1.absence-policies.show): `GET /v1/companies/{company}/absence-policies/{absence_policy}` — Retrieve a single absence policy by its `id` (UUID v7), including the UUIDs of its associated absence types and the count of assigned employees. A policy belonging to another company returns 404 `absence_policy_not_found` (anti-enumeration). - [Unarchive an absence policy](https://docs.factuarea.com/api-reference/absence-policies/public-api.v1.absence-policies.unarchive): `POST /v1/companies/{company}/absence-policies/{absence_policy}/unarchive` — Unarchive an absence policy (transition `archived` → `active`), returning it to use. No request body. Returns 422 if it is already active. - [Unassign a policy from employees](https://docs.factuarea.com/api-reference/absence-policies/public-api.v1.absence-policies.unassign): `POST /v1/companies/{company}/absence-policies/{absence_policy}/unassign` — Remove the assignment of the absence policy from one or more employees. `employee_ids` (a non-empty list of UUID v7) is required; removing an assignment that does not exist is a no-op. Returns the policy with its updated assigned-employee count. - [Update an absence policy](https://docs.factuarea.com/api-reference/absence-policies/public-api.v1.absence-policies.update): `PATCH /v1/companies/{company}/absence-policies/{absence_policy}` — Partially update an absence policy: only the fields present in the payload are changed; omitted fields keep their current value. When `absence_type_ids` is provided it fully replaces the associated types. Returns the updated policy. - [Archive an absence type](https://docs.factuarea.com/api-reference/absence-types/public-api.v1.absence-types.archive): `POST /v1/companies/{company}/absence-types/{absence_type}/archive` — Archive an absence type (transition `active` → `archived`), retiring it from use while preserving it. No request body. Returns 422 if it is already archived. Reversible via unarchive. - [Create an absence type](https://docs.factuarea.com/api-reference/absence-types/public-api.v1.absence-types.create): `POST /v1/companies/{company}/absence-types` — Create an absence type for the authenticated company (resolved from the API key, never from the payload). `name`, `is_paid`, `requires_approval`, `measurement_unit` (`days`/`hours`), `color` (hex `#RRGGBB`) and `visibility` (`everyone`/`managers_only`) are all required. Returns the created type with its generated `id` (UUID v7). - [List all absence types](https://docs.factuarea.com/api-reference/absence-types/public-api.v1.absence-types.list): `GET /v1/companies/{company}/absence-types` — List your company’s absence types with cursor-based pagination. Supports filtering by `status` (`active`/`archived`) and `measurement_unit` (`days`/`hours`), plus free-text `search` over the type name. - [Retrieve an absence type](https://docs.factuarea.com/api-reference/absence-types/public-api.v1.absence-types.show): `GET /v1/companies/{company}/absence-types/{absence_type}` — Retrieve a single absence type by its `id` (UUID v7). A type belonging to another company returns 404 `absence_type_not_found` (anti-enumeration). - [Unarchive an absence type](https://docs.factuarea.com/api-reference/absence-types/public-api.v1.absence-types.unarchive): `POST /v1/companies/{company}/absence-types/{absence_type}/unarchive` — Unarchive an absence type (transition `archived` → `active`), returning it to use. No request body. Returns 422 if it is already active. - [Update an absence type](https://docs.factuarea.com/api-reference/absence-types/public-api.v1.absence-types.update): `PATCH /v1/companies/{company}/absence-types/{absence_type}` — Partially update an absence type: only the fields present in the payload are changed; omitted fields keep their current value. Returns the updated type. - [List agenda items](https://docs.factuarea.com/api-reference/agenda/public-api.v1.agenda.list): `GET /v1/companies/{company}/agenda` — Return a combined agenda between `from` and `to` (at most 93 days): due tasks plus due dates, expiries, tax deadlines, absences and holidays. - `sources` picks the layers; each needs its own read scope, and unreadable layers are left out without error. - The response `sources` lists the layers served; `assignee_id` filters tasks; one page. - [Retrieve the automation catalog](https://docs.factuarea.com/api-reference/automations/public-api.v1.automations.catalog.show): `GET /v1/companies/{company}/automations/catalog` — Return what you need to build a valid automation rule: visible triggers, condition operators and combinators, and actions with their parameter JSON schema. - Visibility follows the company’s plan and modules; labels follow `Accept-Language` (default Spanish). - Trigger fields are served per trigger by `GET /v1/companies/{company}/automations/catalog/triggers/{trigger}/fields`. - [Retrieve the evaluable fields of a trigger](https://docs.factuarea.com/api-reference/automations/public-api.v1.automations.catalog.trigger_fields): `GET /v1/companies/{company}/automations/catalog/triggers/{trigger}/fields` — List the fields you can write conditions against for one trigger: location in the event, type, label and accepted operators. - A trigger outside your visible catalog returns 404, so it cannot be used to probe contracted modules. - A visible trigger with no evaluable fields returns 422. - [Activate an automation rule](https://docs.factuarea.com/api-reference/automations/public-api.v1.automations.rules.activate): `POST /v1/companies/{company}/automations/rules/{rule}/activate` — Put an automation rule into service: every event of its trigger is evaluated against its current version. Returns 200 with the new state. - Only a `draft` or `paused` rule can be activated; an active one returns 422. - Quota and budget are not pre-checked; see `GET /v1/companies/{company}/automations/usage`. - [Create an automation rule](https://docs.factuarea.com/api-reference/automations/public-api.v1.automations.rules.create): `POST /v1/companies/{company}/automations/rules` — Create an automation rule from a trigger, an optional condition tree and an ordered list of actions; the server assigns the `id`. - It is created in `draft` and does not fire until activated via `POST /v1/companies/{company}/automations/rules/{rule}/activate`. - A trigger outside your catalog or an action without adapter returns 422. - [Delete an automation rule](https://docs.factuarea.com/api-reference/automations/public-api.v1.automations.rules.delete): `DELETE /v1/companies/{company}/automations/rules/{rule}` — Delete an automation rule logically: it stops firing and disappears from the API, while versions and run history stay auditable. - Returns 204; not reversible through this API. - A second delete returns 404, like a rule of another company. - [Dry-run an automation rule](https://docs.factuarea.com/api-reference/automations/public-api.v1.automations.rules.dry_run): `POST /v1/companies/{company}/automations/rules/{rule}/dry-run` — Simulate what a rule would do against a sample event: condition match and what each action would resolve to. Executes nothing. - No email, change, quota use or run record; it takes the read scope. - For document rules pass `event_aggregate_id` of a real document, or no step would run. - An unevaluable condition returns 200 with `condition_error`. - [List your automation rules](https://docs.factuarea.com/api-reference/automations/public-api.v1.automations.rules.list): `GET /v1/companies/{company}/automations/rules` — List the company’s automation rules with cursor-based pagination, ordered by `id` ascending. - Filter by `status`, `trigger_type`, creation window (`created[gte]`, `created[lte]`) and search by name with `search`. - A cursor issued for another company yields an empty page. - [Pause an automation rule](https://docs.factuarea.com/api-reference/automations/public-api.v1.automations.rules.pause): `POST /v1/companies/{company}/automations/rules/{rule}/pause` — Stop an active automation rule from firing, keeping its definition and run history. - Returns 200 with the rule in its new state; seals no new version, and it can be activated again. - Only an `active` rule can be paused; anything else returns 422. - [Retrieve an automation rule](https://docs.factuarea.com/api-reference/automations/public-api.v1.automations.rules.show): `GET /v1/companies/{company}/automations/rules/{rule}` — Retrieve a single automation rule by its `id` (UUID v7), with its current definition and the number of the version currently in force. A rule of another company returns 404 `automation_rule_not_found`, indistinguishable from one that never existed (anti-enumeration). - [Update an automation rule](https://docs.factuarea.com/api-reference/automations/public-api.v1.automations.rules.update): `PATCH /v1/companies/{company}/automations/rules/{rule}` — Partially update an automation rule: omitted fields keep their value, and `""` in `description` clears it. - Every edit seals a NEW version and bumps `current_version`; past runs keep their original definition. - The status is unchanged: an active rule stays active. - [List the versions of an automation rule](https://docs.factuarea.com/api-reference/automations/public-api.v1.automations.rules.versions.list): `GET /v1/companies/{company}/automations/rules/{rule}/versions` — List the sealed versions of a rule definition, newest first. - The cursor of this listing is an opaque page-number token: pass `next_cursor` back verbatim, never build it. - A rule of another company returns 200 with an empty list, not 404. - [Retrieve a version of an automation rule](https://docs.factuarea.com/api-reference/automations/public-api.v1.automations.rules.versions.show): `GET /v1/companies/{company}/automations/rules/{rule}/versions/{version}` — Retrieve one frozen version of the definition of a rule by its version number — an ordinal, not a UUID. Unlike the listing, an unknown pair of rule and version returns 404. A version keeps resolving after its rule has been deleted, which is what lets the detail of an old run explain the definition it started from. - [List automation runs](https://docs.factuarea.com/api-reference/automations/public-api.v1.automations.runs.list): `GET /v1/companies/{company}/automations/runs` — List automation runs of the company with cursor pagination, oldest first. - Filter by `status`, `automation_rule_id` or creation window; use `ending_before` to go backwards. - Needs the dedicated `automation_runs:read` scope, because runs embed the triggering event data. - [Replay the parked steps of an automation run](https://docs.factuarea.com/api-reference/automations/public-api.v1.automations.runs.replay): `POST /v1/companies/{company}/automations/runs/{run}/replay` — Rearm every parked step of a run and hand it back to the engine. - The steps EXECUTE FOR REAL (email, webhooks, third parties); confirm with the account owner first. - Run not replayable (in flight or finished cleanly) returns 422 `automation_replay_not_allowed`. - Returns 202 (queued, not finished) with only the run id; check the run or its steps. - [Retrieve an automation run](https://docs.factuarea.com/api-reference/automations/public-api.v1.automations.runs.show): `GET /v1/companies/{company}/automations/runs/{run}` — Retrieve one run with its frozen definition version, the triggering event `data.object` and its steps in order. - The snapshots keep old runs readable after the rule changes. - A run of another company returns 404 `automation_run_not_found`. - [List the steps of an automation run](https://docs.factuarea.com/api-reference/automations/public-api.v1.automations.runs.steps.list): `GET /v1/companies/{company}/automations/runs/{run}/steps` — List the steps of a run in execution order with cursor pagination. - Same step documents as the run detail, without the two heavy frozen snapshots; cheaper to poll. - `step_index` identifies a step: it is what you replay. - [Replay one step of an automation run](https://docs.factuarea.com/api-reference/automations/public-api.v1.automations.runs.steps.replay): `POST /v1/companies/{company}/automations/runs/{run}/steps/{step_index}/replay` — Rearm a single parked step, leaving its siblings untouched. - The step EXECUTES FOR REAL (email, webhooks, third parties); confirm with the account owner first. - `step_index` is the one published by the steps listing; an out-of-range index returns 404. - Returns 202 (queued, not finished) with the run id and the index. - [Retrieve automation usage](https://docs.factuarea.com/api-reference/automations/public-api.v1.automations.usage.show): `GET /v1/companies/{company}/automations/usage` — Read the automation runs consumed in the current period, the plan quota, the reset instant and the warning percentage. - `limit: null` means no automatic ceiling (Enterprise is by contract). - It is the counter the engine enforces; purging history never changes it. - [Preview a change of the additional tax ID seats](https://docs.factuarea.com/api-reference/companies/public-api.v1.additional-nif-seats.preview): `GET /v1/accounts/{account}/additional-nif-seats/preview` — Preview, without charging or writing, setting the contracted additional tax ID seats to `contracted_seats`. - A purchase returns the amount charged today; a reduction returns `0.00`, the `pending_reduction`, `deactivations_required` and the `offer_package_loss`. - Amounts are 2-decimal euro strings; above the account cap it returns 422 `additional_nif_limit_reached`. - 403 `billing_managed_by_provider` when the provider manages billing. - [Retrieve the additional tax ID seats](https://docs.factuarea.com/api-reference/companies/public-api.v1.additional-nif-seats.status): `GET /v1/accounts/{account}/additional-nif-seats` — Return the contracted seats of the additional tax IDs of the account: `quantity` billed, `max_additional_nifs` and the `seats` block (contracted, occupied, free, pending reduction). - `subscribed: false` means no seat subscription is alive; `seats_billable: false` is a legitimate no-charge state (trial, exempt). - Needs `companies:read`; 403 `forbidden_action` when the credential does not reach the account owner. - [Set the contracted additional tax ID seats](https://docs.factuarea.com/api-reference/companies/public-api.v1.additional-nif-seats.update): `PATCH /v1/accounts/{account}/additional-nif-seats` — Set the contracted additional tax ID seats of the account to an absolute `contracted_seats`. - A higher value buys the missing seats now (402 `payment_method_required` or `additional_nif_charge_failed` buys nothing); a lower one is a reduction applied at renewal, without refund. - Going below the occupied seats needs `deactivate` with exactly the surplus (422 `contracted_seats_selection_required`); breaking an offer package needs `accept_offer_package_loss`. - `Idempotency-Key` is mandatory. Above the cap: 422 `additional_nif_limit_reached`. - [Activate a tax ID of the account](https://docs.factuarea.com/api-reference/companies/public-api.v1.companies.activate): `POST /v1/accounts/{account}/companies/{company}/activate` — Reactivate an `inactive` tax ID of the account as an ADDITIONAL tax ID, after the additional tax ID gate. - Gate: 403 `forbidden_action`, 403 `additional_nif_not_in_plan`, 402 `additional_nif_plan_required`. - A free seat covers it; with none, the missing seat is bought and charged at once (402 `payment_method_required`); `active` only if charged. - Send an `Idempotency-Key`. System-suspended: 422 subcode `nif_suspended_by_system`. - [Activate several tax IDs of the account](https://docs.factuarea.com/api-reference/companies/public-api.v1.companies.activate_batch): `POST /v1/accounts/{account}/companies/activate` — Reactivate several `inactive` tax IDs (`company_ids`) atomically, charged in a single invoice. - One invalid or suspended tax ID rejects the whole batch, with no charge. - Same gate as single activation: 403 `forbidden_action`, 402 `additional_nif_plan_required`. - Free seats are used first and the missing ones are bought automatically; send an `Idempotency-Key`. - Charge failure (402 `payment_method_required`): nothing is activated. - [Register a tax ID in the account](https://docs.factuarea.com/api-reference/companies/public-api.v1.companies.create): `POST /v1/accounts/{account}/companies` — Register a new tax ID in the account; `name` and `tax_id` are required. - Duplicate `tax_id` returns 409; one owned by another account returns 422 `business_rule_violation`. - Beyond the first active one it is ADDITIONAL: plan, cap and 402 `payment_method_required` apply. - With no free seat, the missing seat is bought and charged automatically; send an `Idempotency-Key`. - Preview the cost with `GET /v1/accounts/{account}/companies/seat-charge-preview`. - [Retrieve the creation status of a tax ID](https://docs.factuarea.com/api-reference/companies/public-api.v1.companies.creation_status): `GET /v1/accounts/{account}/companies/{company}/creation-status` — Poll the provisioning lifecycle of a tax ID of the account. - Returns `provisioning_status`: `pending`, `awaiting_payment`, `provisioning`, `active` or `failed`. - `payment_setup_url` only while `awaiting_payment`; `failed_reason` only when `failed`. - Test keys go straight to `active`. - [Deactivate a tax ID of the account](https://docs.factuarea.com/api-reference/companies/public-api.v1.companies.deactivate): `POST /v1/accounts/{account}/companies/{company}/deactivate` — Deactivate a tax ID of the account (`active` to `inactive`): it stops operating but its data is kept. - Reversible; no charge, never returns 402; the additional tax ID is released without credit. - The account must keep one active tax ID: 422 subcode `account_must_keep_one_nif`. - [Archive a tax ID of the account](https://docs.factuarea.com/api-reference/companies/public-api.v1.companies.delete): `DELETE /v1/accounts/{account}/companies/{company}` — Archive a tax ID of the account: it moves to `archived`, stops accepting operations and its history is kept. - Never billed (no 402). - Blocked with 422 `business_rule_violation` by open fiscal documents or subcode `account_must_keep_one_nif`. - [Check whether a portfolio NIF can issue](https://docs.factuarea.com/api-reference/companies/public-api.v1.companies.issuing_readiness): `GET /v1/accounts/{account}/companies/{company}/issuing-readiness` — Check whether a NIF within your credential scope is ready to issue invoices: `can_issue`, a closed list of `blockers` and the composing signals. - Neutral read: it never reports plan, quota or price, and never returns a payment-required state. - Unknown, foreign or out-of-scope NIFs all return the same 404 `resource_not_found` (`param: company`). - [List the tax IDs of your account](https://docs.factuarea.com/api-reference/companies/public-api.v1.companies.list): `GET /v1/accounts/{account}/companies` — List the tax IDs of the account that your credential reads, with cursor pagination. - Returns `active` and `inactive` by default; filter with `status` (`archived` is opt-in) or `tax_id`. - `include=readiness` adds a `readiness` object per company; other values return 422 `invalid_param_value`. - [Preview the seat charge of adding a company](https://docs.factuarea.com/api-reference/companies/public-api.v1.companies.seat_charge_preview): `GET /v1/accounts/{account}/companies/seat-charge-preview` — Preview the prorated amount of registering or activating ADDITIONAL tax IDs, without charging. - Use `count` for a batch or `company_ids` for a coverage-aware preview; covered tax IDs cost `0`. - Amounts are 2-decimal euro strings; this read never returns 402 or plan and cap rejections. - Returns 403 `billing_managed_by_provider` when a provider manages billing. - [Retrieve a tax ID of the account](https://docs.factuarea.com/api-reference/companies/public-api.v1.companies.show): `GET /v1/accounts/{account}/companies/{company}` — Retrieve a single tax ID (company) of the account by its `id` (UUID v7). A tax ID that does not exist, is outside the account or is outside what your credential reads returns 404 `resource_not_found` (anti-enumeration), always with the same body. An `{account}` that is not the account of your credential returns 404 `account_not_found`. - [Retrieve invoicing statistics per company](https://docs.factuarea.com/api-reference/companies/public-api.v1.companies.stats): `GET /v1/accounts/{account}/companies/stats` — Return one `company_stats` row per company of the account that your credential reads, with `invoices_count`, `total_invoiced` and `last_invoice`. - Period is `date_from`/`date_to` (`YYYY-MM-DD`, inclusive); default is the current calendar year. - Not paginated: `has_more` is always `false`. A bad date or range returns 422 `invalid_param_value`. - [Update a tax ID of the account](https://docs.factuarea.com/api-reference/companies/public-api.v1.companies.update): `PATCH /v1/accounts/{account}/companies/{company}` — Update the profile of a tax ID of the account (`name`, `business_name`, address, `email`, `phone`); partial, `""` clears a field. - `tax_id` is immutable (sending it returns 422); only an `active` tax ID can be edited. - Never billed (no 402); needs an owner or admin of the account, else 403 `forbidden_action`. - [Verify the creation of a tax ID](https://docs.factuarea.com/api-reference/companies/public-api.v1.companies.verify_creation): `POST /v1/accounts/{account}/companies/{company}/verify-creation` — Reconcile and advance the provisioning of a tax ID against the titular's subscription; no body, idempotent. - While `awaiting_payment`, once a payment method exists it is charged and becomes `active`. - Returns the creation-status resource; never 402: a failed charge leaves it `failed` with its reason. - [Cancel a managed-company-seat offer redemption](https://docs.factuarea.com/api-reference/companies/public-api.v1.gestoria-seat-offer-redemptions.cancel): `POST /v1/companies/{company}/gestoria-seat-offer-redemptions/{id}/cancel` — Cancel a managed-company-seat offer redemption before it is confirmed. - Cancelling never charges; the offer is not consumed. - Use a stable Idempotency-Key and GET the same UUID to read the final state. - Unavailable or other-company codes get the same controlled rejection. - [Confirm a managed-company-seat offer redemption](https://docs.factuarea.com/api-reference/companies/public-api.v1.gestoria-seat-offer-redemptions.confirm): `POST /v1/companies/{company}/gestoria-seat-offer-redemptions/{id}/confirm` — Confirm a managed-company-seat offer redemption, charging the reviewed quote. - Send exactly the reviewed `quote_version` with a stable Idempotency-Key. - After a 202, failure or replay, GET the same UUID until terminal; never create a second purchase. - Existing discounts are never silently stacked or replaced. - [List a managed-company-seat offer redemption](https://docs.factuarea.com/api-reference/companies/public-api.v1.gestoria-seat-offer-redemptions.list): `GET /v1/companies/{company}/gestoria-seat-offer-redemptions` — List a managed-company-seat offer redemptions of the company. - Financial history exposes no private code, profile or Stripe identifiers. - The private offer belongs to the paying company; unavailable or other-company codes get the same rejection. - [Prepare a managed-company-seat offer redemption](https://docs.factuarea.com/api-reference/companies/public-api.v1.gestoria-seat-offer-redemptions.prepare): `POST /v1/companies/{company}/gestoria-seat-offer-redemptions` — Prepare a managed-company-seat offer redemption and its quote without charging. - Preparing never charges or consumes the offer; confirm later with a stable Idempotency-Key. - The private offer belongs to the paying company; unavailable or other-company codes get the same rejection. - Existing discounts are never silently stacked or replaced. - [Refresh the quote for a managed-company-seat offer redemption](https://docs.factuarea.com/api-reference/companies/public-api.v1.gestoria-seat-offer-redemptions.refresh_quote): `POST /v1/companies/{company}/gestoria-seat-offer-redemptions/{id}/quote` — Refresh the quote of a managed-company-seat offer redemption. - Refreshing never charges or consumes the offer; confirm exactly the new `quote_version`. - The private offer belongs to the paying company; unavailable or other-company codes get the same rejection. - [Retrieve a managed-company-seat offer redemption](https://docs.factuarea.com/api-reference/companies/public-api.v1.gestoria-seat-offer-redemptions.show): `GET /v1/companies/{company}/gestoria-seat-offer-redemptions/{id}` — Retrieve a managed-company-seat offer redemption. - GET the same UUID after a 202 or failure until a verified terminal state. - Unknown totals never mean free; no private code or Stripe identifiers are exposed. - [Retrieve the consolidated workforce compliance overview](https://docs.factuarea.com/api-reference/companies/public-api.v1.gestoria.workforce_summary): `GET /v1/accounts/{account}/gestoria/workforce-summary` — Return the consolidated time-tracking compliance panel: one row per `active` company in your credential scope (the owner company excluded). - Each row projects the latest monthly close: closed status, last closed period, balance, overtime and `employee_count`. - Scope-bound: rows come from the tax IDs your credential reaches, never from the payload. - [List your API request logs](https://docs.factuarea.com/api-reference/developers/public-api.v1.developers.request_logs.list): `GET /v1/companies/{company}/request-logs` — List the requests your own integration made against this API, newest first, to debug without a support ticket. - Only requests made with API keys of your account; rows are purged after 30 days. - Not an audit trail. - [Retrieve an API request log](https://docs.factuarea.com/api-reference/developers/public-api.v1.developers.request_logs.show): `GET /v1/companies/{company}/request-logs/{request_id}` — Retrieve one request of your integration by the `request_id` (an opaque `req_...` string) returned in the `X-Request-Id` header. - A request made with a key of another account returns 404. - Same fields as the listing. - [List contact activity](https://docs.factuarea.com/api-reference/contacts/public-api.v1.contacts.activities): `GET /v1/companies/{company}/contacts/{contact}/activities` — List the combined contact timeline with cursor pagination. Filter by `direction` (`sales`, `purchases`, `relationship`) and by document category. Every item exposes public UUIDs and sanitized metadata; internal database identifiers are never returned. - [Archive a contact](https://docs.factuarea.com/api-reference/contacts/public-api.v1.contacts.archive): `POST /v1/companies/{company}/contacts/{contact}/archive` — Archive a contact: a reversible removal that keeps it fully readable (`is_archived: true`). - Always allowed and idempotent: archiving again returns 200 and keeps the first `archived_at`. - Requires `contacts:delete`; undo with `POST /companies/{company}/contacts/{contact}/restore`. - [Assign a contact role](https://docs.factuarea.com/api-reference/contacts/public-api.v1.contacts.assign_contact_role): `POST /v1/companies/{company}/contacts/{contact}/roles/{role}` — Assign `customer`, `supplier`, or `lead` to a contact without changing its other roles. Assigning an already-present role is idempotent and returns the canonical contact. - [Archive contacts in bulk](https://docs.factuarea.com/api-reference/contacts/public-api.v1.contacts.bulk_archive): `POST /v1/companies/{company}/contacts/bulk/archive` — Archive up to 500 contacts by `ids` with partial success. - Always allowed and reversible, one by one, with `POST /companies/{company}/contacts/{contact}/restore`. - Only per-row failure: a UUID the company does not own (`contact_not_found`); the rest still succeed. - [Change contact role status in bulk](https://docs.factuarea.com/api-reference/contacts/public-api.v1.contacts.bulk_change_contact_role_status): `POST /v1/companies/{company}/contacts/bulk/status` — Set one customer, supplier or fiscal lead role to `active` or `inactive` for up to 500 contact `ids`, with partial success per UUID. The operation never changes the other commercial roles or user RBAC. - [Create contacts in bulk](https://docs.factuarea.com/api-reference/contacts/public-api.v1.contacts.bulk_create): `POST /v1/companies/{company}/contacts/bulk-create` — Create or upsert up to 500 canonical contacts. Each row accepts the same identity, cumulative roles and directional profiles as `POST /companies/{company}/contacts`. With `dry_run=true`, validate every row without persisting and return its classification. - [Delete contacts in bulk](https://docs.factuarea.com/api-reference/contacts/public-api.v1.contacts.bulk_delete): `POST /v1/companies/{company}/contacts/bulk-delete` — Delete up to 500 contacts by `ids` with partial success, applying the same soft delete as the single delete. - Irreversible through the API; for a reversible one use `POST /companies/{company}/contacts/bulk/archive`. - Only per-row failure is `contact_not_found`, returned with `id`, `error_code` and `error_message`. - [Change a contact role status](https://docs.factuarea.com/api-reference/contacts/public-api.v1.contacts.change_contact_role_status): `PATCH /v1/companies/{company}/contacts/{contact}/roles/{role}/status` — Set one commercial role to `active` or `inactive`. The other role and the platform RBAC role of every user remain unchanged. - [Create a contact](https://docs.factuarea.com/api-reference/contacts/public-api.v1.contacts.create): `POST /v1/companies/{company}/contacts` — Create one canonical contact with no role or any combination of `customer`, `supplier` and `lead`; the response `id` is a UUID v7. - A repeated `Idempotency-Key` replays the original response without duplicating the contact. - An existing `external_id` is updated idempotently within the company. - [Delete a contact](https://docs.factuarea.com/api-reference/contacts/public-api.v1.contacts.delete): `DELETE /v1/companies/{company}/contacts/{contact}` — Soft delete a contact: it disappears from every read surface and its detail answers 404 `contact_not_found`. - Irreversible through the API (`restore` only unarchives); documents that reference it are preserved. - Releases the tax ID and `external_id`; emits `contact.deleted`. Use `archive` to keep it readable. - [Find a contact by external ID](https://docs.factuarea.com/api-reference/contacts/public-api.v1.contacts.find_by_external_id): `POST /v1/companies/{company}/contacts/find-by-external-id` — Resolve one canonical contact by its integration `external_id` within the authenticated company. Returns 404 `contact_not_found` when the reference is unknown. - [Find a contact by tax ID](https://docs.factuarea.com/api-reference/contacts/public-api.v1.contacts.find_by_tax_id): `POST /v1/companies/{company}/contacts/find-by-tax-id` — Resolve one canonical contact by Spanish tax identifier within the authenticated company. The result includes all cumulative roles, so integrations do not need separate client and supplier lookups. - [Import contacts](https://docs.factuarea.com/api-reference/contacts/public-api.v1.contacts.import): `POST /v1/companies/{company}/contacts/import` — Import contacts from CSV with target roles, field mapping, conflict strategy and optional `dry_run`. - Returns an `import_uuid` with 200 (sync) or 202 (queued); `dry_run` is synchronous and uses no quota. - Exhausted allowance returns 429 `import_row_quota_exceeded`; an empty file 422 subcode `empty_import`. - CSV, TXT, XLSX or XLS up to 10 MB. - [Download the contact import template](https://docs.factuarea.com/api-reference/contacts/public-api.v1.contacts.import_template): `GET /v1/companies/{company}/contacts/import/template` — Download the template accepted by `POST /companies/{company}/contacts/import`, generated from the same column descriptors as the importer. `?format=csv` (default) is a UTF-8 CSV attachment with only the headers; `?format=xlsx` is a workbook with the Data, Instructions, Examples and Allowed values sheets. It contains no company data. - [Download contact import errors](https://docs.factuarea.com/api-reference/contacts/public-api.v1.contacts.imports.errors): `GET /v1/companies/{company}/contacts/imports/{id}/errors.csv` — Download the authorized UTF-8 CSV report with original row_number, field, code and message. Requires contacts:read. Unknown, foreign-company and non-contact imports or an unavailable report return 404 import_not_found. The MCP download_contact_import_errors tool returns identical bytes as file_base64 with filename, mime_type and SHA-256 hash. - [Retrieve a contact import](https://docs.factuarea.com/api-reference/contacts/public-api.v1.contacts.imports.show): `GET /v1/companies/{company}/contacts/imports/{id}` — Retrieve persisted progress and row outcomes using the UUID returned as import_uuid, including synchronous imports. Requires contacts:read. Unknown, foreign-company and non-contact imports return the same 404 import_not_found. Added counts applied create/update/add_role rows; failed imports retain confirmed progress and unprocessed_count. - [List contacts](https://docs.factuarea.com/api-reference/contacts/public-api.v1.contacts.list): `GET /v1/companies/{company}/contacts` — List canonical contacts with cursor pagination. Filter by `roles` (`customer`, `supplier`, `lead`, or the synthetic `unassigned` relationship; CSV or array), `role_match` (`any` or `all`), role status, kind, fiscal identity, external ID, tags, metadata, archive state and creation date. Contacts with cumulative roles appear once and match every role they contain. - [List contact filter options](https://docs.factuarea.com/api-reference/contacts/public-api.v1.contacts.options): `GET /v1/companies/{company}/contacts/options` — Retrieve selectable values for contact forms and filters; `field` is required (`country`, `country_code`, `province`, `city` or `tag`). - Narrow with `search` (max 100 characters), `country_code` and `province`; `limit` defaults to 50 (1-250). - `country` always returns the full ISO catalogue; requires `contacts:read`. - [Preview a contact import](https://docs.factuarea.com/api-reference/contacts/public-api.v1.contacts.preview_import): `POST /v1/companies/{company}/contacts/import/preview` — Validate a contact import without writing. Each row is classified as create, update, add-role, merge candidate, conflict or invalid; ambiguous identities are never merged automatically. A file containing only column headers returns 200 with total 0, no rows and source_headers preserved in their original order, so clients can inspect template columns before adding data. - [Remove a contact role](https://docs.factuarea.com/api-reference/contacts/public-api.v1.contacts.remove_contact_role): `DELETE /v1/companies/{company}/contacts/{contact}/roles/{role}` — Remove one role and its directional profile only when it has no historical or active references. A referenced role returns 422 and can be deactivated instead; removing the final role leaves the contact as unassigned while preserving its identity and history. - [Restore an archived contact](https://docs.factuarea.com/api-reference/contacts/public-api.v1.contacts.restore): `POST /v1/companies/{company}/contacts/{contact}/restore` — Undo the archival of a contact; nothing else changes and roles keep their previous status. - Idempotent: restoring a contact that is not archived returns 200 and writes nothing. - Needs `contacts:write`, not `contacts:delete`. - [Search contacts](https://docs.factuarea.com/api-reference/contacts/public-api.v1.contacts.search): `GET /v1/companies/{company}/contacts/search` — Search contacts by name, fiscal identity, email, phone, mobile or external ID, optionally restricted to customer, supplier or fiscal lead roles and role status. Results are tenant-scoped and cursor-paginated. - [Retrieve a contact](https://docs.factuarea.com/api-reference/contacts/public-api.v1.contacts.show): `GET /v1/companies/{company}/contacts/{contact}` — Retrieve a canonical contact by `id` (UUID v7), including its common identity, roles, directional profiles and bank accounts. A UUID owned by another company returns the same 404 `contact_not_found` as an unknown UUID. - [Get contact statistics](https://docs.factuarea.com/api-reference/contacts/public-api.v1.contacts.stats): `GET /v1/companies/{company}/contacts/stats` — Return aggregate counts for unique canonical contacts and their cumulative customer, supplier and lead roles. A contact with both customer and supplier roles counts once in `total` and once in `dual_role`; role counters intentionally overlap. - [Update a contact](https://docs.factuarea.com/api-reference/contacts/public-api.v1.contacts.update): `PATCH /v1/companies/{company}/contacts/{contact}` — Update only the common identity and contact fields. Roles and directional profiles have explicit endpoints so changing customer data can never overwrite supplier defaults. A duplicate fiscal identity or external ID returns 409. - [Replace the bank accounts of a contact](https://docs.factuarea.com/api-reference/contacts/public-api.v1.contacts.update_bank_accounts): `PATCH /v1/companies/{company}/contacts/{contact}/bank-accounts` — Replace the ENTIRE set of bank accounts of a contact; single accounts cannot be added or dropped. - `bank_accounts` is required: an empty list deletes every account, and omitting it returns 422. - Set invariants: one default collection and one default payment account, no repeated IBAN. - [Update a customer profile](https://docs.factuarea.com/api-reference/contacts/public-api.v1.contacts.update_customer_profile): `PATCH /v1/companies/{company}/contacts/{contact}/customer-profile` — Update sales, collection, tax and DIR3 defaults for the customer role. Supplier defaults are never changed. The contact must already have the customer role. - [Update a supplier profile](https://docs.factuarea.com/api-reference/contacts/public-api.v1.contacts.update_supplier_profile): `PATCH /v1/companies/{company}/contacts/{contact}/supplier-profile` — Update purchase, payment and tax defaults for the supplier role. Customer defaults are never changed. The contact must already have the supplier role. - [Verify a contact against the AEAT census](https://docs.factuarea.com/api-reference/contacts/public-api.v1.contacts.verify_census): `POST /v1/companies/{company}/contacts/census-verification` — Verify a name and Spanish tax identifier against the AEAT census before issuing a document. The operation is stateless and fail-open: AEAT outages return `status: unavailable` rather than a server error. - [Summarize email delivery per document](https://docs.factuarea.com/api-reference/emails/public-api.v1.emails.indicators): `GET /v1/companies/{company}/emails/indicators` — Summarize email delivery for a batch of documents in one call: emails sent, last status, last hand-off and failures per document. - `last_status` and `last_sent_at` describe the hand-off to the outgoing SMTP server, not real delivery. - A `sent` email may still bounce. - [List sent emails](https://docs.factuarea.com/api-reference/emails/public-api.v1.emails.list): `GET /v1/companies/{company}/emails` — List the emails your company sent through the platform, newest first (invoices, quotes, pro formas, delivery notes, reminders). - `status` describes the hand-off to the outgoing SMTP server, not real delivery. - `sent` does not mean the recipient received it. - [Retrieve a sent email](https://docs.factuarea.com/api-reference/emails/public-api.v1.emails.show): `GET /v1/companies/{company}/emails/{email}` — Retrieve one sent email by id: recipient, subject, status, attempts, error message and the document it was sent for. - `status` describes the hand-off to the outgoing SMTP server, not real delivery. - `sent` does not mean the recipient received it. - [List all holidays](https://docs.factuarea.com/api-reference/holidays/public-api.v1.holidays.list): `GET /v1/companies/{company}/holidays` — List the public holidays visible to your company with cursor pagination: seeded read-only national and autonomic holidays plus your custom local ones. - Filter by `year`, `ccaa`, `scope` (`national`/`autonomic`/`local`) and `source` (`reference`/`custom`). - [Resolve applicable holidays](https://docs.factuarea.com/api-reference/holidays/public-api.v1.holidays.resolve): `GET /v1/companies/{company}/holidays/resolve` — Resolve the holidays that apply to a given autonomous community in a given year: national holidays, the autonomic holidays of that `ccaa`, and your custom local holidays, merged into a single flat list under `{ "data": [Holiday, …] }`. Both `ccaa` (ISO 3166-2:ES) and `year` are required; an invalid community code or an out-of-range year returns 422. - [Retrieve a holiday](https://docs.factuarea.com/api-reference/holidays/public-api.v1.holidays.show): `GET /v1/companies/{company}/holidays/{holiday}` — Retrieve a single holiday by its `id` (UUID v7). A custom holiday belonging to another company returns 404 `holiday_not_found` (anti-enumeration). - [List integration events](https://docs.factuarea.com/api-reference/integration-events/public-api.v1.integrations.events.list): `GET /v1/companies/{company}/integrations/events` — Browse everything the payment gateways have sent to Factuarea. This is the inbox to open when a charge did not generate its invoice: every discarded event carries a typed `discard_reason` and whether it can be reprocessed. Newest first, and scoped to the authenticated company. The raw content of the event is never returned. - [Replay a parked integration event](https://docs.factuarea.com/api-reference/integration-events/public-api.v1.integrations.events.replay): `POST /v1/companies/{company}/integrations/events/{event}/replay` — Reprocess a parked gateway event once the cause that parked it is fixed. - Needs `integration_events:write`; the event must have `is_replayable: true`, otherwise 422. - It can issue a real invoice with VeriFactu registration; confirm with the owner first. - 202 means queued, not completed; the outcome arrives as a new event, and invoices are never duplicated. - [Retrieve an integration event](https://docs.factuarea.com/api-reference/integration-events/public-api.v1.integrations.events.show): `GET /v1/companies/{company}/integrations/events/{event}` — Retrieve one integration event by its id, typically after finding it in the listing, to know exactly why a charge did not produce its invoice and what to do next. On top of the listing fields, the detail adds `recommended_action`, one imperative sentence with the next step, and `is_replayable`, which tells you whether the replay operation would accept the event. - [List notifications](https://docs.factuarea.com/api-reference/notifications/public-api.v1.notifications.list): `GET /v1/companies/{company}/notifications` — List the in-app notifications of the member who owns the API key, newest first. Filter by `status` (`unread` or `read`) and `category`; archived notifications never appear. Cursor-paginated: pass the `next_cursor` of a page as `starting_after` to get the next one; `has_more` tells whether there are more. - [Mark all notifications as read](https://docs.factuarea.com/api-reference/notifications/public-api.v1.notifications.mark_all_read): `POST /v1/companies/{company}/notifications/mark-all-read` — Mark every unread notification of the key holder as read and return the updated counters. No request body. - [Mark a notification as read](https://docs.factuarea.com/api-reference/notifications/public-api.v1.notifications.read): `POST /v1/companies/{company}/notifications/{notification}/read` — Mark one notification of the key holder as read and return the updated counters (`total`, `unread`). A notification of another member returns 404 `notification_not_found`. - [Cancel an employee batch](https://docs.factuarea.com/api-reference/employees/public-api.v1.employee-batches.cancel): `POST /v1/companies/{company}/employee-batches/{id}/cancel` — Cancel an employee batch. - Preparing and refreshing never charges, provisions people or consumes an offer. - A batch holds 1 to 100 profiles or inactive employee UUIDs and sends no invitations. - [Confirm an employee batch](https://docs.factuarea.com/api-reference/employees/public-api.v1.employee-batches.confirm): `POST /v1/companies/{company}/employee-batches/{id}/confirm` — Confirm an employee batch, charging and provisioning it once one financial outcome is verified. - Confirm exactly the reviewed `quote_version` with a stable `Idempotency-Key`. - After a 202, error or replay, GET the same UUID until a terminal state; never create a second purchase. - [List an employee batch](https://docs.factuarea.com/api-reference/employees/public-api.v1.employee-batches.list): `GET /v1/companies/{company}/employee-batches` — List the employee batches of the company. - A batch holds 1 to 100 explicit create profiles or inactive employee UUIDs and sends no invitations. - Provisioning happens only after one verified financial outcome. - [Prepare an employee batch](https://docs.factuarea.com/api-reference/employees/public-api.v1.employee-batches.prepare): `POST /v1/companies/{company}/employee-batches` — Prepare a batch purchase of 1 to 100 employees (explicit create profiles or inactive employee UUIDs). - Preparing and refreshing never charge, provision people or send invitations. - Confirm the reviewed `quote_version` with a stable Idempotency-Key. - After a 202 or failure, GET the same UUID until terminal; never create a second purchase. - [Refresh the quote for an employee batch](https://docs.factuarea.com/api-reference/employees/public-api.v1.employee-batches.refresh_quote): `POST /v1/companies/{company}/employee-batches/{id}/quote` — Refresh the quote of a prepared employee batch. - Refreshing never charges, provisions people or consumes an offer. - Confirm exactly the new `quote_version` with a stable Idempotency-Key. - After a 202 or failure, GET the same batch UUID until terminal; never create a second purchase. - [Retrieve an employee batch](https://docs.factuarea.com/api-reference/employees/public-api.v1.employee-batches.show): `GET /v1/companies/{company}/employee-batches/{id}` — Retrieve an employee batch and its financial outcome. - GET the same UUID after a 202, failure or replay until a verified terminal state. - Unknown totals never mean free; financial history exposes no private codes or Stripe identifiers. - [Cancel an employee invitation](https://docs.factuarea.com/api-reference/employees/public-api.v1.employee-invitations.cancel): `DELETE /v1/companies/{company}/employee-invitations/{invitation}` — Cancel a pending employee invitation identified by its `id` (UUID v7); it transitions to `canceled` and can no longer be accepted. Returns 204 on success, 422 if the invitation was already accepted, and 404 if it does not exist in your company. - [List employee invitations](https://docs.factuarea.com/api-reference/employees/public-api.v1.employee-invitations.list): `GET /v1/companies/{company}/employee-invitations` — List the employee invitations of your company. Only invitations with role `employee` are returned; user/admin invitations from the user-management surface are excluded. Each item exposes its opaque `id` (UUID v7), `email`, `status` (`pending`/`accepted`/`canceled`/`expired`) and expiry. - [Resend an employee invitation](https://docs.factuarea.com/api-reference/employees/public-api.v1.employee-invitations.resend): `POST /v1/companies/{company}/employee-invitations/{invitation}/resend` — Resend a pending employee invitation identified by its `id` (UUID v7), regenerating its token and expiry and re-sending the invitation email. Returns 422 if the invitation was already accepted or canceled or its email belongs to a terminated employee (`employee_inactive`), and 404 if it does not exist in your company. - [Send an employee invitation](https://docs.factuarea.com/api-reference/employees/public-api.v1.employee-invitations.send): `POST /v1/companies/{company}/employee-invitations` — Invite a person to your company as an employee (Control Horario portal); only `email` is required and the role is fixed to `employee`. - The person receives an email with an acceptance link. - Returns 422 for an email that already belongs to a company user or has a pending invitation, and 422 `business_rule_violation` (`employee_inactive`) for the email of a terminated employee. - Does not consume the plan `users` seat limit. - [Cancel an employee-seat offer redemption](https://docs.factuarea.com/api-reference/employees/public-api.v1.employee-seat-offer-redemptions.cancel): `POST /v1/companies/{company}/employee-seat-offer-redemptions/{id}/cancel` — Cancel an employee-seat offer redemption before it is confirmed. - Cancelling never charges; the offer is not consumed. - Use a stable Idempotency-Key and GET the same UUID to read the final state. - Unavailable or other-company codes get the same controlled rejection. - [Confirm an employee-seat offer redemption](https://docs.factuarea.com/api-reference/employees/public-api.v1.employee-seat-offer-redemptions.confirm): `POST /v1/companies/{company}/employee-seat-offer-redemptions/{id}/confirm` — Confirm an employee-seat offer redemption, charging the reviewed quote. - Send exactly the reviewed `quote_version` with a stable Idempotency-Key. - After a 202, failure or replay, GET the same UUID until terminal; never create a second purchase. - Existing discounts are never silently stacked or replaced. - [List an employee-seat offer redemption](https://docs.factuarea.com/api-reference/employees/public-api.v1.employee-seat-offer-redemptions.list): `GET /v1/companies/{company}/employee-seat-offer-redemptions` — List an employee-seat offer redemptions of the company. - Financial history exposes no private code, profile or Stripe identifiers. - The private offer belongs to the paying company; unavailable or other-company codes get the same rejection. - [Prepare an employee-seat offer redemption](https://docs.factuarea.com/api-reference/employees/public-api.v1.employee-seat-offer-redemptions.prepare): `POST /v1/companies/{company}/employee-seat-offer-redemptions` — Prepare an employee-seat offer redemption and its quote without charging. - Preparing never charges or consumes the offer; confirm later with a stable Idempotency-Key. - The private offer belongs to the paying company; unavailable or other-company codes get the same rejection. - Existing discounts are never silently stacked or replaced. - [Refresh the quote for an employee-seat offer redemption](https://docs.factuarea.com/api-reference/employees/public-api.v1.employee-seat-offer-redemptions.refresh_quote): `POST /v1/companies/{company}/employee-seat-offer-redemptions/{id}/quote` — Refresh the quote of an employee-seat offer redemption. - Refreshing never charges or consumes the offer; confirm exactly the new `quote_version`. - The private offer belongs to the paying company; unavailable or other-company codes get the same rejection. - [Retrieve an employee-seat offer redemption](https://docs.factuarea.com/api-reference/employees/public-api.v1.employee-seat-offer-redemptions.show): `GET /v1/companies/{company}/employee-seat-offer-redemptions/{id}` — Retrieve an employee-seat offer redemption. - GET the same UUID after a 202 or failure until a verified terminal state. - Unknown totals never mean free; no private code or Stripe identifiers are exposed. - [Cancel the employee seat add-on](https://docs.factuarea.com/api-reference/employees/public-api.v1.employee-seats.cancel): `POST /v1/accounts/{account}/employee-seats/cancel` — Cancel the per-employee billing add-on at period end; the plan subscription is untouched. - Returns the billing status; `subscribed` stays `true` until the period ends. - Owner or admin only (403 `forbidden_action`); 403 `billing_managed_by_provider` if the provider manages billing. - [Sync the employee seat quantity](https://docs.factuarea.com/api-reference/employees/public-api.v1.employee-seats.change-quantity): `POST /v1/accounts/{account}/employee-seats/change-quantity` — Sync the add-on seat quantity to the real number of active employees (no proration, no invoice). - Idempotent: a no-op when the quantity already matches. - Owner or admin only (403 `forbidden_action`); 403 `billing_managed_by_provider` if the provider manages billing. - [Preview the employee seat charge](https://docs.factuarea.com/api-reference/employees/public-api.v1.employee-seats.preview): `GET /v1/accounts/{account}/employee-seats/preview` — Preview the prorated per-seat charge for activating or hiring employees, without charging. - Send `count` (1 to 1000) or `employee_ids` (UUID v7); already covered employees cost 0. - Amounts are 2-decimal euro strings; 403 `billing_managed_by_provider` when the provider manages billing. - [Retrieve employee seat billing status](https://docs.factuarea.com/api-reference/employees/public-api.v1.employee-seats.status): `GET /v1/accounts/{account}/employee-seats` — Return the billing status of the per-employee add-on: `quantity` billed, active employees and recurring per-seat cost with VAT. - Amounts are `null` when not resolvable, never a misleading 0. - `subscribed: false` with `seats_billable: true` and active employees is a billing anomaly. - 403 `billing_managed_by_provider` when the provider manages billing. - [Subscribe to the employee seat add-on](https://docs.factuarea.com/api-reference/employees/public-api.v1.employee-seats.subscribe): `POST /v1/accounts/{account}/employee-seats/subscribe` — Subscribe to the monthly per-employee add-on, charging the first period with the payment method on file. - Atomic: 402 `employee_seat_payment_method_required` or `employee_seat_charge_failed` subscribes nothing. - Owner or admin only (403 `forbidden_action`); 403 `billing_managed_by_provider` if the provider manages billing. - [Set the contracted employee seats](https://docs.factuarea.com/api-reference/employees/public-api.v1.employee-seats.update): `PATCH /v1/accounts/{account}/employee-seats` — Set the contracted employee seats of the account to an absolute `contracted_seats`. - A higher value buys the missing seats now, with the payment method on file; a lower one is a reduction applied at renewal, without refund. - Going below the occupied seats needs `deactivate` with exactly the surplus; breaking an offer package needs `accept_offer_package_loss`. - `Idempotency-Key` is mandatory. - [Create an employee](https://docs.factuarea.com/api-reference/employees/public-api.v1.employees.create): `POST /v1/companies/{company}/employees` — Register a new employee for the company in the path; returns it with a generated `id` (UUID v7). - Required: `first_name`, `last_name`, `email`, `employment_type`, `contract_hours`, `hire_date`, `ccaa`. - Each active employee occupies a contracted seat; with none free, the missing seat is bought and charged automatically (402 `employee_seat_payment_method_required`). Send an `Idempotency-Key`. - [Deactivate an employee](https://docs.factuarea.com/api-reference/employees/public-api.v1.employees.deactivate): `POST /v1/companies/{company}/employees/{employee}/deactivate` — Deactivate an employee (transition `active` → `inactive`), soft-removing them from the active workforce while preserving their record. `termination_date` (`Y-m-d`) is optional — omit it to use today. Returns 422 if the employee is already inactive or the termination date precedes the hire date. Reversible via reactivate. - [Find an employee by external ID](https://docs.factuarea.com/api-reference/employees/public-api.v1.employees.find_by_external_id): `POST /v1/companies/{company}/employees/find-by-external-id` — Look up an employee by their `external_id` (sent in the JSON body), the integration key that maps them to a record in a third-party system (ERP/CRM/HR). Distinct from the fiscal `tax_id`. Returns the matching employee or 404 if no employee uses that external_id within your company. - [List all employees](https://docs.factuarea.com/api-reference/employees/public-api.v1.employees.list): `GET /v1/companies/{company}/employees` — List the employees of your company with cursor-based pagination. Supports filtering by `status` (`active`/`inactive`), `employment_type` (`full_time`/`part_time`) and `ccaa`, plus free-text `search` over name and email. - [Reactivate an employee](https://docs.factuarea.com/api-reference/employees/public-api.v1.employees.reactivate): `POST /v1/companies/{company}/employees/{employee}/reactivate` — Reactivate an employee (transition `inactive` → `active`), clearing their `termination_date` and returning them to the active workforce. No request body. Returns 422 if the employee is already active. - It occupies a contracted seat; with none free, the missing seat is bought and charged automatically. Send an `Idempotency-Key`. - [Retrieve an employee](https://docs.factuarea.com/api-reference/employees/public-api.v1.employees.show): `GET /v1/companies/{company}/employees/{employee}` — Retrieve a single employee by its `id` (UUID v7). An employee belonging to another company returns 404 `employee_not_found` (anti-enumeration). - [Get employee stats](https://docs.factuarea.com/api-reference/employees/public-api.v1.employees.stats): `GET /v1/companies/{company}/employees/stats` — Aggregated KPIs for your workforce: total employee count, active and inactive counts, and a breakdown by working-hours arrangement (`full_time`/`part_time`). Deactivated employees count in `total`/`inactive` but not as active seats. Returned as `{ "data": EmployeeStats }`. - [Update an employee](https://docs.factuarea.com/api-reference/employees/public-api.v1.employees.update): `PATCH /v1/companies/{company}/employees/{employee}` — Partially update an employee; omitted fields keep their value, and the updated employee is returned. - `hire_date` cannot be later than `termination_date`: 422 `parameter_invalid_value`, subcode `invalid_hire_date`. - Entries outside the new employment period stay in the ledger, flagged `is_outside_employment`. - [Close a monthly time record](https://docs.factuarea.com/api-reference/monthly-register-closes/public-api.v1.monthly_time_record_closes.create): `POST /v1/companies/{company}/monthly-time-record-closes` — Freeze the immutable monthly close of the time record register for a finished `(year, month)`. - Snapshots balances and absences of every employee in the period and locks it against retroactive entries. - A month not yet ended returns 422; an already closed period returns 409. - Returns 201 with the close and a `Location` header. - [Download the closed register (RD-ley 8/2019)](https://docs.factuarea.com/api-reference/monthly-register-closes/public-api.v1.monthly_time_record_closes.export): `GET /v1/companies/{company}/monthly-time-record-closes/{monthly_time_record_close}/export` — Download the daily time record of a closed period as a spreadsheet in the `rdley_8_2019` format, read from the locked, tamper-evident ledger (append-only entries + hash chain) of the period. `format` is optional and defaults to `rdley_8_2019`; a format outside the catalog returns 422. A period without a close returns 404. The response is a binary file download. - [List all monthly time record closes](https://docs.factuarea.com/api-reference/monthly-register-closes/public-api.v1.monthly_time_record_closes.list): `GET /v1/companies/{company}/monthly-time-record-closes` — List the monthly closes of the time record register of your company with cursor-based pagination, ordered by period descending. Supports filtering by `year`. Each item exposes its status (`closed`/`reopened`), period bounds and employee count. - [Reopen a monthly time record close](https://docs.factuarea.com/api-reference/monthly-register-closes/public-api.v1.monthly_time_record_closes.reopen): `POST /v1/companies/{company}/monthly-time-record-closes/{monthly_time_record_close}/reopen` — Reopen a `closed` monthly close by its `id` (UUID v7) — an audited recovery of an erroneous close that re-enables writes for the period. The close keeps its `id`; its status becomes `reopened`. A close that cannot be reopened returns 422 in Spanish, and one belonging to another company returns 404. Returns 200 with the reopened close. - [Retrieve the report of a closed period](https://docs.factuarea.com/api-reference/monthly-register-closes/public-api.v1.monthly_time_record_closes.report): `GET /v1/companies/{company}/monthly-time-record-closes/{monthly_time_record_close}/report` — Return the monthly report of a closed period by close `id`, read from the frozen snapshot so totals never drift. - Holds company totals and one row per employee with absences, balances and daily detail; totals in minutes. - A period without a close returns 404; exposes `close_id`, never an `id` of its own. - [Seal a monthly time record register](https://docs.factuarea.com/api-reference/monthly-register-closes/public-api.v1.monthly_time_record_closes.seal): `POST /v1/companies/{company}/monthly-time-record-closes/{monthly_time_record_close}/seal` — Seal (digitally sign) a `closed` monthly register with the company certificate, making it tamper-evident. - One seal per close: a sealed period returns 409; a non-`closed` close or no active certificate returns 422. - Returns 201 with the seal and a `Location` header. - [Retrieve the seal of a monthly register](https://docs.factuarea.com/api-reference/monthly-register-closes/public-api.v1.monthly_time_record_closes.seal_show): `GET /v1/companies/{company}/monthly-time-record-closes/{monthly_time_record_close}/seal` — Retrieve the digital seal of a monthly register by close `id`, with its verification state recomputed live. - `verified` is `true` when snapshot and signature are intact; otherwise `verification_reason` says why. - A close without a seal returns 404 `monthly_register_signature_not_found`. - [Retrieve a monthly time record close](https://docs.factuarea.com/api-reference/monthly-register-closes/public-api.v1.monthly_time_record_closes.show): `GET /v1/companies/{company}/monthly-time-record-closes/{monthly_time_record_close}` — Retrieve a single monthly close by its `id` (UUID v7). A close belonging to another company returns 404 `monthly_time_record_close_not_found` (anti-enumeration). - [Download the payroll export of a closed month](https://docs.factuarea.com/api-reference/payroll-exports/public-api.v1.monthly_time_record_closes.payroll_export): `GET /v1/companies/{company}/monthly-time-record-closes/{monthly_time_record_close}/payroll-export` — Download the payroll incidents file of a closed month for a Spanish payroll software, read from the frozen snapshot. - `format` is optional (`a3` default, `sage`, `nominasol`); an unknown format returns 422. - A period without a close returns 404; the response is a binary spreadsheet. - [List the supported payroll export formats](https://docs.factuarea.com/api-reference/payroll-exports/public-api.v1.payroll_export_formats.list): `GET /v1/payroll-export-formats` — List the payroll software formats supported by the payroll export (`a3`, `sage`, `nominasol`), each with its commercial label, so an integration can offer a software selector without hardcoding the values. A flat read-only catalog with no pagination. - [Download the exact retained PDF](https://docs.factuarea.com/api-reference/pdf-artifacts/public-api.v1.pdf_artifacts.download): `GET /v1/companies/{company}/pdf-artifacts/{artifact}/download` — Download the retained bytes of a ready artifact as `application/pdf` (`Content-Disposition: attachment`). The `ETag` is the SHA-256 of the file; send it in `If-None-Match` to receive `304 Not Modified`. Authorization and integrity are verified before any 304. Requires `pdfs:read`. - [Prepare an exact presentation PDF](https://docs.factuarea.com/api-reference/pdf-artifacts/public-api.v1.pdf_artifacts.prepare): `POST /v1/companies/{company}/pdf-artifacts` — Reserve the artifact of one retained presentation of a document without rendering it. Send `document_type`, `document_id`, `presentation_id`, `purpose`, `format` and `variant` (`official` or `alternative`); every field is required and unknown fields are rejected. Repeating the same selection returns the same artifact. Render it afterwards with the render operation. Requires `pdfs:read` and `Idempotency-Key`. - [Render a prepared PDF artifact](https://docs.factuarea.com/api-reference/pdf-artifacts/public-api.v1.pdf_artifacts.render): `POST /v1/companies/{company}/pdf-artifacts/{artifact}/render` — Render a prepared artifact. `mode` is required: `sync` waits for the result and `async` queues it. The artifact is returned in state `ready` (200) or still pending (202); poll the show operation while it is `queued` or `processing`. Rendering an artifact that is already ready changes nothing. It counts against the PDF generation budget. Requires `pdfs:read` and `Idempotency-Key`. - [Read PDF artifact metadata](https://docs.factuarea.com/api-reference/pdf-artifacts/public-api.v1.pdf_artifacts.show): `GET /v1/companies/{company}/pdf-artifacts/{artifact}` — Read the state of an artifact (`prepared`, `queued`, `processing`, `ready`, `failed`, `unavailable` or `corrupt`), its hash, size and `download_url` once it is ready. It never prepares or renders anything. Requires `pdfs:read`. - [List office/remote presence declarations](https://docs.factuarea.com/api-reference/presence/public-api.v1.presence.daily): `GET /v1/companies/{company}/presence/daily` — List the office/remote presence declarations of your company with cursor-based pagination. Supports filtering by `employee_id` (UUID v7), by exact day (`date`) or by date range (`from`/`to`, `YYYY-MM-DD`). Each record is one employee’s declared work location for one day. Read-only over the public API — declarations are made from the Factuarea app. - [Get the live team presence](https://docs.factuarea.com/api-reference/presence/public-api.v1.presence.live): `GET /v1/companies/{company}/presence` — Return the live presence panel of your team for the Control Horario module: one `employee_presence` item per active employee. - Each item has the workday state, the late-arrival flag and today's declared office/remote location. - Computed and read-only: `id` is the employee UUID v7; no filters or pagination. - [Retrieve an employee’s live presence](https://docs.factuarea.com/api-reference/presence/public-api.v1.presence.show): `GET /v1/companies/{company}/presence/{employee}` — Retrieve the live presence of a single employee by its `id` (UUID v7): the workday state derived from the ledger, the late-arrival flag and the office/remote location declared today. An employee that does not exist or belongs to another company returns 404 `employee_presence_not_found` (anti-enumeration). A computed resource: it exposes the employee UUID v7 as its `id`. - [Create a price list](https://docs.factuarea.com/api-reference/price-lists/public-api.v1.price-lists.create): `POST /v1/companies/{company}/price-lists` — Create an active price list with a name unique within the authenticated company. - [Delete a price list](https://docs.factuarea.com/api-reference/price-lists/public-api.v1.price-lists.delete): `DELETE /v1/companies/{company}/price-lists/{priceList}` — Soft-delete an unassigned price list. Historical document price snapshots remain unchanged. - [Delete a price list item](https://docs.factuarea.com/api-reference/price-lists/public-api.v1.price-lists.items.delete): `DELETE /v1/companies/{company}/price-lists/{priceList}/items/{item}` — Soft-delete a price entry from the list while historical document snapshots remain immutable. - [List price list items](https://docs.factuarea.com/api-reference/price-lists/public-api.v1.price-lists.items.list): `GET /v1/companies/{company}/price-lists/{priceList}/items` — List the product, variant and presentation prices configured in a price list. - [Permanently delete a retired price list item](https://docs.factuarea.com/api-reference/price-lists/public-api.v1.price-lists.items.purge_retired): `POST /v1/companies/{company}/price-lists/{priceList}/items/{item}/purge` — Permanently destroy a retired price entry: its historical amount, its retirement reason and the snapshot of its target. This cannot be undone and there is no copy anywhere else, so `confirm` must be sent as `true`. Only a RETIRED entry can be purged — an active entry is rejected, and so is an unknown one. - [Reassign a retired price list item](https://docs.factuarea.com/api-reference/price-lists/public-api.v1.price-lists.items.reassign_retired): `POST /v1/companies/{company}/price-lists/{priceList}/items/{item}/reassign` — Create a NEW active price entry from a retired one, pointing at a live catalog target with a confirmed price. - Not a restore: the retired entry keeps its history; the response carries the new entry with its own `id`. - Rejected if the live target already has an active price in this list. - [Upsert a price list item](https://docs.factuarea.com/api-reference/price-lists/public-api.v1.price-lists.items.upsert): `POST /v1/companies/{company}/price-lists/{priceList}/items` — Create or update the unique price entry for a catalog target in this price list. - [List price lists](https://docs.factuarea.com/api-reference/price-lists/public-api.v1.price-lists.list): `GET /v1/companies/{company}/price-lists` — List tenant price lists with pagination and optional status or search filters. - [List active price list options](https://docs.factuarea.com/api-reference/price-lists/public-api.v1.price-lists.options): `GET /v1/companies/{company}/price-lists/options` — Return a compact list of active price lists suitable for selectors. - [Resolve a catalog price](https://docs.factuarea.com/api-reference/price-lists/public-api.v1.price-lists.resolve): `POST /v1/companies/{company}/price-lists/resolve` — Resolve the catalog price of a complete selection (product, variant, presentation, combination, `option_value_ids`); no amount is accepted in the payload. - Returns `source_amount` and `option_adjustment_total` to detect double charges, and `regular_unit_price`, `regular_source` and `promotion` (`null` if none). - `date` and `channel` (`documents` or `web`) apply the running promotions; `client_id` picks the price list as a document does (`price_list_id` wins, `null` = none). - Promotion `gross` uses the item VAT and company regime: for the exact amount use `taxes/calculate-totals`. - [Resolve many catalog prices](https://docs.factuarea.com/api-reference/price-lists/public-api.v1.price-lists.resolve_many): `POST /v1/companies/{company}/price-lists/resolve-many` — Reprice a document: resolve up to 100 selections and compare each with the line's `current_unit_price`. Persists nothing. - An unresolvable target is reported under `targets.` instead of failing the batch. - `date` and `channel` (`documents` or `web`) apply to every target with the running promotions; `client_id` picks the price list as a document does (`price_list_id` wins, `null` = none). - Each price carries `regular_unit_price`, `regular_source` and `promotion`; its `gross` uses the item VAT and company regime (exact amount: `taxes/calculate-totals`). - [Retrieve a price list](https://docs.factuarea.com/api-reference/price-lists/public-api.v1.price-lists.show): `GET /v1/companies/{company}/price-lists/{priceList}` — Retrieve one tenant-scoped price list by public UUID together with its assignment summary. - [Update a price list](https://docs.factuarea.com/api-reference/price-lists/public-api.v1.price-lists.update): `PATCH /v1/companies/{company}/price-lists/{priceList}` — Update the name or lifecycle status of a price list. - [Archive a PDF commercial identity](https://docs.factuarea.com/api-reference/pdf-templates/public-api.v1.pdf_commercial_identities.archive): `POST /v1/companies/{company}/pdf-commercial-identities/{identity}/archive` — Archive a brand identity and resolve in the same atomic step every template or default that points to it. Send the `expected_impact_fingerprint` read from the impact endpoint, the `expected_version` and one decision per association in `replacements` (`replace`, `clear` or `pause`; a template link also accepts `revision_id`). A changed impact returns 409 and nothing is modified. Retained images are not deleted. Requires `pdf_templates:write` and supports `Idempotency-Key`. - [Create a PDF commercial identity](https://docs.factuarea.com/api-reference/pdf-templates/public-api.v1.pdf_commercial_identities.create): `POST /v1/companies/{company}/pdf-commercial-identities` — Create a brand identity with its first revision: `name` plus a `configuration` with the commercial name, logo and brand image asset identifiers, brand mode and contact email, phone and address. Assets must belong to your company and be of the right kind. Supply `id` and `revision_id` (UUID v7) to choose the identifiers yourself. Returns 201. Only company administrators can create it. Requires `pdf_templates:write` and supports `Idempotency-Key`. - [Retrieve a PDF commercial identity](https://docs.factuarea.com/api-reference/pdf-templates/public-api.v1.pdf_commercial_identities.find): `GET /v1/companies/{company}/pdf-commercial-identities/{identity}` — Retrieve one brand identity of your company with its current revision, availability and version. An unknown identifier and one that belongs to another company are indistinguishable (404). Requires `pdf_templates:read`. - [Inspect the impact of a PDF commercial identity change](https://docs.factuarea.com/api-reference/pdf-templates/public-api.v1.pdf_commercial_identities.impact): `GET /v1/companies/{company}/pdf-commercial-identities/{identity}/impact` — Read-only preview of the templates and company defaults affected by publishing a revision (`action=publish`) or archiving the identity (`action=archive`). `action` is required. The response carries the `impact_fingerprint` that publish and archive must echo as `expected_impact_fingerprint`. It does not modify anything. Requires `pdf_templates:read`, not write. - [List PDF commercial identities](https://docs.factuarea.com/api-reference/pdf-templates/public-api.v1.pdf_commercial_identities.list): `GET /v1/companies/{company}/pdf-commercial-identities` — List the brand identities (commercial name, logo, contact details) that your templates can use, with page-based pagination (`page`, `per_page` up to 100). Filters: `q` (name) and `state` (`active` by default, `archived` or `all`). A commercial identity never replaces the fiscal identity or the bank data printed on a document. Requires `pdf_templates:read`. - [Publish a PDF commercial identity revision](https://docs.factuarea.com/api-reference/pdf-templates/public-api.v1.pdf_commercial_identities.publish_revision): `POST /v1/companies/{company}/pdf-commercial-identities/{identity}/revisions` — Append an immutable revision with a partial `configuration` (at least one commercial key). Read the impact of the identity with `action=publish` first and send its `expected_impact_fingerprint` with the `expected_version` of the identity; `If-Match` is not accepted on this action. Documents already issued keep the revision they used. Returns 201. Requires `pdf_templates:write` and supports `Idempotency-Key`. - [Restore a PDF commercial identity](https://docs.factuarea.com/api-reference/pdf-templates/public-api.v1.pdf_commercial_identities.restore): `POST /v1/companies/{company}/pdf-commercial-identities/{identity}/restore` — Make an archived brand identity active again. Send its current `expected_version` in the body; `If-Match` is not accepted on this action. It does not re-establish the associations that were replaced on archive. Requires `pdf_templates:write` and supports `Idempotency-Key`. - [Retrieve a PDF commercial identity revision](https://docs.factuarea.com/api-reference/pdf-templates/public-api.v1.pdf_commercial_identities.revision): `GET /v1/companies/{company}/pdf-commercial-identities/{identity}/revisions/{revision}` — Retrieve one immutable revision of a brand identity as it was published. Requires `pdf_templates:read`. - [Update PDF commercial identity metadata](https://docs.factuarea.com/api-reference/pdf-templates/public-api.v1.pdf_commercial_identities.update): `PATCH /v1/companies/{company}/pdf-commercial-identities/{identity}` — Change only the name and the description; the commercial content is published with a new revision. Send the current `expected_version` in the body or the strong `ETag` of this identity in `If-Match`: a wrong tag returns 412, an outdated version 409 and neither 428. Requires `pdf_templates:write` and supports `Idempotency-Key`. - [Create a PDF template preview](https://docs.factuarea.com/api-reference/pdf-templates/public-api.v1.pdf_template_previews.create): `POST /v1/companies/{company}/pdf-template-previews` — Render an illustrative or draft PDF to try a template before using it. `document_type` and `source` select what is previewed: `example` data, an `unsaved_form`, a `persisted_draft`, a `presentation_revision` or an `invoice_substitution`. It returns the metadata of a preview artifact; read and download it with the PDF artifact operations. A preview never changes a document, numbering or the retained presentation. It counts against the PDF generation budget, so a request without `Idempotency-Key` is rejected. Requires `pdfs:read` and `pdf_templates:read`. - [Archive a PDF template](https://docs.factuarea.com/api-reference/pdf-templates/public-api.v1.pdf_templates.archive): `POST /v1/companies/{company}/pdf-templates/{template}/archive` — Archive a template and resolve every association that depends on it in one atomic step. First read the impact of the template with `action=archive`, then send its `expected_impact_fingerprint`, the `expected_version` of the template and one decision per listed association in `replacements` (`replace`, `clear` or `pause`). A changed impact returns 409 `pdf_library_impact_conflict` and nothing is modified. Archived templates keep their revisions and the documents that already used them. Requires `pdf_templates:write` and supports `Idempotency-Key`. - [Retrieve a PDF template image](https://docs.factuarea.com/api-reference/pdf-templates/public-api.v1.pdf_templates.asset_get): `GET /v1/companies/{company}/pdf-templates/assets/{asset}` — Retrieve a private image of your company. With `Accept: application/json` (the default) it returns the metadata of the asset; with an `image/*` Accept header it returns the stored bytes inline with `Cache-Control: private, no-store`. Requires `pdf_templates:read`. Accept application/json returns immutable metadata; an image MIME returns authorized private bytes with integrity verified. No storage path or binary content is exposed in JSON. - [Upload a PDF template image](https://docs.factuarea.com/api-reference/pdf-templates/public-api.v1.pdf_templates.asset_upload): `POST /v1/companies/{company}/pdf-templates/assets` — Upload a logo or brand image (`kind`: `logo` or `imago`) as `multipart/form-data` in the `file` field. Accepted formats are JPEG, PNG and WebP up to 2048 KiB, at most 6000 px per side and 24 megapixels. Metadata such as EXIF and GPS is stripped. The asset is private and immutable, and a repeated `id` returns 409 `pdf_template_asset_conflict`. Returns 201 with the asset identifier to use in a brand. Requires `pdf_templates:write` and `Idempotency-Key`. - [Retrieve a contact PDF template preference](https://docs.factuarea.com/api-reference/pdf-templates/public-api.v1.pdf_templates.contact_default_get): `GET /v1/companies/{company}/pdf-templates/contact-defaults/{contact}/{document_type}/{purpose}` — Retrieve the template that your company prefers for one contact, document type (`invoice`, `quote`, `proforma`, `delivery-note`) and purpose. A merged contact is resolved to its surviving contact. When nothing is stored the response is virtual (version 1, `template_id` null) and nothing is written. An unknown or foreign contact returns 404. Requires `pdf_templates:read`. - [Set a contact PDF template preference](https://docs.factuarea.com/api-reference/pdf-templates/public-api.v1.pdf_templates.contact_default_set): `PATCH /v1/companies/{company}/pdf-templates/contact-defaults/{contact}/{document_type}/{purpose}` — Set or clear (`template_id: null`) the template used by default for one contact, document type and purpose. The template must be active and compatible with that type and purpose, and the contact must be a customer. Send the current `expected_version` in the body or the strong `ETag` of this preference in `If-Match`. Omitting `template_id` keeps the stored value. Requires `pdf_templates:write` and supports `Idempotency-Key`. - [Create a PDF template](https://docs.factuarea.com/api-reference/pdf-templates/public-api.v1.pdf_templates.create): `POST /v1/companies/{company}/pdf-templates` — Create a template with its first revision; only `name` is required (optional `id` and `revision_id`, UUID v7). Returns 201. - `document_kind` is `commercial` by default or `transport-document` for a transport control document (DeCA) template; it never changes, and a DeCA template accepts only `branding`, `typography` and `colors`. - A logo or brand image needs an effective brand; HTML, CSS, scripts, URLs and legal or bank data are rejected. - Company administrators only, with `pdf_templates:write`; supports `Idempotency-Key`. - [Retrieve the PDF template defaults](https://docs.factuarea.com/api-reference/pdf-templates/public-api.v1.pdf_templates.defaults_get): `GET /v1/companies/{company}/pdf-templates/defaults` — Retrieve the company default template and brand, the per-type defaults and `render_activation` (`legacy` or `revisioned`), which every document creator needs. A company that has never configured defaults gets a virtual response at version 1 that is not stored. Any non-employee member of the company can read it with the `pdf_templates:read` scope, even when the templates section is restricted for that member; employees receive 403. - [Update the PDF template defaults](https://docs.factuarea.com/api-reference/pdf-templates/public-api.v1.pdf_templates.defaults_set): `PATCH /v1/companies/{company}/pdf-templates/defaults` — Set the company default template and brand and the per-type defaults. Omitted fields are kept, `null` clears a value and `type_defaults`, when sent, replaces the whole list. - `type_defaults` admits `transport-document` with `complete` and an active A4 template of kind `transport-document`. - Send the current `expected_version` in the body or the strong `ETag` of the defaults in `If-Match`. - Company administrators only, with `pdf_templates:write`; supports `Idempotency-Key`. - [Duplicate a PDF template](https://docs.factuarea.com/api-reference/pdf-templates/public-api.v1.pdf_templates.duplicate): `POST /v1/companies/{company}/pdf-templates/{template}/duplicate` — Create a new active template from the current configuration of a source template, which may be archived. Returns 201. - Send `name` and the `expected_version` of the source in the body; `If-Match` is not accepted. - `document_kind` keeps the kind of the source; `transport-document` on a commercial source creates a DeCA template with only its preset, layout, branding, typography (8-11 pt), colors and brand. - The copy starts at version 1 without defaults, series or contact preferences. Requires `pdf_templates:write`; supports `Idempotency-Key`. - [Retrieve a PDF template](https://docs.factuarea.com/api-reference/pdf-templates/public-api.v1.pdf_templates.find): `GET /v1/companies/{company}/pdf-templates/{template}` — Retrieve one template of your company with its current revision, its availability for the plan of your company and its version. An unknown identifier and one that belongs to another company are indistinguishable (404). Requires `pdf_templates:read`. - [Inspect the impact of a PDF template change](https://docs.factuarea.com/api-reference/pdf-templates/public-api.v1.pdf_templates.impact): `GET /v1/companies/{company}/pdf-templates/{template}/impact` — Read-only preview of what publishing a new revision (`action=publish`) or archiving (`action=archive`) would affect: company and per-type defaults, series, recurring invoices and contact preferences. `action` is required and any other value returns 422. The response carries the `impact_fingerprint` that the publish and archive operations must echo as `expected_impact_fingerprint`. It does not modify anything. Requires `pdf_templates:read`, not write. - [List PDF templates](https://docs.factuarea.com/api-reference/pdf-templates/public-api.v1.pdf_templates.list): `GET /v1/companies/{company}/pdf-templates` — List the PDF templates of your company, paginated by `page` and `per_page` (up to 100) and ordered by name, then id. - Filters: `q` (name), `state` (`active` by default, `archived` or `all`), `document_kind` (`commercial` or `transport-document`), `document_type`, `purpose` and `format`. - A filter or page value out of range returns 422 instead of being trimmed silently. - Requires `pdf_templates:read`; employees are not allowed. - [Publish a PDF template revision](https://docs.factuarea.com/api-reference/pdf-templates/public-api.v1.pdf_templates.publish_revision): `POST /v1/companies/{company}/pdf-templates/{template}/revisions` — Append an immutable revision with the new compatibility, base preset, brand or configuration. Returns 201 with the new revision. - First read the impact with `action=publish`, then send its `expected_impact_fingerprint` and the `expected_version` of the template; a changed impact returns 409. - Objects in `configuration` are merged deeply and lists replaced; the kind is fixed, so `document_kind` is rejected. - Earlier revisions and the documents issued with them are not modified. Requires `pdf_templates:write`; supports `Idempotency-Key`. - [Restore a PDF template](https://docs.factuarea.com/api-reference/pdf-templates/public-api.v1.pdf_templates.restore): `POST /v1/companies/{company}/pdf-templates/{template}/restore` — Make an archived template active again. Send its current `expected_version` in the body; `If-Match` is not accepted on this action. Restoring only changes the state: it does not create a revision and does not re-establish the associations that were replaced when it was archived. Requires `pdf_templates:write` and supports `Idempotency-Key`. - [Retrieve a PDF template revision](https://docs.factuarea.com/api-reference/pdf-templates/public-api.v1.pdf_templates.revision): `GET /v1/companies/{company}/pdf-templates/{template}/revisions/{revision}` — Retrieve one immutable revision of a template, with the compatibility and configuration that were published. Revisions never change after publication. Requires `pdf_templates:read`. - [Update PDF template metadata](https://docs.factuarea.com/api-reference/pdf-templates/public-api.v1.pdf_templates.update): `PATCH /v1/companies/{company}/pdf-templates/{template}` — Change only the name and the description of a template; the visual content is published with a new revision instead. Send the current `expected_version` in the body or the strong `ETag` of this same template in `If-Match`. A wrong tag returns 412, an outdated version returns 409 with `current_version`, and sending neither returns 428. Omitting the description keeps it; `null` clears it. A request that changes nothing does not create a new version. Requires `pdf_templates:write` and supports `Idempotency-Key`. - [Cancel a promotion](https://docs.factuarea.com/api-reference/promotions/public-api.v1.promotions.cancel): `POST /v1/companies/{company}/promotions/{promotion}/cancel` — Cancel a scheduled promotion, or end an active one right now. Returns the promotion, now `cancelled`. - An ended or already cancelled promotion is read-only: 422 `promotion_read_only`. - [Create a promotion](https://docs.factuarea.com/api-reference/promotions/public-api.v1.promotions.create): `POST /v1/companies/{company}/promotions` — Schedule a promotion: a discount on products, variants, presentations, configurations or packs, between two days of the company time zone (end day included). - Send `channels` (`documents`, `web` or both) and at least one item with `target_type`, `target_id`, `mode` (`percent_off` or `fixed`), `value` and, for `fixed`, `basis` (`net` or `gross`). - A failing item answers 422 `invalid_promotion_item` (`param` `items..…`) or `duplicate_promotion_item`, and nothing is created. - [Delete a promotion](https://docs.factuarea.com/api-reference/promotions/public-api.v1.promotions.delete): `DELETE /v1/companies/{company}/promotions/{promotion}` — Delete a scheduled promotion permanently. Returns 204 with no body. - An active promotion is part of the price history: 422 `promotion_started` (cancel it instead). - An ended or cancelled promotion is read-only: 422 `promotion_read_only`. - It cannot be undone, so the request needs an `Idempotency-Key`. - [List all promotions](https://docs.factuarea.com/api-reference/promotions/public-api.v1.promotions.list): `GET /v1/companies/{company}/promotions` — List the promotions of the company with cursor-based pagination, oldest first, each one with its items. - Filter by `status` (`scheduled`, `active`, `ended` or `cancelled`), `channel` (`documents` or `web`), `starts_at[gte|lte]`, `ends_at[gte|lte]` and `updated[gte]`. - Dates are ISO 8601; a day without time is read in the company time zone. - `GET /promotions?status=active&channel=web` returns what a web shop shows today. - [Retrieve a promotion](https://docs.factuarea.com/api-reference/promotions/public-api.v1.promotions.show): `GET /v1/companies/{company}/promotions/{promotion}` — Retrieve a promotion by its `id`, with its items: regular price, promotion price and legal previous price of each one. - Returns 404 `promotion_not_found` for an unknown id or one of another company. - [Update a promotion](https://docs.factuarea.com/api-reference/promotions/public-api.v1.promotions.update): `PATCH /v1/companies/{company}/promotions/{promotion}` — Update a promotion. Only the fields you send change; `label` sent as `null` is cleared and `items` replaces the previous items as a whole. - A scheduled promotion accepts every field. - An active promotion only accepts a new `ends_on` (to extend it); anything else is 422 `promotion_started`. - An ended or cancelled promotion is read-only: 422 `promotion_read_only`. - [Archive a project](https://docs.factuarea.com/api-reference/projects/public-api.v1.projects.archive): `POST /v1/companies/{company}/projects/{project}/archive` — Archive a project: it leaves the default listings and stops accepting new tasks (422 `project_archived`), but everything is kept and can be read. Reversible with `POST /v1/companies/{company}/projects/{project}/unarchive`. - [Create a project column](https://docs.factuarea.com/api-reference/projects/public-api.v1.projects.columns.create): `POST /v1/companies/{company}/projects/{project}/columns` — Add a column at the end of the project board. `name` is required; `icon`, `color` (from the task palette) and `is_final` are optional. The `slug` is derived from the name and must be unique in the project: a clash returns 409 `column_slug_in_use`, and a reserved slug (`planned`, `archived`) returns 422 `column_slug_reserved`. - [Delete a project column](https://docs.factuarea.com/api-reference/projects/public-api.v1.projects.columns.delete): `DELETE /v1/companies/{company}/projects/{project}/columns/{column}` — Permanently delete a board column; irreversible, so send the required `Idempotency-Key` header. - If the column has tasks and `move_to_column_id` is missing, returns 409 `column_has_tasks`. - An invalid target returns 422 `invalid_move_target_column`; a valid one receives the tasks at its end. - [List project columns](https://docs.factuarea.com/api-reference/projects/public-api.v1.projects.columns.list): `GET /v1/companies/{company}/projects/{project}/columns` — List the board columns of a project in board order. Each column carries its `slug`, `icon`, `color` and whether it is final (`is_final`: tasks moved there are completed). Returns a plain list, without pagination. - [Reorder project columns](https://docs.factuarea.com/api-reference/projects/public-api.v1.projects.columns.reorder): `PUT /v1/companies/{company}/projects/{project}/columns/reorder` — Set the board order of the project columns by sending all their ids in `column_ids`, in the new order. The list must contain every column of the project exactly once; an unknown column returns 404 `project_column_not_found`. - [Update a project column](https://docs.factuarea.com/api-reference/projects/public-api.v1.projects.columns.update): `PATCH /v1/companies/{company}/projects/{project}/columns/{column}` — Partially update a column: `name` (its `slug` follows), `icon`, `color` and `is_final`. Turning a column final completes the tasks it holds; turning it back reopens them. A `slug` clash returns 409 `column_slug_in_use`. - [Create a project](https://docs.factuarea.com/api-reference/projects/public-api.v1.projects.create): `POST /v1/companies/{company}/projects` — Create a task project with a `name`, a unique `key` (an uppercase letter followed by up to nine uppercase letters or digits, used in task keys such as `DEV-12`), an optional `icon` and `description`. The project is created with the default board columns. A `key` already used by another project of your company returns 409 `project_key_in_use`. - [Create a project custom field](https://docs.factuarea.com/api-reference/projects/public-api.v1.projects.custom_fields.create): `POST /v1/companies/{company}/projects/{project}/custom-fields` — Define a custom field for the tasks of a project. `name` and `type` are required; `required`, `default_value` and `options` (for `dropdown` and `multiselect`) are optional. An inconsistent definition —options on a type that has none, a default that is not a valid value— returns 422 `invalid_custom_field_definition`. Existing tasks receive the default value. - [Delete a project custom field](https://docs.factuarea.com/api-reference/projects/public-api.v1.projects.custom_fields.delete): `DELETE /v1/companies/{company}/projects/{project}/custom-fields/{field}` — Permanently delete a custom field definition together with the values stored in every task of the project. Irreversible: there is no trash or restore, so send an `Idempotency-Key` header (required) to retry safely. - [List project custom fields](https://docs.factuarea.com/api-reference/projects/public-api.v1.projects.custom_fields.list): `GET /v1/companies/{company}/projects/{project}/custom-fields` — List the custom field definitions of a project in their display order: `name`, `type` (`text`, `number`, `date`, `dropdown`, `boolean` or `multiselect`), whether it is `required`, its `default_value` and, for `dropdown`/`multiselect`, its `options`. Returns a plain list, without pagination. - [Update a project custom field](https://docs.factuarea.com/api-reference/projects/public-api.v1.projects.custom_fields.update): `PATCH /v1/companies/{company}/projects/{project}/custom-fields/{field}` — Partially update a custom field definition. Removing an option that tasks still use, or changing the type in a way their values cannot follow, returns 422 `invalid_custom_field_definition`. - [Delete a project](https://docs.factuarea.com/api-reference/projects/public-api.v1.projects.delete): `DELETE /v1/companies/{company}/projects/{project}` — Permanently delete a project with all its tasks, comments, attachments and time entries. - Irreversible, no restore: send the required `Idempotency-Key` header. - A project with invoiced hours returns 422 `task_time_entry_invoiced` until that invoice is deleted. - [Find a project by key](https://docs.factuarea.com/api-reference/projects/public-api.v1.projects.find_by_key): `POST /v1/companies/{company}/projects/find-by-key` — Look up a project by its `key` sent in the request body (case-insensitive). Returns 404 `project_not_found` when no project of your company has that key. A read-only lookup: it does not change anything and does not need an `Idempotency-Key`. - [List projects](https://docs.factuarea.com/api-reference/projects/public-api.v1.projects.list): `GET /v1/companies/{company}/projects` — List the task projects of your company in app order, with task statistics for each. - Archived projects are left out unless `include_archived=true`. - Cursor-paginated: pass `next_cursor` as `starting_after`; `has_more` tells whether more pages exist. - [Retrieve a project](https://docs.factuarea.com/api-reference/projects/public-api.v1.projects.show): `GET /v1/companies/{company}/projects/{project}` — Retrieve a project with its billing settings and task statistics. Its columns are read with `GET /v1/companies/{company}/projects/{project}/columns`. A project of another company, or an `id` that does not exist, returns 404 `project_not_found`. - [Export project tasks](https://docs.factuarea.com/api-reference/projects/public-api.v1.projects.tasks.export): `GET /v1/companies/{company}/projects/{project}/tasks/export` — Export a project's tasks as a `factuarea.tasks.v1` JSON document with its labels, custom fields and comments. - The document can be re-imported with `POST /v1/companies/{company}/projects/{project}/tasks/import`. - Needs only `projects:read`, yet includes every task description and comment. - [Import tasks into a project](https://docs.factuarea.com/api-reference/projects/public-api.v1.projects.tasks.import): `POST /v1/companies/{company}/projects/{project}/tasks/import` — Import tasks into a project from a JSON document (`factuarea.tasks.v1` or a supported format). - Synchronous, max 200 tasks per call (more returns 422); the report lists `id`/`key` or `error`. - `Idempotency-Key` required (422 `idempotency_key_required`); a new key creates a new copy. - [Invoice project time](https://docs.factuarea.com/api-reference/projects/public-api.v1.projects.time_invoices.create): `POST /v1/companies/{company}/projects/{project}/time-invoices` — Turn the selected billable time into a DRAFT invoice for the project billing contact and mark the entries as invoiced. - Requires `invoices:write`; already invoiced entries return 422 `task_time_entry_invoiced`. - Resending the same `batch_id` and request returns the same invoice; deleting the draft releases the entries. - [Preview a project time invoice](https://docs.factuarea.com/api-reference/projects/public-api.v1.projects.time_invoices.preview): `POST /v1/companies/{company}/projects/{project}/time-invoices/preview` — Preview the invoice lines that invoicing the selected time would produce, without creating anything. - Entries that cannot be invoiced return 422 `task_time_not_invoiceable`. - Read-only POST: no `Idempotency-Key` needed. - [Retrieve a project time summary](https://docs.factuarea.com/api-reference/projects/public-api.v1.projects.time_summary.show): `GET /v1/companies/{company}/projects/{project}/time-summary` — Summarize the time logged on the tasks of a project, optionally between `from` and `to` (dates in the company time zone): total, billable, invoiced and pending-to-invoice seconds, broken down by member (with their names) and by task. Requires `projects:read` only, without `tasks:read` or `users:read`. - [Unarchive a project](https://docs.factuarea.com/api-reference/projects/public-api.v1.projects.unarchive): `POST /v1/companies/{company}/projects/{project}/unarchive` — Restore an archived project so it shows up again in the listings and accepts new tasks. Unarchiving a project that is not archived is a no-op that returns the project unchanged. - [Update a project](https://docs.factuarea.com/api-reference/projects/public-api.v1.projects.update): `PATCH /v1/companies/{company}/projects/{project}` — Partially update a project: only the fields you send change. - Editable: `name`, `key` (old key stays as alias), `icon`, `description`, billing defaults. - A `key` already in use returns 409 `project_key_in_use`. - [List purchase scanner emails](https://docs.factuarea.com/api-reference/purchase-scan-emails/public-api.v1.purchase_scan_emails.list): `GET /v1/companies/{company}/purchase-scan-emails` — List the emails received in the purchase scanner mailbox with sender, subject, accepted and rejected attachments and ingestion result. Search by sender or subject and filter by ingestion result or date range; cursor-based pagination. - [Archive a purchase scan](https://docs.factuarea.com/api-reference/purchase-scans/public-api.v1.purchase_scans.archive): `DELETE /v1/companies/{company}/purchase-scans/{purchase_scan}` — Archive a scan that is not being processed. Reversible with the restore operation. Requires `expected_version`. Accepts `Idempotency-Key`. - [Create the expense from a scan](https://docs.factuarea.com/api-reference/purchase-scans/public-api.v1.purchase_scans.convert): `POST /v1/companies/{company}/purchase-scans/{purchase_scan}/convert` — Create exactly one draft expense from a reviewed scan and link it. Responds `200` on the first call and on replays, returning the same linked expense. Requires `expected_version` and that no blocking issue remains; otherwise `422`. - [Upload documents to the purchase scanner](https://docs.factuarea.com/api-reference/purchase-scans/public-api.v1.purchase_scans.create): `POST /v1/companies/{company}/purchase-scans` — Upload up to 20 PDF, JPEG or PNG files as `multipart/form-data` (`files[]`) to the purchase scanner. - Responds `202` with `accepted[]` and `rejected[]`; `422` when no file was accepted. - Send an `Idempotency-Key` header: a replay returns the same result without re-ingesting. - [Resolve a duplicate purchase scan](https://docs.factuarea.com/api-reference/purchase-scans/public-api.v1.purchase_scans.duplicate_resolution): `POST /v1/companies/{company}/purchase-scans/{purchase_scan}/duplicate-resolution` — Resolve a scan in `duplicate` status with `resolution` = `link_existing` (link the existing expense) or `archive`. Duplicate overrides require an authorised user in the Factuarea app; they are not available through the public API or MCP. Requires `expected_version`. Accepts `Idempotency-Key`. - [List purchase scans](https://docs.factuarea.com/api-reference/purchase-scans/public-api.v1.purchase_scans.list): `GET /v1/companies/{company}/purchase-scans` — List the documents received by the purchase scanner (upload, API or mailbox) with their lifecycle status, extraction issues and `available_actions`. Use `filter[status]`, `filter[source]` and the documented date/range filters; cursor-based pagination. - [Restore an archived purchase scan](https://docs.factuarea.com/api-reference/purchase-scans/public-api.v1.purchase_scans.restore): `POST /v1/companies/{company}/purchase-scans/{purchase_scan}/restore` — Return an archived scan to its previous restorable state; interrupted processing resumes from `queued`, and interrupted automatic conversion returns to `needs_review`. Check `available_actions` before reviewing or converting; restoring does not recover a purged original. Requires `expected_version`. Accepts `Idempotency-Key`. - [Retry a failed purchase scan](https://docs.factuarea.com/api-reference/purchase-scans/public-api.v1.purchase_scans.retry): `POST /v1/companies/{company}/purchase-scans/{purchase_scan}/retry` — Start OCR for a scan in `received`, or queue it again for a scan in `failed` whose error is recoverable. Requires `expected_version`; a stale version responds `409`. Accepts `Idempotency-Key`. - [Save the review of a purchase scan](https://docs.factuarea.com/api-reference/purchase-scans/public-api.v1.purchase_scans.review): `PATCH /v1/companies/{company}/purchase-scans/{purchase_scan}/review` — Persist the human corrections of a scan in `needs_review`: supplier, fiscal header, lines and notes, each field marked as verified. Requires `expected_version`; a stale version responds `409` and the latest version must be reloaded. Returns the updated scan. Malformed payloads return `422` before version comparison. - [Retrieve a purchase scan](https://docs.factuarea.com/api-reference/purchase-scans/public-api.v1.purchase_scans.show): `GET /v1/companies/{company}/purchase-scans/{purchase_scan}` — Retrieve a purchase scan by its public `id` (UUID v7): evidence-first extraction (value, confidence and page/bounding-box evidence per field and line), issues, duplicate match, attempts, linked expense and `available_actions`. The current `version` is required by every mutation. - [Download the original document](https://docs.factuarea.com/api-reference/purchase-scans/public-api.v1.purchase_scans.source): `GET /v1/companies/{company}/purchase-scans/{purchase_scan}/source` — Download the original file of a purchase scan (PDF or image) as a binary stream with `Content-Disposition: attachment`. Available while the original is retained. - [Get purchase scanner stats](https://docs.factuarea.com/api-reference/purchase-scans/public-api.v1.purchase_scans.stats): `GET /v1/companies/{company}/purchase-scans/stats` — Aggregated counters of the purchase scanner for your company: documents in progress, pending review and with incidents, plus per-status counts. Returned as `{ "data": PurchaseScanStats }`. - [Test a Shopify store connection](https://docs.factuarea.com/api-reference/shopify/public-api.v1.shopify.stores.connection_test): `POST /v1/companies/{company}/shopify/stores/{store}/connection-test` — Tests the connection to a connected Shopify store and writes nothing; requires `Idempotency-Key`. - A failed check still answers 200: read `reachable`, `credential_accepted` and `failure_code`. - `failure_code` is e.g. `shopify_credentials_rejected` or `shopify_api_version_expired`. - Unknown store returns 404 `store_not_found`. - [Connect a store](https://docs.factuarea.com/api-reference/stores/public-api.v1.stores.create): `POST /v1/companies/{company}/stores` — Connects an e-commerce store to the company; auto-invoicing stays OFF until you enable it. - `external_store_id` is unique per provider (`store_already_connected`). - `remote_base_url` must pass the outbound policy (`store_url_not_allowed`). - [Disconnect a store](https://docs.factuarea.com/api-reference/stores/public-api.v1.stores.disconnect): `DELETE /v1/companies/{company}/stores/{store}` — Disconnects a store and destroys its credential; reconnecting means authorising again at the provider. - Irreversible: requires `Idempotency-Key`. - Invoices already produced are kept; later deliveries are recorded without processing. - Responds 204; an unknown store returns 404. - [List connected stores](https://docs.factuarea.com/api-reference/stores/public-api.v1.stores.index): `GET /v1/companies/{company}/stores` — Lists the e-commerce stores connected to the company across every provider, with cursor pagination. - Each store exposes `id` (UUID v7), `provider`, `external_store_id`, `environment` and `status`. - It also exposes its invoicing settings, e.g. `autoinvoicing_enabled`. - [Retrieve a connected store](https://docs.factuarea.com/api-reference/stores/public-api.v1.stores.show): `GET /v1/companies/{company}/stores/{store}` — Retrieve a connected store by its `id` (UUID v7). Returns the provider connection it hangs from, the identifier the provider gave the shop and its full invoicing configuration. Returns 404 if the store does not exist or belongs to another company — the two answers are identical on purpose, so the endpoint never reveals whether a store of another company exists. - [Update store settings](https://docs.factuarea.com/api-reference/stores/public-api.v1.stores.update): `PATCH /v1/companies/{company}/stores/{store}` — Updates the settings of a connected store; omitted fields keep their value. - Editable: `name`, `series_id` (`null` = default series), invoicing flags, `remote_base_url`, `environment`. - `invoice_note` takes up to 500 characters; `null` or empty clears it. - Provider and `external_store_id` cannot change. - [Retrieve the running task timer](https://docs.factuarea.com/api-reference/task-timers/public-api.v1.task_timers.current): `GET /v1/companies/{company}/task-timers/current` — Return the running timer of the member who owns the API key, with its task, or `data: null` when none is running. - [Stop the running task timer](https://docs.factuarea.com/api-reference/task-timers/public-api.v1.task_timers.stop): `POST /v1/companies/{company}/task-timers/stop` — Stop the timer of the member who owns the API key and return the closed time entry. No request body. With no timer running it returns 422 `task_timer_not_running`. - [Create a task label](https://docs.factuarea.com/api-reference/task-labels/public-api.v1.task_labels.create): `POST /v1/companies/{company}/task-labels` — Add a label to the catalog with a `name` (unique in your company, case-insensitive: 409 `task_label_name_in_use`) and a `color` from the task palette. - [Delete a task label](https://docs.factuarea.com/api-reference/task-labels/public-api.v1.task_labels.delete): `DELETE /v1/companies/{company}/task-labels/{label}` — Permanently delete a label from the catalog and remove it from every task. Irreversible: there is no trash or restore, so send an `Idempotency-Key` header (required) to retry safely. - [List task labels](https://docs.factuarea.com/api-reference/task-labels/public-api.v1.task_labels.list): `GET /v1/companies/{company}/task-labels` — List the task label catalog of your company, ordered by name. Each label carries `tasks_count`: how many tasks of your company carry it, archived tasks included. Cursor-paginated: pass the `next_cursor` of a page as `starting_after` to get the next one; `has_more` tells whether there are more. - [Retrieve a task label](https://docs.factuarea.com/api-reference/task-labels/public-api.v1.task_labels.show): `GET /v1/companies/{company}/task-labels/{label}` — Retrieve a label of the catalog, with `tasks_count`: how many tasks of your company carry it, archived tasks included. - [Update a task label](https://docs.factuarea.com/api-reference/task-labels/public-api.v1.task_labels.update): `PATCH /v1/companies/{company}/task-labels/{label}` — Partially update the `name` or `color` of a label; every task that carries it shows the change. - [List Stripe payouts](https://docs.factuarea.com/api-reference/stripe/public-api.v1.payouts.list): `GET /v1/companies/{company}/payouts` — List the Stripe payouts ingested for your company, with cursor-based pagination. Each exposes the net/fees/gross amounts, currency, arrival date, reconciliation `status` (`ingested`/`reconciled`) and an informative `composition`. Filter by `status` and arrival-date window. Payouts are read-only; bank reconciliation happens in the dashboard. - [Retrieve a Stripe payout](https://docs.factuarea.com/api-reference/stripe/public-api.v1.payouts.show): `GET /v1/companies/{company}/payouts/{payout}` — Retrieve a Stripe payout by its `id` (UUID v7). Returns the amounts, currency, arrival date, reconciliation state (`bank_transaction_ref` once reconciled) and the informative `composition` of component charges. Returns 404 if the payout does not exist or belongs to another company. - [Create a charge treatment rule](https://docs.factuarea.com/api-reference/stripe/public-api.v1.stripe_autoinvoicing.accounts.charge_rules.create): `POST /v1/companies/{company}/connected-accounts/{account}/charge-rules` — Creates a charge treatment rule at the end of the account's list; responds 201. - A rule matches by `condition` and either invoices the charge or excludes it with `non_invoice_reason`. - Fails with `charge_rule_invalid` or `charge_rule_limit_reached`. - [Delete a charge treatment rule](https://docs.factuarea.com/api-reference/stripe/public-api.v1.stripe_autoinvoicing.accounts.charge_rules.delete): `DELETE /v1/companies/{company}/connected-accounts/{account}/charge-rules/{rule}` — Delete a charge treatment rule. Charges already excluded by it keep their record in the non-invoiced charges list. Responds 204 with no body. Returns 404 `charge_rule_not_found` if the rule does not exist in that account and company. - [List charge treatment rules of a connected Stripe account](https://docs.factuarea.com/api-reference/stripe/public-api.v1.stripe_autoinvoicing.accounts.charge_rules.list): `GET /v1/companies/{company}/connected-accounts/{account}/charge-rules` — Lists the charge treatment rules of a connected Stripe account ordered by `position`; the first match decides. - Each rule exposes `id` (UUID v7), `condition`, `outcome`, `concept`, `vat_rate`, `non_invoice_reason`. - Returns 404 if the account is not in your company. - [Reorder the charge treatment rules](https://docs.factuarea.com/api-reference/stripe/public-api.v1.stripe_autoinvoicing.accounts.charge_rules.reorder): `PUT /v1/companies/{company}/connected-accounts/{account}/charge-rules/order` — Reorder the rules of a connected Stripe account by sending every rule `id` in `rule_ids` in the new order (the first one is evaluated first). The list must contain exactly the account's rules, with no repeats: otherwise it fails with 422 `charge_rule_invalid` and `param` `rule_ids`. Returns the rules in their new order. - [Update a charge treatment rule](https://docs.factuarea.com/api-reference/stripe/public-api.v1.stripe_autoinvoicing.accounts.charge_rules.update): `PUT /v1/companies/{company}/connected-accounts/{account}/charge-rules/{rule}` — Replace a charge treatment rule: `condition`, `outcome`, `concept`, `vat_rate` and `non_invoice_reason` are all sent again; its `position` does not change (use the reorder operation). Returns 404 `charge_rule_not_found` if the rule does not exist in that account and company, and 422 `charge_rule_invalid` when a field breaks the contract. - [Disconnect a connected Stripe account](https://docs.factuarea.com/api-reference/stripe/public-api.v1.stripe_autoinvoicing.accounts.disconnect): `DELETE /v1/companies/{company}/connected-accounts/{account}` — Disconnect a connected Stripe account without touching the others. The account is marked `disconnected` (its already-issued invoices and history are kept; later webhooks are recorded without processing). Responds 204 with no body. A missing account or one from another company returns 404. - [List connected Stripe accounts](https://docs.factuarea.com/api-reference/stripe/public-api.v1.stripe_autoinvoicing.accounts.list): `GET /v1/companies/{company}/connected-accounts` — Lists the connected Stripe accounts (Stripe Connect, multi-store) of the company. - Each exposes `id`, `name`, `external_account_id` (`acct_xxx`), `series_id`, `status` and `connected_at`. - It also exposes its per-account configuration, e.g. `autoinvoicing_enabled`. - [List non-invoiced charges of a connected Stripe account](https://docs.factuarea.com/api-reference/stripe/public-api.v1.stripe_autoinvoicing.accounts.non_invoiced_charges.list): `GET /v1/companies/{company}/connected-accounts/{account}/non-invoiced-charges` — Lists charges of a connected Stripe account that a rule deliberately excluded from invoicing, newest first. - Items expose `amount`, `refunded_amount`, `net_amount`, `reason`, `charge_rule_id` and `occurred_at`. - Filter with `occurred_from`/`occurred_to` (`YYYY-MM-DD`); an invalid range returns 422. - [Retrieve a connected Stripe account](https://docs.factuarea.com/api-reference/stripe/public-api.v1.stripe_autoinvoicing.accounts.show): `GET /v1/companies/{company}/connected-accounts/{account}` — Retrieve a connected Stripe account by its `id` (UUID v7). Returns its name, external account id, assigned series (`series_id`), effective per-account auto-invoicing configuration and status. Returns 404 if the account does not exist or belongs to another company. - [Update a connected Stripe account](https://docs.factuarea.com/api-reference/stripe/public-api.v1.stripe_autoinvoicing.accounts.update): `PATCH /v1/companies/{company}/connected-accounts/{account}` — Updates a connected Stripe account; omitted fields keep their value. - Editable: `name`, `series_id` (`null` uses the company default series) and the per-account fiscal policy. - `invoice_note` (up to 500 characters) goes in auto-created invoices; `null` clears it. - `email_invoice_to_payer` emails each auto-created invoice to the address that comes with the charge. - [Start a Stripe Connect authorization](https://docs.factuarea.com/api-reference/stripe/public-api.v1.stripe_autoinvoicing.authorizations.create): `POST /v1/companies/{company}/connected-accounts/authorizations` — Starts connecting a Stripe account to the company and returns the Stripe onboarding `url` (201, `status` `pending`). - Needs `Idempotency-Key` and an `https` `return_url` on an allowed domain (`connect_return_url_not_allowed`). - Live credentials only: test keys fail with 403 `live_credential_required`. - No MCP tool: it needs a browser redirect. - [Retrieve Stripe autoinvoicing config](https://docs.factuarea.com/api-reference/stripe/public-api.v1.stripe_autoinvoicing.config.show): `GET /v1/companies/{company}/stripe-autoinvoicing/config` — Returns the Stripe Connect state and auto-invoicing configuration: enabled, series, plan gating, fiscal policy. - With several connected accounts it returns 422 `per_account_config_required`. - Read each account via `GET /v1/companies/{company}/connected-accounts`. - [Update Stripe autoinvoicing config](https://docs.factuarea.com/api-reference/stripe/public-api.v1.stripe_autoinvoicing.config.update): `PATCH /v1/companies/{company}/stripe-autoinvoicing/config` — Partially updates auto-invoicing of Stripe Connect charges: `enabled`, series and fiscal policy; omitted fields keep their value. - `simplified_threshold_cents` accepts [0, 300000]. - With several connected accounts it returns 422 `per_account_config_required`. - [List Stripe autoinvoiced correctives](https://docs.factuarea.com/api-reference/stripe/public-api.v1.stripe_autoinvoicing.correctives.list): `GET /v1/companies/{company}/stripe-autoinvoicing/correctives` — List the corrective invoices automatically generated from Stripe refunds (`charge.refunded`), with cursor-based pagination. The public `id` is the corrective invoice (UUID v7); `original_invoice_id` links to the original invoice, and `refund_id` is the originating gateway refund. - [List Stripe autoinvoiced charges](https://docs.factuarea.com/api-reference/stripe/public-api.v1.stripe_autoinvoicing.payments.list): `GET /v1/companies/{company}/stripe-autoinvoicing/payments` — List the Stripe charges that generated an invoice (flows A and B plus subscription cycles), with cursor-based pagination. The generated invoice and client are returned as `invoice_id`/`client_id`. Subscription-cycle charges also expose `subscription_id` (external `sub_xxx`), `stripe_invoice_id` and the billed period. Filter by `origin` (`subscription`/`oneshot`). - [Retrieve an employee’s time balance for a period](https://docs.factuarea.com/api-reference/time-balances/public-api.v1.time_balances.employee): `GET /v1/companies/{company}/time-balances/employee/{employee}` — Return an employee's time balance for a period: expected vs worked minutes, balance and overtime per day, and period totals (minutes). - `from` and `to` (`YYYY-MM-DD`) are required; `to` before `from` returns 422. - Days flagged `is_unscheduled` or `is_outside_employment` have expected, balance and overtime 0. Computed resource: exposes `employee_id`, no `id`. - [Retrieve an employee’s monthly time sheet](https://docs.factuarea.com/api-reference/time-balances/public-api.v1.time_balances.monthly_sheet): `GET /v1/companies/{company}/time-balances/monthly-sheet` — Return the live monthly time sheet of an employee for the open period: expected vs worked minutes, balance and overtime per day, and totals (minutes). - `employee_id` is required; `month` (`YYYY-MM`) defaults to the current month. - `total_*` project the whole month; `to_date` holds the closed days up to `through_date`. Computed resource: no `id`. - [Retrieve the team time balance summary](https://docs.factuarea.com/api-reference/time-balances/public-api.v1.time_balances.team_summary): `GET /v1/companies/{company}/time-balances/team-summary` — Return the team time balance summary for a month: one row per employee employed on any day of that month (with or without a schedule or portal account, including one terminated during the month), with expected, worked, balance and overtime minutes. - `month` (`YYYY-MM`) defaults to the current month. - `total_*` cover the whole month (a projection in the current one); `to_date` accumulates closed days. Computed resource: no `id`. - [Approve a time entry correction](https://docs.factuarea.com/api-reference/time-corrections/public-api.v1.time_corrections.approve): `POST /v1/companies/{company}/time-corrections/{time_correction}/approve` — Approve a pending correction request, appending the resolving `correction_entry` linked to the original entry; optional approver `note`. - A non-pending request or approving your own request returns 422. - If the entry now falls outside employment, 422 `business_rule_violation` with subcode `clocking_outside_employment_period`; the request stays pending. - [Request a time entry correction](https://docs.factuarea.com/api-reference/time-corrections/public-api.v1.time_corrections.create): `POST /v1/companies/{company}/time-corrections` — Request the correction of a time entry; it stays `pending` until a manager approves or rejects it. Returns 201 with a `Location` header. - `time_entry_id`, `kind` (`add_missing_entry`/`adjust_time`/`remove_entry`), `reason` and `proposed` are required. - A proposed time outside employment returns 422 `business_rule_violation`, subcode `clocking_outside_employment_period`. - [List all time entry corrections](https://docs.factuarea.com/api-reference/time-corrections/public-api.v1.time_corrections.list): `GET /v1/companies/{company}/time-corrections` — List the time entry correction requests of your company with cursor-based pagination, ordered by request time. Supports filtering by `status` (`pending` is the manager inbox, `approved`/`rejected` are resolved), `employee_id` (UUID v7) and a date range (`from`/`to`). - [Reject a time entry correction](https://docs.factuarea.com/api-reference/time-corrections/public-api.v1.time_corrections.reject): `POST /v1/companies/{company}/time-corrections/{time_correction}/reject` — Reject a pending correction request by its `id` (UUID v7) with a required `reason`, resolving it without touching the original time entry. A request that is not pending returns 422 (already resolved). Returns 200 with the resolved correction. - [Retrieve a time entry correction](https://docs.factuarea.com/api-reference/time-corrections/public-api.v1.time_corrections.show): `GET /v1/companies/{company}/time-corrections/{time_correction}` — Retrieve a single correction request by its `id` (UUID v7), including its derived status. A request belonging to another company returns 404 `correction_request_not_found` (anti-enumeration). - [Retrieve the time tracking settings](https://docs.factuarea.com/api-reference/time-tracking-settings/public-api.v1.time_tracking_settings.show): `GET /v1/companies/{company}/time-tracking-settings` — Return the time tracking configuration of your company: the overtime computation basis (`weekly`/`daily`) and thresholds, the rounding tolerance and the forgotten-clock-in reminder settings. If your company has not configured it yet, the defaults are returned with `id: null` — the first update materialises the row. - [Update the time tracking settings](https://docs.factuarea.com/api-reference/time-tracking-settings/public-api.v1.time_tracking_settings.update): `PATCH /v1/companies/{company}/time-tracking-settings` — Create or partially update your company's time tracking configuration; an omitted field keeps its current value. - Fields: `overtime_basis` (`weekly`/`daily`), overtime thresholds in minutes (`null` derives them from the schedule), `overtime_tolerance_minutes` and the clock-in reminder settings. - A negative threshold or tolerance returns 422. - [List users](https://docs.factuarea.com/api-reference/users/public-api.v1.users.list): `GET /v1/companies/{company}/users` — List the people tasks can be assigned to in your company, ordered by name: its members plus people with `operate` access through an account relation. - View-only relation access is not listed; `q` filters by name or email. - Cursor-paginated: pass `next_cursor` as `starting_after`. - [Retrieve the current user](https://docs.factuarea.com/api-reference/users/public-api.v1.users.me): `GET /v1/companies/{company}/users/me` — Return the person who owns the API key in the company the call acts on: a member of that company or a person of another account with `operate` access to it through an account relation. If the key holder is neither, or is no longer a member of the company that owns the key, it returns 404 `route_not_found`. - [Validate the time record hash chain](https://docs.factuarea.com/api-reference/time-entries/public-api.v1.time_entries.chain.validate): `GET /v1/companies/{company}/time-entries/chain/validate` — Recompute the SHA-256 hash chain (`huella`) of your time record ledger and compare it with the stored values, without changing data. - Returns whether the chain is intact and, if not, the `id` of the first corrupted record. - Limited to 1 request per minute per credential and company; datasets over 50,000 records return 422 `dataset_too_large`. - [Clock in an employee](https://docs.factuarea.com/api-reference/time-entries/public-api.v1.time_entries.clock_in): `POST /v1/companies/{company}/time-entries/clock-in` — Clock the start of an employee's workday, opening a new work span. - `employee_id` and `source` (`web`/`mobile`) are required; `occurred_at` defaults to now. - Fails if already clocked in, or outside the employment period: 422 `business_rule_violation` (`clocking_outside_employment_period`). - A terminated employee is read-only and cannot clock in, even on their termination day: 422 `business_rule_violation` (`employee_inactive`). Record the days they worked with a manual entry instead. - Returns 201 with the `clock_in` entry. - [Clock out an employee](https://docs.factuarea.com/api-reference/time-entries/public-api.v1.time_entries.clock_out): `POST /v1/companies/{company}/time-entries/clock-out` — Clock the end of the employee’s current work span (from `working` or `paused`). `employee_id` (UUID v7) and `source` are required. Valid only when a span is open; an invalid transition returns 422 in Spanish. Returns 201 with the created `clock_out` entry. - [Retrieve an employee’s current workday state](https://docs.factuarea.com/api-reference/time-entries/public-api.v1.time_entries.current): `GET /v1/companies/{company}/time-entries/current` — Return the derived state of an employee’s current workday (`not_started`/`working`/`paused`/`finished`), reconstructed from the open work span in the immutable ledger — there is no session table. `employee_id` (UUID v7) is required as a query parameter. - [List all time entries](https://docs.factuarea.com/api-reference/time-entries/public-api.v1.time_entries.list): `GET /v1/companies/{company}/time-entries` — List the time entries of your company with cursor-based pagination, ordered by `occurred_at`. Supports filtering by `employee_id` (UUID v7), a date range (`from`/`to`) and `entry_type` (`clock_in`/`pause_start`/`pause_end`/`clock_out`). - [Record a manual retroactive entry](https://docs.factuarea.com/api-reference/time-entries/public-api.v1.time_entries.manual): `POST /v1/companies/{company}/time-entries/manual` — Record a past work span for an employee as a retroactive manual entry. - `employee_id`, `started_at`, `ended_at` and `reason` are required; optional `pauses`. - Outside the employment period: 422 `business_rule_violation` (`clocking_outside_employment_period`); nothing is written. - Returns 201 with the span's `clock_out` entry. - [Start a pause](https://docs.factuarea.com/api-reference/time-entries/public-api.v1.time_entries.pause): `POST /v1/companies/{company}/time-entries/pause` — Start a pause in the employee’s current work span. `employee_id` (UUID v7) and `source` are required. Valid only when the employee is `working`; an invalid transition returns 422 in Spanish. Returns 201 with the created `pause_start` entry. - [Resume from a pause](https://docs.factuarea.com/api-reference/time-entries/public-api.v1.time_entries.resume): `POST /v1/companies/{company}/time-entries/resume` — Resume the employee’s workday after a pause. `employee_id` (UUID v7) and `source` are required. Valid only when the employee is `paused`; an invalid transition returns 422 in Spanish. Returns 201 with the created `pause_end` entry. - [Retrieve a time entry](https://docs.factuarea.com/api-reference/time-entries/public-api.v1.time_entries.show): `GET /v1/companies/{company}/time-entries/{time_entry}` — Retrieve a single time entry by its `id` (UUID v7). An entry belonging to another company returns 404 `time_record_entry_not_found` (anti-enumeration). - [Cancel a transport document](https://docs.factuarea.com/api-reference/transport-documents/public-api.v1.transport_documents.cancel): `POST /v1/companies/{company}/transport-documents/{transport_document}/cancel` — Cancel an `issued` transport document with a `reason` (3–500 characters). It stores a final PDF version marked «ANULADO» that the public URL keeps serving, and the document becomes terminal (`cancelled`). A PDF over 5 MB returns 422 `transport_document_pdf_too_large` and nothing changes. Irreversible: requires `Idempotency-Key`. - [Close a transport document](https://docs.factuarea.com/api-reference/transport-documents/public-api.v1.transport_documents.close): `POST /v1/companies/{company}/transport-documents/{transport_document}/close` — Mark an `issued` transport document as finished (`closed`, `close_mode: manual`). Documents are also closed automatically 7 days after their last transport date. A manually closed document can be reopened until that automatic-close deadline (`reopen_deadline`). - [Create a transport document](https://docs.factuarea.com/api-reference/transport-documents/public-api.v1.transport_documents.create): `POST /v1/companies/{company}/transport-documents` — Create a transport document (DeCA) in `draft`; the minimum data is only required to issue. - `company_role` (`shipper`/`carrier`) sets your party; `delivery_note_ids` (1 to 50) pre-fills shipments. - 422 `delivery_note_cancelled` or `invalid_gross_weight`; 409 `resource_conflict` is retryable. - Returns 201 with `Location`. - [Delete a draft transport document](https://docs.factuarea.com/api-reference/transport-documents/public-api.v1.transport_documents.delete): `DELETE /v1/companies/{company}/transport-documents/{transport_document}` — Delete a transport document that is still in `draft`, together with its shipments. It consumes no number and leaves no file. An issued document is always kept: deleting it returns 422 `transport_document_cannot_be_deleted`. Returns 204. - [List transport document issuance evidence](https://docs.factuarea.com/api-reference/transport-documents/public-api.v1.transport_documents.evidence): `GET /v1/companies/{company}/transport-documents/{transport_document}/evidence` — List the issuance evidence of a transport document in chronological order: versions, closes, reopenings, cancellation, supersession, email deliveries and public downloads. - Only the first 100 public downloads are listed; `meta.downloads_total` gives the full count. - Each entry names its actor in `actor_name`. A draft returns 422. - [List all transport documents](https://docs.factuarea.com/api-reference/transport-documents/public-api.v1.transport_documents.index): `GET /v1/companies/{company}/transport-documents` — List the transport control documents (DeCA) of your company with cursor-based pagination. - Filters: `status`, `transport_date[gte]`/`[lte]`, `company_role`, `carrier_tax_id`, `delivery_note_id`, `q`. - Sort with `sort` (default `-transport_date`). Any other query parameter returns 400. - [Download transport document issuance proof](https://docs.factuarea.com/api-reference/transport-documents/public-api.v1.transport_documents.issuance_proof): `GET /v1/companies/{company}/transport-documents/{transport_document}/issuance-proof` — Generate on demand a PDF proof of issuance with parties, every version (date, author, reason, sha256), status changes, email deliveries and public downloads. - Requires scope `transport_documents:read`; `pdfs:read` alone returns 403 `insufficient_scope`. - Not stored; pass `?download=1` for an attachment. A draft returns 422. - [Issue a transport document](https://docs.factuarea.com/api-reference/transport-documents/public-api.v1.transport_documents.issue): `POST /v1/companies/{company}/transport-documents/{transport_document}/issue` — Issue a draft transport document, assigning the next `DC` number and the permanent public URL, and storing PDF version 1. - Missing minimum data returns 422 `transport_document_not_issuable` with the list in `error.details.missing`. - A PDF over 5 MB returns 422 `transport_document_pdf_too_large`; nothing is issued. - Irreversible: requires `Idempotency-Key`. - [Modify an issued transport document](https://docs.factuarea.com/api-reference/transport-documents/public-api.v1.transport_documents.modify): `POST /v1/companies/{company}/transport-documents/{transport_document}/modify` — Modify an `issued` transport document during the service, keeping its number, URL and QR; stores a new PDF version. - Send the changes plus `reason` and `data_origin` (`company`/`carrier_reported`); parties are immutable. - 422 `transport_document_no_changes`; the 49th change returns `transport_document_version_limit_reached`. - Irreversible: requires `Idempotency-Key`. - [Download transport document PDF](https://docs.factuarea.com/api-reference/transport-documents/public-api.v1.transport_documents.pdf): `GET /v1/companies/{company}/transport-documents/{transport_document}/pdf` — Download the stored PDF of the current version or of `?version=N`, byte for byte as issued (never re-rendered). - Returns `application/pdf`; pass `?download=1` for an attachment. - A draft returns 422, a purged document 410 `transport_document_file_unavailable` and an unknown `version` 404 `transport_document_version_not_found`. - [Download transport document QR code](https://docs.factuarea.com/api-reference/transport-documents/public-api.v1.transport_documents.qr): `GET /v1/companies/{company}/transport-documents/{transport_document}/qr` — Download the QR code that encodes the permanent public URL of the document, generated on the server as `?format=svg` (default) or `?format=png`. The URL is the same in every version. Pass `?download=1` for `Content-Disposition: attachment`. A draft has no URL and returns 422. - [Reopen a transport document](https://docs.factuarea.com/api-reference/transport-documents/public-api.v1.transport_documents.reopen): `POST /v1/companies/{company}/transport-documents/{transport_document}/reopen` — Reopen a manually `closed` transport document with a `reason` (3–500 characters). It returns to `issued` without creating a version. Allowed only before the automatic-close deadline and never after an automatic close; otherwise 422 `transport_document_cannot_be_reopened`. - [Send a transport document by email](https://docs.factuarea.com/api-reference/transport-documents/public-api.v1.transport_documents.send): `POST /v1/companies/{company}/transport-documents/{transport_document}/send` — Email the stored PDF of the current version, with the public link, to up to 5 recipients across `to`, `cc` and `bcc`. - Only `issued` or `closed` documents; without `to`, the carrier contact's email is used, else 422 `transport_document_not_sendable`. - Irreversible: requires `Idempotency-Key`. A 500 `send_failed` records nothing; retry with a new key. - [Retrieve a transport document](https://docs.factuarea.com/api-reference/transport-documents/public-api.v1.transport_documents.show): `GET /v1/companies/{company}/transport-documents/{transport_document}` — Retrieve a transport document (DeCA) by its `id`, with parties, vehicle, shipments, goods, every version (author, reason, sha256), public URL and lifecycle dates. - Shipments built from a delivery note report `source_changed`/`source_changes` or `source_missing`. - Another company's document returns 404 `transport_document_not_found`. - [List transport document statuses](https://docs.factuarea.com/api-reference/transport-documents/public-api.v1.transport_documents.statuses): `GET /v1/companies/{company}/transport-documents/statuses` — List the closed catalog of transport document statuses (`draft`, `issued`, `closed`, `cancelled`, `superseded`) with their Spanish label and UI color. Use it to populate filters or status pickers instead of hard-coding values. The response `data` is an array of `{ value, label, color }` items. - [Mark a transport document as superseded](https://docs.factuarea.com/api-reference/transport-documents/public-api.v1.transport_documents.supersede): `POST /v1/companies/{company}/transport-documents/{transport_document}/supersede` — Mark an `issued` transport document as superseded by the carrier's own document; it becomes terminal (`superseded`). - Send `reference` (1-300 characters) and `reason`. A PDF over 5 MB returns 422 `transport_document_pdf_too_large`. - Irreversible: requires `Idempotency-Key`. - [Update a draft transport document](https://docs.factuarea.com/api-reference/transport-documents/public-api.v1.transport_documents.update): `PATCH /v1/companies/{company}/transport-documents/{transport_document}` — Partially update a transport document in `draft`: an absent field is kept, `null` clears it and `shipments` replaces the whole list. - Any other status returns 422 `transport_document_cannot_be_edited`; use `modify` for an issued document. - An impossible weight returns 422 `invalid_gross_weight`; an identifier collision returns 409 `resource_conflict` (retryable). - [List task activity](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.activities.list): `GET /v1/companies/{company}/tasks/{task}/activities` — List the activity log of a task, newest first: status and column changes, edits (with the changed fields), assignments, labels, comments, relations, attachments and time, each with its actor (`user`, `api_key`, `external` or `system`). Cursor-paginated with an OPAQUE cursor: pass the `next_cursor` back as `starting_after` untouched —activity entries have no `id` of their own. - [Assign a task](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.assign): `POST /v1/companies/{company}/tasks/{task}/assign` — Assign a task to a person of your company (`assignee_id`): a member, or a person of another account with `operate` access via an account relation. - Anyone else, including view-only relation access, returns 422 `task_assignee_not_member`. - Find assignable ids with `GET /v1/companies/{company}/users`. - [Upload a task attachment](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.attachments.create): `POST /v1/companies/{company}/tasks/{task}/attachments` — Upload a file to a task as `multipart/form-data` (`file`), up to 10 MB; the type is checked by content, not extension. - `target` places it in a new comment (default) or the description; `note` (max 1,000 characters) is the comment text. - Counts towards the plan storage quota (402 `storage_quota_exceeded`). Requires an `Idempotency-Key`. - [Delete a task attachment](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.attachments.delete): `DELETE /v1/companies/{company}/tasks/{task}/attachments/{attachment}` — Permanently delete an attachment and its file, freeing its storage. Irreversible: there is no trash or restore, so send an `Idempotency-Key` header (required) to retry safely. - [Download a task attachment](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.attachments.download): `GET /v1/companies/{company}/tasks/{task}/attachments/{attachment}/download` — Download the file of an attachment. The response `Content-Type` is the real type of the file as detected on upload (images, PDF, office documents, text, CSV, Markdown or ZIP); files that are not safe to display inline are served as `Content-Disposition: attachment` with `X-Content-Type-Options: nosniff`. - [List task attachments](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.attachments.list): `GET /v1/companies/{company}/tasks/{task}/attachments` — List the files attached to a task (in its description or its comments) with their name, MIME type and size. Returns a plain list, without pagination. - [Retrieve a task attachment](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.attachments.show): `GET /v1/companies/{company}/tasks/{task}/attachments/{attachment}` — Retrieve the metadata of an attachment: name, MIME type, size, where it is attached and who uploaded it. Use the download operation to get the file. - [Bulk delete tasks](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.bulk_delete): `POST /v1/companies/{company}/tasks/bulk-delete` — Permanently delete up to 200 tasks (`task_ids`) with their comments, attachments and time entries. - Irreversible; requires an `Idempotency-Key`. - Missing tasks are skipped; any task with invoiced hours rejects the whole request with 422 `task_time_entry_invoiced`. - [Bulk change task status](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.bulk_status): `POST /v1/companies/{company}/tasks/bulk-status` — Move up to 200 tasks (`task_ids`) to one board target: a `column_id` or a virtual `status`. Tasks that no longer exist or were moved are skipped silently; the result reports how many changed. More than 200 ids returns 422 `bulk_task_selection_too_large`. Requires an `Idempotency-Key`. - [Bulk update tasks](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.bulk_update): `POST /v1/companies/{company}/tasks/bulk-update` — Apply the same change to up to 200 tasks (`task_ids`): `priority`, `assignee_id` (`null` unassigns), `due_on` (`null` clears it), `add_label_id` and/or `remove_label_id`. A key you do not send is left untouched. Sending no change, or adding and removing the same label, returns 422. Requires an `Idempotency-Key`. - [Create a task comment](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.comments.create): `POST /v1/companies/{company}/tasks/{task}/comments` — Add a comment to a task as the member who owns the API key. `body` is Markdown; mentions of members notify them. - [Delete a task comment](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.comments.delete): `DELETE /v1/companies/{company}/tasks/{task}/comments/{comment}` — Permanently delete a comment. The author can delete their own comments; owners and admins can delete anyone's (moderation). Anyone else gets 403 `forbidden_action`. Irreversible: there is no trash or restore, so send an `Idempotency-Key` header (required) to retry safely. - [List task comments](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.comments.list): `GET /v1/companies/{company}/tasks/{task}/comments` — List the comments of a task, oldest first. Each comment has its Markdown `body` and an `author` whose `type` is `user`, `external` (synchronized from a code forge, with its `provider`), `imported` or `automation`. Cursor-paginated: pass the `next_cursor` of a page as `starting_after` to get the next one; `has_more` tells whether there are more. - [Update a task comment](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.comments.update): `PUT /v1/companies/{company}/tasks/{task}/comments/{comment}` — Edit the body of a comment. Only its author can edit it; comments synchronized from a code forge or imported cannot be edited (422 `task_comment_not_editable`). - [Create a task](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.create): `POST /v1/companies/{company}/tasks` — Create a task in a project; `project_id` and `title` are required. - It starts in the first column unless you send `column_id` or a virtual `status` (`planned` for the backlog). - `entity_link` (`type` + `id`) links a document or contact atomically; if the entity is not found or accessible, 404 `linked_entity_not_found` and no task is created. - [Set a task custom field value](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.custom_fields.set): `PUT /v1/companies/{company}/tasks/{task}/custom-fields/{field}` — Set the value of one custom field of the task's project. The value must fit the field type (and its options for `dropdown`/`multiselect`); `null` clears an optional field. An invalid value returns 422 `invalid_custom_field_value`. - [Delete a task](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.delete): `DELETE /v1/companies/{company}/tasks/{task}` — Permanently delete a task with its comments, attachments, relations and time entries. A task that has invoiced hours cannot be deleted (422 `task_time_entry_invoiced`) until the invoice is deleted. Irreversible: there is no trash or restore, so send an `Idempotency-Key` header (required) to retry safely. - [Duplicate a task](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.duplicate): `POST /v1/companies/{company}/tasks/{task}/duplicate` — Create a copy of a task at the end of the same column or backlog, with an optional new `title`. - Keeps description, priority, dates, labels, custom fields, assignee, parent and description attachments (these count towards storage, 402 `storage_quota_exceeded`). - Comments, activity, time entries, subtasks, other relations and links are not copied. - [Link a task to an entity](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.entity_links.create): `POST /v1/companies/{company}/tasks/{task}/entity-links` — Link a task to a Factuarea entity (`entity_type` + `entity_id`). An entity that does not exist, belongs to another company or whose module is not accessible returns 404 `linked_entity_not_found`. Linking it again returns the existing link. - [Unlink a task from an entity](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.entity_links.delete): `DELETE /v1/companies/{company}/tasks/{task}/entity-links/{link}` — Remove the link between a task and a Factuarea entity. The entity itself is not affected. - [List task entity links](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.entity_links.list): `GET /v1/companies/{company}/tasks/{task}/entity-links` — List the Factuarea entities a task is linked to (invoices, quotes, contacts, products…), with their display label. Plain list, no pagination. - A link is always returned; if its entity is deleted, its module is inaccessible or the key lacks the entity read scope, it has `available: false` and `summary: null`. - [Create a task external link](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.external_links.create): `POST /v1/companies/{company}/tasks/{task}/external-links` — Add a link to an external resource (`url`, `http` or `https`, with an optional `title`) to a task. Adding the same URL again returns the existing link. - [Delete a task external link](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.external_links.delete): `DELETE /v1/companies/{company}/tasks/{task}/external-links/{link}` — Remove a link added by hand from a task. Links synchronized from a code forge are managed by the integration. - [List task external links](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.external_links.list): `GET /v1/companies/{company}/tasks/{task}/external-links` — List the external links of a task: links added by hand and links synchronized from a code forge (issues, pull requests, branches). Returns a plain list, without pagination. - [Find a task by key](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.find_by_key): `POST /v1/companies/{company}/tasks/find-by-key` — Look up a task by its key (`DEV-12`) sent in the request body. Previous keys of a task keep working after moving it to another project or renaming the project key. Returns 404 `task_not_found` when no task of your company matches; a malformed key returns 422 `invalid_task_key`. A read-only lookup: no `Idempotency-Key` needed. - [Assign a label to a task](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.labels.assign): `POST /v1/companies/{company}/tasks/{task}/labels` — Add a label of your company catalog (`label_id`) to a task. Adding a label the task already has is a no-op. - [Remove a label from a task](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.labels.unassign): `DELETE /v1/companies/{company}/tasks/{task}/labels/{label}` — Remove a label from a task. The label stays in the catalog. - [List tasks linked to an entity](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.linked): `GET /v1/companies/{company}/tasks/linked` — List the tasks of any project linked to a Factuarea entity (`entity_type` + `entity_id`); archived tasks are included and flagged. - An entity that does not exist or belongs to another company returns an empty list. - Cursor-paginated: pass `next_cursor` as `starting_after`; `has_more` tells if there are more. - [Move a task to another project](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.move): `POST /v1/companies/{company}/tasks/{task}/move` — Move a task to another project of your company (`project_id`), optionally to a `column_id` or virtual `status` of the destination. The task gets a new key in the destination and keeps answering to its previous one. Custom field values the destination does not define are dropped. Moving it to the project it is already in returns 422 `task_already_in_project`. - [Create a task relation](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.relations.create): `POST /v1/companies/{company}/tasks/{task}/relations` — Relate a task to another task of your company (`target_task_id`) with a `type`: `subtask`, `blocks` or `related`. A task cannot relate to itself (422 `task_self_relation`), a relation that would close a cycle is rejected (422 `task_relation_cycle`) and an existing one returns 409 `task_relation_exists`. - [Delete a task relation](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.relations.delete): `DELETE /v1/companies/{company}/tasks/{task}/relations/{relation}` — Remove a relation between two tasks. The tasks themselves are not affected, and the relation can be created again. - [List task relations](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.relations.list): `GET /v1/companies/{company}/tasks/{task}/relations` — List the relations of a task: its subtasks and parent, the tasks it blocks and is blocked by, and related tasks, each with the other task's key, title and status. Returns a plain list, without pagination. - [Reposition a task](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.reposition): `POST /v1/companies/{company}/tasks/{task}/reposition` — Place a task at an exact position of its column (or of the backlog): either an `index` or a neighbour (`before_task_id` / `after_task_id`). Optionally move it to another column in the same call. - [Search tasks](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.search): `GET /v1/companies/{company}/tasks` — Search the tasks of your company across projects, filtering by `q`, `project_id`, `status`, `column_id`, `priority`, `assignee_id` (UUID or `me`), `label_id`, due dates and `completed`. - `sort` takes `created_at`, `updated_at`, `due_on`, `priority` or `number`; prefix `-` for descending (default `-created_at`). - Cursor-paginated: pass `next_cursor` as `starting_after`. - [Retrieve a task](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.show): `GET /v1/companies/{company}/tasks/{task}` — Retrieve a task with its key, board status and column, priority, dates, assignee, labels, custom field values and counters. A task of another company returns 404 `task_not_found`. - [Change task status](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.status): `POST /v1/companies/{company}/tasks/{task}/status` — Move a task to a board target: a `column_id` of its project, or a virtual `status` (`planned` for the backlog, `archived`). Moving it into a final column completes it; moving it out reopens it. It is placed at the end of the target; use `POST /v1/companies/{company}/tasks/{task}/reposition` to choose the position. - [Create a task time entry](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.time_entries.create): `POST /v1/companies/{company}/tasks/{task}/time-entries` — Log a closed period of work on a task (`started_at`, `ended_at`, ISO 8601), with an optional `description` and `billable` flag (default `true`). The period must end after it starts (422 `invalid_time_entry_period`). This is task time, unrelated to the working-day records of the time tracking module. - [Delete a task time entry](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.time_entries.delete): `DELETE /v1/companies/{company}/tasks/{task}/time-entries/{time_entry}` — Permanently delete a time entry. Invoiced entries cannot be deleted (422 `task_time_entry_invoiced`). Irreversible: there is no trash or restore, so send an `Idempotency-Key` header (required) to retry safely. - [List task time entries](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.time_entries.list): `GET /v1/companies/{company}/tasks/{task}/time-entries` — List the time logged on a task, newest first, with author, period, duration, `billable` flag and whether it was invoiced. - It is task time, not the working-day clock-ins at `/v1/companies/{company}/time-entries`. - Cursor-paginated: pass `next_cursor` as `starting_after`; `has_more` tells if there are more. - [Retrieve a task time entry](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.time_entries.show): `GET /v1/companies/{company}/tasks/{task}/time-entries/{time_entry}` — Retrieve one time entry of a task. A running timer appears as an entry with `ended_at: null`. - [Update a task time entry](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.time_entries.update): `PATCH /v1/companies/{company}/tasks/{task}/time-entries/{time_entry}` — Partially update a time entry: `started_at`, `ended_at`, `description` and `billable`. Invoiced entries cannot be edited (422 `task_time_entry_invoiced`) until the draft invoice is deleted. - [Start a task timer](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.timer.start): `POST /v1/companies/{company}/tasks/{task}/timer/start` — Start a timer on a task for the member who owns the API key. No request body. A member can run one timer at a time: if another is running, the call returns 409 `task_timer_already_running`; stop it with `POST /v1/companies/{company}/task-timers/stop`. - [Unassign a task](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.unassign): `POST /v1/companies/{company}/tasks/{task}/unassign` — Remove the assignee of a task. No request body. Unassigning a task that has no assignee is a no-op. - [Update a task](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.update): `PATCH /v1/companies/{company}/tasks/{task}` — Partially update a task (`PATCH` semantics): only the fields you send change. `title`, `priority`, `description` (Markdown), `start_on`, `due_on` and `assignee_id`; an explicit `null` clears `description`, `start_on`, `due_on` and `assignee_id` (`priority` cannot be null). `start_on` after `due_on` returns 422 `invalid_task_schedule`. - [Create a task upload link](https://docs.factuarea.com/api-reference/tasks/public-api.v1.tasks.upload_links.create): `POST /v1/companies/{company}/tasks/{task}/upload-links` — Create a single-use link to upload files to a task from a phone or by someone without an account. The link expires after 30 minutes and works once; the response includes the `url` (shown only now). `target` and `note` behave as in the attachment upload. - [Test a WooCommerce store connection](https://docs.factuarea.com/api-reference/woocommerce/public-api.v1.woocommerce.stores.connection_test): `POST /v1/companies/{company}/woocommerce/stores/{store}/connection-test` — Test the connection with a connected WooCommerce store; it reads the store's system status and writes nothing. - Returns 200 with `reachable`, `credential_accepted` and, on problems, a `failure_code` (e.g. `woocommerce_credentials_rejected`). - Requires `Idempotency-Key`; an unknown store returns 404 `store_not_found`. - [Archive a work schedule](https://docs.factuarea.com/api-reference/work-schedules/public-api.v1.work_schedules.archive): `POST /v1/companies/{company}/work-schedules/{schedule}/archive` — Archive a work schedule (transition `active` → `archived`), retiring it from use while preserving it. No request body. Returns 422 if it is already archived. Reversible via unarchive. - [Assign a schedule to an employee](https://docs.factuarea.com/api-reference/work-schedules/public-api.v1.work_schedules.assign): `POST /v1/companies/{company}/work-schedules/{schedule}/assign` — Assign the work schedule to an employee with an effective start date; the previous open assignment is closed and history is kept. - `employee_id` and `effective_from` (`Y-m-d`) are required. - An unknown employee returns 422 `assigned_employee_not_found`; moving back the start of an assignment already in effect returns 422. - A terminated employee is read-only: 422 `business_rule_violation` (`employee_inactive`). - Returns the created assignment. - [List a schedule’s assignments](https://docs.factuarea.com/api-reference/work-schedules/public-api.v1.work_schedules.assignments): `GET /v1/companies/{company}/work-schedules/{schedule}/assignments` — List the employees with an open assignment (`effective_to` = null) to this work schedule, as a flat list under `{ "data": [ … ] }`. - [Create a work schedule](https://docs.factuarea.com/api-reference/work-schedules/public-api.v1.work_schedules.create): `POST /v1/companies/{company}/work-schedules` — Create a weekly work schedule for your company (resolved from the API key). - `name` and `week_pattern` are required; `mode` defaults to `validated`. `week_pattern` lists ISO weekdays (1..7) with ordered, non-overlapping `HH:MM` ranges (empty `ranges` = rest day). - Returns the schedule with its `id`; `weekly_hours` is derived. - [Get an employee’s schedule on a date](https://docs.factuarea.com/api-reference/work-schedules/public-api.v1.work_schedules.employee_schedule): `GET /v1/companies/{company}/work-schedules/employee/{employee}` — Resolve the work schedule in effect for an employee on a day; `date` (`Y-m-d`) is optional and defaults to today. - Returns the schedule, not the assignment. - 404 `schedule_assignment_not_found` if none is in effect (or the employee belongs to another company); 422 for an invalid `date`. - [List all work schedules](https://docs.factuarea.com/api-reference/work-schedules/public-api.v1.work_schedules.list): `GET /v1/companies/{company}/work-schedules` — List the weekly work schedules of your company with cursor-based pagination. Supports filtering by `status` (`active`/`archived`) and `mode` (`validated`/`real_clocking`), plus free-text `search` over the schedule name. - [Retrieve a work schedule](https://docs.factuarea.com/api-reference/work-schedules/public-api.v1.work_schedules.show): `GET /v1/companies/{company}/work-schedules/{schedule}` — Retrieve a single work schedule by its `id` (UUID v7). A schedule belonging to another company returns 404 `work_schedule_not_found` (anti-enumeration). - [Get work schedule stats](https://docs.factuarea.com/api-reference/work-schedules/public-api.v1.work_schedules.stats): `GET /v1/companies/{company}/work-schedules/stats` — Aggregated KPIs for your work schedules: total count, active and archived counts, a breakdown by mode (`validated`/`real_clocking`) and the number of employees with an assigned schedule. Returned as `{ "data": … }`. - [Unarchive a work schedule](https://docs.factuarea.com/api-reference/work-schedules/public-api.v1.work_schedules.unarchive): `POST /v1/companies/{company}/work-schedules/{schedule}/unarchive` — Unarchive a work schedule (transition `archived` → `active`), returning it to use. No request body. Returns 422 if it is already active. - [Unassign a schedule from an employee](https://docs.factuarea.com/api-reference/work-schedules/public-api.v1.work_schedules.unassign): `POST /v1/companies/{company}/work-schedules/{schedule}/unassign` — Close the employee's open assignment to this schedule; `employee_id` is required and `effective_to` (`Y-m-d`) defaults to today. - An assignment not yet started is cancelled and kept in history as an empty span. - Closing an assignment in effect before its start returns 422; no open assignment returns 404. Responds 204. - [Update a work schedule](https://docs.factuarea.com/api-reference/work-schedules/public-api.v1.work_schedules.update): `PATCH /v1/companies/{company}/work-schedules/{schedule}` — Partially update a work schedule; an omitted field keeps its value. - A sent `week_pattern` replaces the whole pattern and `weekly_hours` is recomputed. - An invalid value returns 422 and changes nothing. Returns the updated schedule. - [All error codes](https://docs.factuarea.com/guides/errors/all): Complete reference of every public API error code, grouped by bounded context, with its HTTP status and type. - [FAQ](https://docs.factuarea.com/es/faq): Respuestas rápidas a las preguntas que más surgen al integrar la API pública de Factuarea — claves, modo de prueba, dinero, fechas, idempotencia y límites de peticiones. - [API de Factuarea](https://docs.factuarea.com/es): La API REST de Factuarea para automatizar tu SaaS de facturación multi-tenant para empresas españolas. - [Precios y límites de la API](https://docs.factuarea.com/es/pricing): Qué cuesta la API, qué tier otorga cada plan y los topes por tier de peticiones, API keys y endpoints de webhook. - [Explorar la API](https://docs.factuarea.com/es/reference): Busca una operación o entra en el dominio con el que vas a trabajar. - [Soporte](https://docs.factuarea.com/es/support): Cómo contactar con el equipo de la API de Factuarea, qué incluir al reportar un problema, cómo funciona el acceso a la API, la página de estado y el changelog. - [Agentes y scripting](https://docs.factuarea.com/es/cli/agents): El contrato agent-first del CLI factuarea — JSON estable por stdout, errores estructurados por stderr, exit codes semánticos, el manifiesto commands --json, scope-check local y confirmación tipada de operaciones irreversibles. - [Devloop](https://docs.factuarea.com/es/cli/devloop): Prueba los webhooks de Factuarea en local sin desplegar ni ngrok — factuarea listen reenvía los eventos de un NIF a localhost con un cuerpo firmado, factuarea trigger produce eventos reales en sandbox. - [Resumen del CLI](https://docs.factuarea.com/es/cli): Instala y autentica el CLI oficial factuarea — maneja la API REST v1 desde tu terminal con brew, npm o un instalador curl. Agent-first, inspirado en Stripe. - [Uso](https://docs.factuarea.com/es/cli/usage): El árbol de comandos de factuarea — list, show, create, acciones de dominio, plantillas PDF, escrituras condicionales, descargas binarias, subidas multipart, el escape hatch genérico api y el manifiesto commands --json. - [Ajustes del contrato de cuentas](https://docs.factuarea.com/es/changelog/account-contract-adjustments): Correcciones del contrato v1 tras la revisión del 6 de octubre, compras duraderas en el eje de empresa y la forma final de las cuentas gestionadas, el NIF adicional y el tope de usuarios. - [Modelo de cuentas](https://docs.factuarea.com/es/changelog/account-model): Cuentas, NIF, miembros, acceso cedido, cuentas gestionadas, importación masiva, webhooks de cuenta y las operaciones y campos que añaden o renombran. - [Equipo, claves y logs en el eje de cuenta](https://docs.factuarea.com/es/changelog/account-team-keys-and-logs): Una operación nueva, el uso diario de una API key, y campos nuevos en claves, miembros, invitaciones, logs de peticiones y dominios de retorno de Stripe Connect, además de la corrección sobre reactivar un endpoint de webhook de cuenta desactivado. - [Vista previa del alta y detalles de cuenta](https://docs.factuarea.com/es/changelog/accounts-provisioning-preview-and-details): Una operación nueva, la vista previa de lo que costaría una cuenta gestionada nueva, y campos nuevos en empresas, traspasos de NIF, cuentas gestionadas, cambio de plan, importación masiva y consolidado de RR. HH., y una caducidad del vale que ahora se devuelve siempre al reemitir. - [API y MCP incluidos en todos los planes](https://docs.factuarea.com/es/changelog/api-included-in-plans): El acceso a la API pública y MCP está incluido en todos los planes de Factuarea. Los límites de peticiones siguen el plan activo y también hay acceso durante el trial. - [Nota configurable en las facturas automáticas](https://docs.factuarea.com/es/changelog/automatic-invoice-note): Las cuentas conectadas y las tiendas aceptan una invoice_note que Factuarea escribe en las notas de las facturas que emite automáticamente, y esas facturas vencen a los 30 días por defecto. Siete operaciones actualizadas y dos tools MCP actualizadas. - [Tope de automatizaciones activas](https://docs.factuarea.com/es/changelog/automation-active-rules-cap): El tope de activas, el error de activación y el consumo active_rules en API y MCP. - [Automatizaciones](https://docs.factuarea.com/es/changelog/automations): Crea reglas a partir de eventos, previsualiza sus efectos y consulta cada ejecución. Dieciocho operaciones cubren reglas, versiones, ejecuciones, relanzamiento y consumo. - [Una sola ventana de rotura: eje y payload](https://docs.factuarea.com/es/changelog/axis-and-payload-breaking-window): Los recursos de empresa y de cuenta pasan a la URL, los importes viajan como cadenas decimales, la fecha de cobro cambia de nombre, X-Active-Profile se rechaza y la cuenta pasa a ser el cliente. Todas las operaciones que toca la ventana —519— recurso por recurso. - [Las operaciones recientes pasan al eje](https://docs.factuarea.com/es/changelog/axis-for-recent-operations): Las operaciones publicadas desde el 21 de septiembre —proyectos y tareas, el escáner de gastos, notificaciones, usuarios, la representación VeriFactu, emitir sin enviar y la edición de series— viven bajo /v1/companies/{company}, y ocho actualizaciones parciales pasan de PUT a PATCH. - [API de contactos](https://docs.factuarea.com/es/changelog/canonical-contacts): Gestiona una sola identidad con roles acumulables de cliente, proveedor y lead. La API canónica ya cubre creación y archivado en lote, búsqueda por identificadores, verificación censal AEAT, estadísticas, actividad e importaciones. - [Cobertura completa de catálogo y tarifas](https://docs.factuarea.com/es/changelog/catalog-price-lists): Gestiona presentaciones, variantes, ofertas de proveedores y tarifas. Los documentos conservan snapshots de precio y hacen explícita la actualización de precios. - [Selecciones configurables y precios exactos de catálogo](https://docs.factuarea.com/es/changelog/catalog-selections): Configura qué combinaciones de producto se pueden vender y resuelve precios negociados exactos. La API incorpora consulta de selecciones, auditoría de stock y resolución de precios en lote. - [Razón social y nombre comercial de una empresa](https://docs.factuarea.com/es/changelog/company-legal-and-trade-name): name es el nombre con que se conoce a una empresa y business_name su razón social cuando es distinta. Las respuestas siguen ese contrato en todas las empresas, la edición parcial se resuelve sobre los nombres actuales y los dos campos admiten hasta 100 caracteres. - [Impuestos propios de la empresa](https://docs.factuarea.com/es/changelog/company-taxes): Crea, edita y elimina tus propios impuestos junto al catálogo de Factuarea, que es de solo lectura, distínguelos con el nuevo campo ownership y fija los predeterminados solo para tu empresa. Dos tools MCP nuevas, un scope OAuth nuevo y dos códigos de error nuevos. - [Eliminar y archivar contactos](https://docs.factuarea.com/es/changelog/contact-delete-and-archive): Cambio que rompe: DELETE /v1/contacts/{id} y POST /v1/contacts/bulk-delete eliminan en lugar de archivar, y la eliminación no se puede deshacer desde la API. Archivar pasa a POST /v1/contacts/{id}/archive, está siempre permitido y sigue siendo reversible. Se publica el evento webhook contact.deleted y desaparece el subcode contact_has_commercial_references. - [Seguimiento y resultados íntegros de importaciones de contactos](https://docs.factuarea.com/es/changelog/contact-import-integrity-and-tracking): Previsualiza archivos de contactos, consulta resultados confirmados por fila y descarga informes de errores autorizados. - [Rellena las plantillas de contactos antes de importar](https://docs.factuarea.com/es/changelog/contact-import-template-roundtrip): Previsualiza plantillas vacías conservando sus columnas y gestiona empty_import antes de aplicar una importación. - [Plazas contratadas, paquetes de oferta y prueba](https://docs.factuarea.com/es/changelog/contracted-seats-offers-and-trial): La factura sigue las plazas que contratas: crear un empleado ocupa una plaza libre, reducir tiene efecto en la renovación sin abono y eliges a quién se desactiva. Cuatro operaciones nuevas fijan y previsualizan las plazas, la API REST y el MCP compran solos las plazas que faltan, los paquetes de oferta conservan sus precios mientras se mantienen sus mínimos y la prueba responde con su propio motivo. - [Tope anual de documentos en la API y MCP](https://docs.factuarea.com/es/changelog/document-annual-quota): El tope anual, las operaciones v1 afectadas (14 en total), los errores MCP y la emisión automática. - [Biblioteca de plantillas PDF y facturas estructuradas](https://docs.factuarea.com/es/changelog/document-templates-and-structured-invoices): Gestiona plantillas PDF e identidades de marca, elige la presentación de cada documento, prepara artefactos PDF exactos y lleva calendarios de pagos, referencias y centros DIR3 en las facturas. Cincuenta operaciones nuevas, los scopes pdf_templates y un bloque pdf_output_state en cada documento. - [Lotes de empleados y ofertas privadas de asientos](https://docs.factuarea.com/es/changelog/durable-customer-purchases): Nuevas operaciones duraderas para lotes de empleados y ofertas de asientos de empleados o empresas gestionadas dirigidas a una empresa. - [Asientos de empleado cobrados siempre que el plan factura](https://docs.factuarea.com/es/changelog/employee-seat-charges): Dar de alta o reactivar un empleado cobra un asiento siempre que el plan factura, también en past_due y en planes concedidos; los empleados de la prueba se desactivan al empezar el cobro, hay un 503 nuevo con los lotes activados y las ofertas de asientos sobre una suscripción activa empiezan en la siguiente renovación. Ocho operaciones actualizadas. - [Coherencia de la causa de exención y conflicto al generar recurrentes](https://docs.factuarea.com/es/changelog/exemption-cause-coherence-and-recurring-conflict): Cambian tres operaciones: la vista previa de la factura acepta un exemption_reason opcional, guardar o emitir una factura con causa de cabecera sin IVA y líneas con IVA responde 422 exemption_cause_contradicts_taxed_lines, y generar una factura recurrente puede responder un 409 reintentable recurring_presentation_activation_changed. - [Resultados de importación, reintentos de tareas y campos nuevos](https://docs.factuarea.com/es/changelog/import-tracking-and-task-idempotency): La importación de contactos informa de filas actualizadas, avisos y del motivo de cada fila omitida; la de tareas se reintenta sin duplicar; las facturas exponen origin; presupuestos y proformas exponen operation_regime. - [Actividad de la factura: resultados de la AEAT, correo y cobros](https://docs.factuarea.com/es/changelog/invoice-activity-events): La línea de tiempo de la factura añade el resultado de cada envío a la AEAT, los correos no entregados, la primera visita diaria al enlace público y los eventos de cobro, cada uno con un contrato exacto de metadata. - [Emitida no es enviada: versión de la API 2026-10-01](https://docs.factuarea.com/es/changelog/invoice-issued-vocabulary): Las facturas separan la emisión de la entrega. La versión opcional 2026-10-01 publica el estado issued con issued_at, is_sent y sent_via; nuevo POST /v1/invoices/{invoice}/issue; mark-sent registra una entrega manual desde esa versión; nuevos eventos invoice.issued, invoice.marked_sent e invoice.unsent, con invoice.sent como alias deprecado; payloads de webhook versionados por endpoint; las facturas recurrentes ganan generation_mode. La versión predeterminada no cambia. - [Gastos y Facturas: nuevos nombres de producto](https://docs.factuarea.com/es/changelog/invoice-product-terminology): Las facturas de compra pasan a llamarse Gastos y las facturas de venta, Facturas. Las integraciones conservan sus interfaces. - [Qué cambia en Factuarea.](https://docs.factuarea.com/es/changelog/launch): Versiones, cambios de contrato y novedades de las herramientas para tu integración. - [Las tools MCP de envío masivo ya aplican el tope de 200 ids por lote](https://docs.factuarea.com/es/changelog/mcp-bulk-send-limit): Las tools MCP de envío masivo rechazan los lotes de más de 200 IDs con un error claro. El comportamiento REST se mantiene. - [Consentimiento OAuth: cuenta, nivel y permisos que ya no se conceden](https://docs.factuarea.com/es/changelog/mcp-consent-account-and-level): La pantalla de consentimiento del MCP pide elegir cuenta y empresa, no concede escritura con nivel Ver ni los permisos de módulos vetados en Pruebas, y la solicitud caduca a los 5 minutos. - [MCP: errores más claros, acceso desde ChatGPT y listas de tools más estables](https://docs.factuarea.com/es/changelog/mcp-real-clients-compatibility): Las tools MCP vuelven a informar de los errores de negocio, OAuth admite private_key_jwt para clientes como ChatGPT, los cursores de tools/list duran 24 horas y cuatro nombres antiguos de contactos se retiran el 15 de noviembre de 2026. - [Devoluciones e importe neto de los cobros no facturados](https://docs.factuarea.com/es/changelog/non-invoiced-charges-refunds): Los cobros de Stripe que no se facturan llevan sus devoluciones y el importe neto que se queda el comercio, se pueden filtrar por fecha y llegan a la gestoría en el envío trimestral como CSV. Cuatro operaciones actualizadas y tres tools MCP actualizadas. - [Packs y un escaparate común para productos](https://docs.factuarea.com/es/changelog/packs-and-storefront): Los packs tienen su propia API con imágenes y vista de escaparate, los productos se pueden publicar en la web con precio con y sin IVA, y las facturas admiten líneas de pack con el precio cobrado. - [Pagos anticipados y validación de la fecha de pago](https://docs.factuarea.com/es/changelog/payment-date-advance-payments): Una fecha de pago anterior a la de emisión se acepta ahora como pago anticipado, y una fecha de pago posterior a hoy responde 422. Afecta a ventas y gastos, a marcar como pagada y a registrar un pago. - [Un justificante por cada cobro](https://docs.factuarea.com/es/changelog/payment-receipts-per-payment): Los justificantes se emiten por cobro, también los parciales: las operaciones de justificante de facturas y gastos aceptan un payment_id opcional y sus tools MCP devuelven el número del justificante. Los PDF de documentos muestran el IBAN del emisor solo con formas de pago bancarias y usan 9 pt de tamaño base por defecto. Dos operaciones y dos tools MCP actualizadas. - [Anulación de cobros](https://docs.factuarea.com/es/changelog/payment-reversal): Anula un cobro conservando el registro original y su trazabilidad. El saldo de la factura refleja la anulación y las integraciones reciben el evento correspondiente. - [Capacidades PDF en la cuenta](https://docs.factuarea.com/es/changelog/pdf-capabilities): El recurso Account y el endpoint de plantillas exponen un bloque de capacidades de solo lectura: qué permite el plan en la marca de los documentos, qué plantillas pueden fijarse y qué plan desbloquea el editor. Las actualizaciones de personalización fuera del plan devuelven ya 403. - [Opciones de maquetación de las plantillas PDF](https://docs.factuarea.com/es/changelog/pdf-template-layout-options): La configuración de las plantillas PDF incorpora las claves de schema_version 2: cabecera y lado del logo, estilo y concepto de la tabla de líneas, pie legal, densidad de página, tamaño de letra por zona, colores de realce y de superficie, texto de privacidad, condiciones generales, títulos opcionales de bloque, el tamaño de marca xl y la columna de importe con impuesto. Las revisiones informan schema_version. - [La personalización se aplica a la plantilla principal](https://docs.factuarea.com/es/changelog/personalization-main-template): En las empresas que ya usan la biblioteca de plantillas PDF, PATCH /v1/companies/{company}/personalization y update_account_personalization aplican el diseño y el color de acento a la plantilla principal, y personalization lee sus valores efectivos. El contrato no cambia; el error nuevo es 409 pdf_main_template_required. - [Escalera de planes: Esencial, Profesional, Avanzado y Enterprise](https://docs.factuarea.com/es/changelog/plan-ladder): Nuevos nombres comerciales y Avanzado en el contrato de cuenta, con capacidad de API incluida en cada plan. - [Lanzamiento de la plataforma](https://docs.factuarea.com/es/changelog/platform-launch): La plataforma pública reúne la API REST v1, los SDKs oficiales de TypeScript y PHP, el CLI y MCP, con un sandbox aislado para probar integraciones. - [Unidades contadas, peso por piezas y sustitución por cambio de unidad base](https://docs.factuarea.com/es/changelog/product-units-and-base-unit-change): Vende en paquetes, cajas o piezas un producto medido en kilos o litros, registra las piezas en las líneas de peso variable, sustituye un producto por otro con distinta unidad base con vista previa y ejecución irreversible, y lee la unidad real en FacturaE y UBL. Dos operaciones nuevas, dos tools MCP, el evento product.replaced y campos nuevos en productos y líneas de documento. - [Ofertas sobre una variante y una presentación a la vez](https://docs.factuarea.com/es/changelog/promotion-variant-and-presentation): Un artículo de una oferta puede apuntar a una presentación vendida con su variante, como artículo propio con su precio y su precio anterior. Cinco operaciones de ofertas actualizadas y dos tools MCP actualizadas. - [Ofertas y precio anterior](https://docs.factuarea.com/es/changelog/promotions): Pon productos y packs en oferta con fechas y canales. Las lecturas exponen la oferta y el precio anterior legal, y la resolución de precios admite fecha, canal y el cliente de la web. - [Líneas de compra medidas](https://docs.factuarea.com/es/changelog/purchase-measurements): Las líneas de factura de compra registran ya los bultos recibidos, la unidad a la que se aplica el coste del proveedor y la medida real. El contrato añade un bloque de medida, persiste el descuento de línea, resuelve el coste desde la oferta del proveedor y duplica una compra desde un origen autorizado. - [Escaneos de compra: historial acotado, OCR aplazado y faceta de proveedores](https://docs.factuarea.com/es/changelog/purchase-scan-detail-history): El detalle del escaneo devuelve ahora los 50 intentos y eventos de auditoría más recientes con sus totales, los escaneos que esperan la cuota diaria de OCR lo indican y las estadísticas añaden una faceta por proveedor. - [Escáner de gastos: original no disponible](https://docs.factuarea.com/es/changelog/purchase-scan-source-unavailable): Reintentar, convertir y restaurar identifican ahora cuándo ya no se conserva el archivo original del escaneo. - [Escáner de compras: API pública y MCP](https://docs.factuarea.com/es/changelog/purchase-scanner-api): Sube, revisa, resuelve duplicados y convierte escaneos de compra desde la API pública y MCP. Trece operaciones cubren todo el flujo, el buzón del escáner y las categorías de gasto. - [Pausar y reanudar facturas recurrentes en bloque](https://docs.factuarea.com/es/changelog/recurring-invoice-bulk-status): Nueva operación POST /v1/recurring_invoices/bulk-status: mueve hasta 50 facturas recurrentes a active o paused con éxito parcial, con la tool MCP bulk_change_recurring_invoice_status como espejo. Reanudar una recurrencia completada responde ahora 422 recurring_invoice_completed_cannot_resume. - [Edita series de numeración](https://docs.factuarea.com/es/changelog/series-update): Actualiza una serie con PUT /v1/series/{series} y la tool MCP update_series, bajo las mismas guardas fiscales que la aplicación web. - [Uso de la cuenta: mensaje de error genérico](https://docs.factuarea.com/es/changelog/storage-quota-generic-message): El mensaje y la guía de storage_quota_exceeded remiten ahora a soporte sin cifras de uso. - [Tiendas, MCP y ejemplos completos de respuesta](https://docs.factuarea.com/es/changelog/stores-mcp-responses): Conecta tiendas WooCommerce y Shopify, trabaja con snapshots de pedidos y usa el transporte MCP actualizado. Cada respuesta documentada tiene un ejemplo explícito o la representación de descarga adecuada. - [Stripe Connect en marca blanca](https://docs.factuarea.com/es/changelog/stripe-connect-white-label): Cuatro operaciones y cuatro códigos de error nuevos para que tus clientes conecten su propia cuenta de Stripe desde tu producto, con dominios de retorno que controlas tú. - [Envía cada factura automática a quien paga](https://docs.factuarea.com/es/changelog/stripe-email-invoice-to-payer): Las cuentas conectadas de Stripe aceptan email_invoice_to_payer, que envía por email cada factura que Factuarea emite automáticamente a la dirección que llega con el cobro. Tres operaciones actualizadas y una tool MCP actualizada. - [Cuentas de Stripe existentes y reglas de cobro](https://docs.factuarea.com/es/changelog/stripe-existing-accounts-and-charge-rules): Conecta una cuenta de Stripe que ya tienes, decide por cuenta qué cobros se facturan y cuáles no, y consulta los cobros que quedaron fuera. Seis operaciones nuevas, tres campos nuevos en las cuentas conectadas y cinco motivos nuevos en la bandeja. - [Comisiones de Stripe como gasto y una liquidación más detallada](https://docs.factuarea.com/es/changelog/stripe-platform-account-and-fee-expenses): Las cuentas de Stripe conectadas pueden registrar cada mes sus comisiones de Stripe como gasto, los payouts detallan ahora todos los movimientos que liquidan y los gastos que autoliquidan su IVA ya no lo cuentan en el total. Nueve operaciones actualizadas, tres campos nuevos en la cuenta, tres campos nuevos en el payout y un método de conexión nuevo. - [Las personas con acceso operate pueden recibir tareas](https://docs.factuarea.com/es/changelog/tasks-people-from-granted-access): El listado de usuarios y el usuario actual incluyen ahora a las personas de otras cuentas que llegan a la empresa con acceso operate, y se les puede asignar una tarea. Tres operaciones actualizadas; ningún campo cambia. - [Ajustes de Tareas](https://docs.factuarea.com/es/changelog/tasks-review-fixes): Límites más precisos y errores más claros en Proyectos y Tareas: descripción de tarea de hasta 400.000 caracteres, tarifa por hora de hasta 99.999.999,99, vínculos que respetan los scopes, id de la tarea en las notificaciones, borrados bloqueados por horas facturadas y facturación de horas idempotente. users:read pasa a ser un scope sensible. - [Proyectos y tareas](https://docs.factuarea.com/es/changelog/tasks): El módulo de tareas llega a la API: proyectos con su tablero, tareas, etiquetas, temporizadores, usuarios, notificaciones y la agenda — 80 endpoints nuevos, 21 eventos, 80 tools MCP y cuatro acciones de automatización. - [Informes fiscales: libro de trabajo y tools para agentes](https://docs.factuarea.com/es/changelog/tax-report-workbooks): Los informes fiscales usan un libro de trabajo Excel y exponen nueve tools MCP. Los endpoints existentes documentan con precisión los formatos de salida admitidos. - [Un empleado dado de baja es de solo lectura](https://docs.factuarea.com/es/changelog/terminated-employees-read-only): Fichar la entrada, asignar un horario o una política de ausencias, aprobar una ausencia que pasa de la baja e invitar al portal a un empleado dado de baja responden 422 con el subcode employee_inactive. El resumen de equipo lista a todo empleado de alta en el mes, tenga o no horario. - [El control horario respeta el periodo de alta](https://docs.factuarea.com/es/changelog/time-tracking-employment-period): Cambio que rompe: fichar antes de la fecha de alta de un empleado o después de su fecha de baja responde ahora 422 con el subcode clocking_outside_employment_period. Los saldos diarios añaden is_unscheduled e is_outside_employment, la hoja mensual y el resumen de equipo añaden un bloque to_date con los días cerrados, el horario del empleado acepta una fecha, hire_date pasa a ser editable, y reasignar o desasignar un horario que aún no ha empezado lo anula. - [Control horario](https://docs.factuarea.com/es/changelog/time-tracking): Gestiona horarios, fichajes, ausencias, balances y presencia desde la API y MCP, con el mismo modelo de permisos que el resto de la plataforma. - [Las plantillas de documentos de control tienen su propio tipo](https://docs.factuarea.com/es/changelog/transport-control-templates): Las plantillas PDF y sus revisiones informan de document_kind (commercial o transport-document). Crear y duplicar lo aceptan, el listado filtra por él, y el default de documentos de control en PATCH /v1/companies/{company}/pdf-templates/defaults solo acepta plantillas del tipo transport-document. - [Los documentos de control usan la biblioteca de plantillas PDF](https://docs.factuarea.com/es/changelog/transport-document-pdf-templates): El PDF del documento de control de transporte (DeCA) toma su diseño de la biblioteca de plantillas. El default de documentos de control se fija en PATCH /v1/companies/{company}/pdf-templates/defaults y en la tool MCP, y cada versión del DeCA informa del diseño con el que se pintó en versions[].presentation. - [Documento de control (DeCA) y peso de transporte](https://docs.factuarea.com/es/changelog/transport-documents-deca): Nuevo recurso transport_documents con 17 endpoints para emitir, modificar, compartir y conservar el documento de control digital del transporte de mercancías por carretera, obligatorio desde el 5 de octubre de 2026; 15 tools MCP, 10 eventos transport_document.*, 24 códigos de error y peso bruto de transporte en productos, variantes, presentaciones y albaranes. - [Facturación desde terminales desatendidos](https://docs.factuarea.com/es/changelog/unattended-checkout-invoicing): Una factura simplificada ya cobrada desde un cajero en una sola llamada idempotente, la remisión de VeriFactu a través de Factuarea, la subsanación de registros aceptados y errores por línea. Tres cambios que rompen: una línea sin tipo ya no toma el 21 %, emitir se rechaza cuando el registro no cabe en el esquema de la AEAT y, en modo NO VERI*FACTU, hace falta un certificado utilizable. POST /v1/verifactu/records/{id}/retry ya no responde max_retries_exceeded. - [v1.13.0 — Paridad de contrato](https://docs.factuarea.com/es/changelog/v1-13-0): Semántica de escritura de producto, consentimiento OAuth ampliado, capacidad API derivada del plan y notas multilínea en PDF. - [VeriFactu informa del entorno real de la AEAT](https://docs.factuarea.com/es/changelog/verifactu-instance-environment): La configuración y los registros de VeriFactu devuelven el entorno de la AEAT y el envío automático de la instancia: en la API de producción, siempre la AEAT real y de forma automática. environment y auto_transmit quedan obsoletos en la actualización de ajustes. Cuatro operaciones actualizadas y cuatro tools MCP actualizadas. - [Plugin de Claude Code](https://docs.factuarea.com/es/mcp/claude-code-plugin): Dos plugins oficiales en un mismo marketplace — factuarea-mcp conecta Claude Code al servidor MCP de Factuarea, y factuarea-api trae cinco skills para construir la propia integración. - [Conectar un cliente](https://docs.factuarea.com/es/mcp/connect): Conecta cualquier cliente MCP por Streamable HTTP, o mediante el servidor local de npm, y autentícalo con OAuth o API key. - [Errores y límites de peticiones](https://docs.factuarea.com/es/mcp/errors): Formas de error JSON-RPC mapeadas desde el contrato v1, la tabla completa de códigos y throttling por token / por plan con Retry-After. - [Resumen de MCP](https://docs.factuarea.com/es/mcp): Conecta agentes de IA a Factuarea sobre el Model Context Protocol — tools de facturación, catálogo, precios, cumplimiento, control horario, proyectos y tareas, automatizaciones, webhooks y el modelo de cuentas, con autenticación OAuth 2.1 y API key. - [Protocolo y transporte MCP](https://docs.factuarea.com/es/mcp/protocol): Revisión 2026-07-28 con discovery sin sesiones, compatibilidad con clientes 2025-11-25 y 2025-06-18, cabeceras explícitas y paginación por credencial. - [Recursos y prompts](https://docs.factuarea.com/es/mcp/resources-and-prompts): Lee las reglas fiscales y usa los cinco flujos guiados antes de invocar herramientas de negocio. - [Scopes y permisos](https://docs.factuarea.com/es/mcp/scopes): El catálogo de scopes del consentimiento OAuth, cómo se mapea a los scopes detallados que aplican las tools, los scopes de cuenta y privilegiados, el super-scope y el gating por plan/módulo. - [Catálogo de tools](https://docs.factuarea.com/es/mcp/tools): Todas las tools del MCP de Factuarea agrupadas por dominio, más las diez tools privilegiadas de cuentas gestionadas, con el scope que requiere cada una y su categoría de límite de peticiones. - [Integración GoCardless](https://docs.factuarea.com/es/payments/gocardless): Estado de la integración con GoCardless — todavía no liberada, qué existe ya detrás del flag, y la superficie v1 y MCP exacta que aparece el día que se enciende. - [Bandeja de eventos de integración](https://docs.factuarea.com/es/payments/integration-events-inbox): Por qué un cobro no acabó en factura — los motivos de descarte tipados, cuáles te avisan, cuáles parquean el evento para que puedas reprocesarlo, y cómo funciona la ventana de retención de 30 días. - [Conciliar con la metadata de sistema](https://docs.factuarea.com/es/payments/metadata-reconciliation): Las claves de metadata que Factuarea escribe en las facturas auto-emitidas desde un ciclo de suscripción de Stripe, y cómo usar el filtro de metadata para sacar todas las facturas de una suscripción o de un periodo de facturación. - [Integración MONEI](https://docs.factuarea.com/es/payments/monei): Estado de la integración con MONEI — todavía no liberada, qué existe ya detrás del flag, por qué no tiene recurso de mandatos, y la superficie v1 y MCP exacta que aparece al liberarse. - [Payouts y conciliación bancaria](https://docs.factuarea.com/es/payments/payouts-reconciliation): Cómo Factuarea ingiere los payouts de Stripe, los vincula con los cobros que agrupan, los concilia contra tu extracto Norma 43 y emite el evento payout.reconciled. - [Auto-facturación con Stripe](https://docs.factuarea.com/es/payments/stripe-autoinvoicing): Emite facturas automáticamente desde los cobros de Stripe Connect — captura de NIF en el Checkout, umbral de factura simplificada, exigir NIF y qué cobros se derivan a revisión manual. - [Conectar Stripe en marca blanca](https://docs.factuarea.com/es/payments/stripe-connect-white-label): Deja que tus clientes conecten su propia cuenta de Stripe a un NIF desde tu producto. Da de alta tus dominios de retorno, inicia la autorización, lleva a la persona a Stripe y lee el resultado cuando vuelva. - [Comisiones de Stripe como gasto](https://docs.factuarea.com/es/payments/stripe-fee-expenses): Registra como gasto mensual las comisiones que Stripe cobra a tu cuenta conectada, con el tratamiento fiscal que elijas, y recupera los meses que ya han pasado. - [Resumen de los SDKs](https://docs.factuarea.com/es/sdks): SDKs oficiales de TypeScript y PHP para la API de Factuarea — instala @factuarea/sdk o factuarea/factuarea-php y obtén reintentos, idempotencia, paginación por cursor, errores tipados y verificación de webhooks de serie. - [PHP](https://docs.factuarea.com/es/sdks/php): Instala factuarea/factuarea-php con Composer, autentícate y crea tu primera factura. PSR-4, basado en Guzzle, PHP 8.2+. - [TypeScript](https://docs.factuarea.com/es/sdks/typescript): Instala @factuarea/sdk para Node.js, autentícate y crea tu primera factura. ESM + CommonJS dual, declaraciones de tipos completas, Node 20+. - [Herramientas para construir](https://docs.factuarea.com/es/tools): Elige tu SDK, trabaja desde la terminal o genera un cliente desde OpenAPI. - [El contrato, listo para tus herramientas.](https://docs.factuarea.com/es/tools/openapi): Usa OpenAPI para explorar la API o generar un cliente. Los SDKs oficiales son la primera opción para TypeScript y PHP. - [Ausencias](https://docs.factuarea.com/es/guides/absences): Configura tipos y políticas de ausencia, gestiona las solicitudes y lee los saldos y el calendario de equipo sobre la API v1. - [Personalización de la cuenta](https://docs.factuarea.com/es/guides/account-personalization): Fija el idioma de emisión de facturas, la plantilla PDF y el color de acento de tu cuenta — y léelos desde el recurso Account. - [Webhooks de cuenta](https://docs.factuarea.com/es/guides/account-webhooks): Recibe en un solo endpoint los eventos de tu cuenta y de sus NIF, con la tabla de equivalencias frente a los webhooks de empresa. - [Cuentas y NIF](https://docs.factuarea.com/es/guides/accounts-and-nifs): Tu cuenta es el cliente: sus NIF, su equipo con roles owner, admin y member, los grants por NIF, el traspaso de NIF y cómo consultarla con GET /v1/me. - [Alcanzar un NIF por el segmento de empresa](https://docs.factuarea.com/es/guides/acting-on-behalf): Trabaja con cualquier NIF que alcanza tu credencial nombrándolo en el segmento de empresa de la ruta — los propios, los de un acceso cedido y los de cuentas gestionadas — con cómo resolver su id, las respuestas que obtienes y la cabecera X-Active-Profile retirada. - [Plazas de NIF adicional](https://docs.factuarea.com/es/guides/additional-nifs): Contrata plazas para los NIF adicionales de tu cuenta: compra y reducción, qué usa cada escritura, la regla del trial, el tope y las vistas previas. - [Importes y fechas](https://docs.factuarea.com/es/guides/amounts-and-dates): Cómo representa la API el dinero documental, precios y cantidades precisas de catálogo, fechas, timestamps y límites Europe/Madrid. - [Anular o rectificar](https://docs.factuarea.com/es/guides/annul-vs-correct): Cuatro operaciones parecen «deshacer una factura» y solo una es correcta en cada caso — eliminar, cancelar, anular y rectificar. Si eliges mal, pierdes un documento fiscal o presentas una declaración que no pretendías. - [API keys (autoservicio)](https://docs.factuarea.com/es/guides/api-keys): Emite, lista, acota, rota y revoca las API keys de tu cuenta desde la API v1 — quién puede emitirlas, los environments live/test, los scopes que puedes asignar y el techo de nivel por NIF. - [Autenticación](https://docs.factuarea.com/es/guides/authentication): API keys con prefijos fact_live_ / fact_test_, scopes granulares, los scopes privilegiados accounts:*, qué alcanza el consentimiento OAuth, rotación con periodo de gracia y lista de acceso por IP. - [Automatizaciones](https://docs.factuarea.com/es/guides/automations): El modelo cuándo, si y haz del motor de reglas — versiones, el ensayo que no materializa nada, el historial de ejecuciones y sus pasos, el relanzamiento, los límites del motor y las reglas de cartera de una cuenta. - [Importación masiva de cuentas gestionadas](https://docs.factuarea.com/es/guides/bulk-import): Previsualiza y aplica un CSV de clientes de una vez: columnas, modalidades, estados por fila, límites y qué hace una reimportación. - [Operaciones en lote](https://docs.factuarea.com/es/guides/bulk-operations): Contrato de éxito parcial para endpoints bulk — total, successful, failed y una lista failures por fila. - [Catálogo y precios](https://docs.factuarea.com/es/guides/catalog-overview): Organiza productos, variantes y tarifas, y entiende cómo llegan a tus documentos. - [Verificación censal AEAT](https://docs.factuarea.com/es/guides/census-verification): Contrasta el par razón social + NIF de tu empresa — y el de tus clientes — contra el censo de la AEAT antes de emitir facturas VeriFactu — estados deterministas, NIFs mágicos del sandbox y comportamiento fail-open. - [Claves acotadas a una parte de tu cuenta](https://docs.factuarea.com/es/guides/child-api-keys): Emite, acota, rota y revoca API keys que alcanzan solo algunos de los NIF de tu cuenta — scoped_company_ids, el techo de nivel por NIF y qué pasa cuando la persona que emitió una clave pierde acceso. - [Cartera de NIF](https://docs.factuarea.com/es/guides/companies): Da de alta, sigue y gestiona los NIF de tu cuenta por la API v1 — la plaza contratada que ocupa un NIF adicional, e