Factuarea API
Conceptes clau

Registrar pagaments

Registra pagaments parcials contra factures i factures de compra, i consulta el saldo en curs des del ledger.

Les factures i les factures de compra mantenen un ledger de pagaments: una llista de pagaments individuals, cadascun amb el seu propi import, data i mètode. Registra els pagaments d'un en un a mesura que entra els diners — l'API recalcula els imports cobrat i pendent després de cada entrada i passa el document a paid quan el saldo arriba a zero.

No existeix un estat «parcialment pagada» a part. L'avanç del cobrament es llegeix a partir de dos camps derivats, només de presentació, a la factura: paid_amount (suma del ledger) i pending_amount (total − paid_amount). Un document amb pending_amount > 0 continua pending; aquell el pending_amount del qual arriba a 0 passa a paid.

Registrar un pagament de venda

POST /v1/invoices/{id}/payments afegeix un pagament a una factura de venda. El body és petit:

CampTipusRequeritNotes
amountnumberMés gran que 0. No pot superar pending_amount.
paid_onstring (YYYY-MM-DD)La data en què es va rebre els diners.
payment_methodstring (enum)Un dels valors del catàleg (vegeu a sota).
referencestringNoLa teva pròpia referència (p. ex. un número de transferència).
notesstringNoNota interna lliure.

payment_method és un enum tancat de set valors: bank_transfer, direct_debit, cash, credit_card, check, paypal, other. Obtén el catàleg amb etiquetes des de GET /v1/payment-methods en lloc de fixar els valors a mà.

La resposta és 201 Created amb el pagament acabat de crear sota data:

{
  "data": {
    "id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a0b",
    "object": "payment",
    "invoice_id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a01",
    "amount": 500.00,
    "payment_date": "2026-05-20",
    "payment_method": "bank_transfer",
    "payment_method_text": "Transferencia bancaria",
    "reference": "TRF-2026-0042",
    "notes": null,
    "created_at": "2026-05-20T10:30:00Z",
    "updated_at": "2026-05-20T10:30:00Z"
  }
}
import os, requests

resp = requests.post(
    'https://api.factuarea.com/v1/invoices/01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a01/payments',
    json={
        'amount': 500.00,
        'paid_on': '2026-05-20',
        'payment_method': 'bank_transfer',
        'reference': 'TRF-2026-0042',
    },
    headers={'Authorization': f"Bearer {os.environ['FACTUAREA_API_KEY']}"},
)
resp.raise_for_status()
payment = resp.json()['data']
print(payment['id'], payment['amount'])
const res = await fetch(
  'https://api.factuarea.com/v1/invoices/01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a01/payments',
  {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.FACTUAREA_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      amount: 500.0,
      paid_on: '2026-05-20',
      payment_method: 'bank_transfer',
      reference: 'TRF-2026-0042',
    }),
  },
);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const { data } = await res.json();
console.log(data.id, data.amount);
curl -s -X POST \
  https://api.factuarea.com/v1/invoices/01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a01/payments \
  -H "Authorization: Bearer $FACTUAREA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 500.00,
    "paid_on": "2026-05-20",
    "payment_method": "bank_transfer",
    "reference": "TRF-2026-0042"
  }' | jq '.data'

Pagaments parcials i saldo

El saldo en curs no viu a l'objecte del pagament — viu a la factura. Després de registrar un o diversos pagaments, llegeix la factura (GET /v1/invoices/{id}) per veure com està:

{
  "data": {
    "id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a01",
    "object": "invoice",
    "status": "pending",
    "total": 1210.00,
    "paid_amount": 500.00,
    "pending_amount": 710.00,
    "payments": {
      "detail": [
        {
          "id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a0b",
          "object": "payment",
          "invoice_id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a01",
          "amount": 500.00,
          "payment_date": "2026-05-20",
          "payment_method": "bank_transfer",
          "payment_method_text": "Transferencia bancaria",
          "reference": "TRF-2026-0042",
          "notes": null,
          "created_at": "2026-05-20T10:30:00Z",
          "updated_at": "2026-05-20T10:30:00Z"
        }
      ],
      "total": 500.00,
      "pending": 710.00
    }
  }
}
  • paid_amount / pending_amount — els totals cobrat i pendent. Sempre presents, calculats a partir del ledger.
  • payments.total / payments.pending — les mateixes dues xifres, reflectides dins de l'objecte payments. Sempre presents.
  • payments.detail — l'array de pagaments individuals. Es materialitza només a l'endpoint de detall (GET /v1/invoices/{id}); als endpoints de llistat arriba com a [] (mentre total i pending continuen poblats) perquè els llistats siguin lleugers. Fes servir el sub-recurs per obtenir el detall per separat.

Quan l'últim pagament tanca el saldo (pending_amount arriba a 0), la factura passa a paid.

Un pagament l'amount del qual supera pending_amount es rebutja amb 422 i subcode: "payment_exceeds_pending_amount" (param: "amount"). Un pagament exactament igual a l'import pendent és vàlid i salda la factura. Consulta Errors.

