Invoices

Create a credit note draft

Create a rectificative invoice (credit note) as a draft, by differences (TipoRectificativa = I), for the full amount of an existing invoice.

The endpoint never issues. The draft carries no fiscal number, no hash and no VeriFactu submission: those happen when a person issues it in the app. A previous version created the document with sent status — that behaviour is gone.

Requirements:

  • Plan pro or above. Otherwise 403 PLAN_UPGRADE_REQUIRED.
  • An Idempotency-Key header. Otherwise 400 IDEMPOTENCY_KEY_REQUIRED.
  • The original invoice must not be draft, cancelled, or already fully credited.

Errors carry a stable machine-readable code alongside error.

post/v1/invoices/{invoiceId}/credit-note

Request

  • Base URL: https://api.frihet.io
  • URL: https://api.frihet.io/v1/invoices/{invoiceId}/credit-note
  • Auth: API key in header X-API-Key

Path parameters

invoiceIdstring required

Invoice unique identifier

Headers

Idempotency-Keystring required
Example:550e8400-e29b-41d4-a716-446655440000

Unique key identifying this credit-note operation. REQUIRED here (unlike other POST endpoints, where it is optional): a credit note is a fiscal document, so a retry must replay rather than create a second one.

The key is reserved against the operation — method, path AND request body — before the handler runs, and the draft plus the stored response are written in a single transaction. Two concurrent calls with the same key therefore produce exactly one draft.

A retry receives the stored 201 with the same id and the header X-Idempotent-Replayed: true. It is not downgraded to 200. The same key sent with a DIFFERENT body is a different operation and is refused with 409 IDEMPOTENCY_KEY_REUSED; the same key on a different endpoint is refused the same way, without executing.

Request body

reason'refund' | 'discount' | 'error' | 'cancellation' | 'other' required

Reason for the credit note. Maps to the R-type (R1 for error, R4 otherwise).

reasonDescriptionstring

Optional free-text description of the reason

fullCreditboolean

Only true (or omitted) is supported: a full credit by differences. Sending false returns 400 PARTIAL_CREDIT_NOT_IMPLEMENTED — partial corrections need the corrected lines, which this endpoint does not accept. Create those in the app.

issueDatestring date

Issue date for the credit note. Defaults to today.

Example request

{
  "reason": "error",
  "reasonDescription": "Incorrect unit price on line 2",
  "fullCredit": true,
  "issueDate": "2026-04-07"
}

Response

Credit note draft created — and the status a REPLAY returns too. A retry with the same Idempotency-Key receives this same 201, the same id and the same body, plus X-Idempotent-Replayed: true; no second document is written. (Earlier versions replayed as 200.)

Example response

{
  "data": {
    "success": true,
    "creditNote": {
      "id": "cn_abc123",
      "documentNumber": "CN-FAC-2026-0042",
      "originalInvoiceId": "abc123def456",
      "reason": "error",
      "fullCredit": true,
      "status": "draft",
      "rectificationMethod": "I",
      "totalCredited": 544.5
    }
  }
}

Changes

No recorded changes to this operation across all 1 revision of this API.