Llistar pagaments

GET /v1/invoices/{id}/payments retorna el ledger complet d'una factura, del més recent al més antic. Una factura sense pagaments retorna { "data": [] }, mai un 404.

{
  "data": [
    {
      "id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a0b",
      "object": "payment",
      "invoice_id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a01",
      "amount": 500.00,
      "payment_date": "2026-05-20",
      "payment_method": "bank_transfer",
      "payment_method_text": "Transferencia bancaria",
      "reference": "TRF-2026-0042",
      "notes": null,
      "created_at": "2026-05-20T10:30:00Z",
      "updated_at": "2026-05-20T10:30:00Z"
    }
  ]
}

Pagaments de factura de compra

Les factures de compra mantenen el seu propi ledger (total_retention, la retenció IRPF agregada, viu al recurs de la factura de compra). El contracte és asimètric respecte al de venda — llegeix-lo amb atenció abans de reutilitzar codi:

  • POST /v1/purchase_invoices/{id}/payments retorna 201 amb el pagament creat sota data (objecte purchase_invoice_payment), no la factura completa.
  • GET /v1/purchase_invoices/{id}/payments retorna { "data": [...] }, del més recent al més antic.
  • El body afegeix un bank_account_id opcional (enter), i aquí payment_method és un string lliure (màx. 30 caràcters), no l'enum tancat que es fa servir al costat de venda.
CampTipusRequeritNotes
amountnumberMés gran que 0. No pot superar l'import pendent.
paid_onstring (YYYY-MM-DD)Entre la data d'emissió i avui.
payment_methodstringText lliure, màx. 30 caràcters.
bank_account_idintegerNoCompte bancari des del qual es va fer el pagament.
referencestringNoLa teva pròpia referència.
notesstringNoNota interna lliure.
{
  "data": {
    "id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a0c",
    "object": "purchase_invoice_payment",
    "amount": 423.50,
    "paid_on": "2026-05-21",
    "payment_method": "transferencia",
    "bank_account_id": 12,
    "reference": "TRF-2026-0099",
    "notes": null,
    "created_at": "2026-05-21T09:00:00Z"
  }
}
import os, requests

resp = requests.post(
    'https://api.factuarea.com/v1/purchase_invoices/01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a05/payments',
    json={
        'amount': 423.50,
        'paid_on': '2026-05-21',
        'payment_method': 'transferencia',
        'bank_account_id': 12,
    },
    headers={'Authorization': f"Bearer {os.environ['FACTUAREA_API_KEY']}"},
)
resp.raise_for_status()
print(resp.json()['data']['id'])
const res = await fetch(
  'https://api.factuarea.com/v1/purchase_invoices/01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a05/payments',
  {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.FACTUAREA_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      amount: 423.5,
      paid_on: '2026-05-21',
      payment_method: 'transferencia',
      bank_account_id: 12,
    }),
  },
);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const { data } = await res.json();
console.log(data.id);
curl -s -X POST \
  https://api.factuarea.com/v1/purchase_invoices/01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a05/payments \
  -H "Authorization: Bearer $FACTUAREA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 423.50,
    "paid_on": "2026-05-21",
    "payment_method": "transferencia",
    "bank_account_id": 12
  }' | jq '.data'

Les regles de pagament de la factura de compra (BR-PUR-019) s'apliquen com a 422: un import per sobre del saldo pendent (subcode: "payment_exceeds_pending_amount"), una data fora de data_emissió … avui (subcode: "invalid_payment_date"), o un pagament sobre una factura cancel·lada (subcode: "purchase_invoice_not_payable").

Mètodes de pagament

GET /v1/payment-methods retorna el catàleg tancat que dona suport al camp payment_method de venda, cadascun amb un value i una etiqueta llegible (en castellà). És un catàleg d'enum global — no específic d'empresa.

{
  "data": [
    { "value": "bank_transfer", "label": "Transferencia bancaria" },
    { "value": "direct_debit",  "label": "Domiciliación bancaria" },
    { "value": "cash",          "label": "Efectivo" },
    { "value": "credit_card",   "label": "Tarjeta de crédito" },
    { "value": "check",         "label": "Cheque" },
    { "value": "paypal",        "label": "PayPal" },
    { "value": "other",         "label": "Otro" }
  ]
}

Llegeix-lo un cop en arrencar i mostra les etiquetes a la teva interfície; retorna el value a payment_method.

Errors

  • 422 payment_exceeds_pending_amount — l'import és més gran que el saldo pendent (param: "amount"). És una violació de regla de negoci, així que és 422, mai 409.
  • 409 en un POST de pagament es reserva per a l'embolcall estàndard d'idempotència / conflicte (un Idempotency-Key reutilitzat amb un body diferent, o un conflicte de concurrència) — no per a les dades del pagament en si.

Consulta Errors per a l'embolcall complet i el catàleg de codis.

En aquesta pàgina