Payables
2 operations under /v1/payables (POST GET): parameters, status codes, refusal bodies, and the same request in curl, HTTP, Python and TypeScript.
Base URL: https://api.codespar.dev
Every operation below requires a Bearer token. See Authentication.
POST /v1/payables
https://api.codespar.dev/v1/payablesCreate a payable from a partner's record or a person's form
A payable is an obligation to pay somebody. This endpoint takes one as structured data: attribution.channel is structured for a partner system's record and manual for a form a person filled in. Both go through the same schema and the same deterministic checks, so the same payable sent through either channel ends in the same status with the same validation. upload is refused, because this endpoint takes no file yet.
Every field carries its provenance in from. Amounts are integer centavos (*_minor). rail_quote is refused by name: the amount and the payee of a payment come from the rail, never from a request. attribution.credential_id is set to the API key the request authenticated with; a different value is refused.
Every payable this endpoint creates is NEEDS_REVIEW for now. The amount, payee and due-date checks (amount_matches_rail, beneficiary_document_matches_supplier, due_date_state, and pix_key_owner_matches_supplier when the payable carries a Pix BR Code) always block READY, because the amount and the payee of a payment come from the payment rail, and the rail consult is not wired to this endpoint yet. They appear in review.review_by with cause required_not_implemented. No check can be left without an answer in this release, so VALIDATING is not returned either.
Status. Two fields answer two questions. review.validation_status is what the checks alone say: REJECTED (a check that rejects failed), NEEDS_REVIEW (a check failed, or a required check has no answer it can have), VALIDATING (a required, implemented check did not answer and will be retried) or VALIDATED (every required check passed). status is what the payable may do: READY only from VALIDATED with no review trigger open, and NEEDS_REVIEW when a trigger is open. The trigger this API evaluates is new_supplier: this project has no executed payable for the supplier's document, or the payable names no supplier document. It is evaluated per project, never across projects.
Why things are in review. review.review_by lists each check that sends the payable to a person and its cause: check_failed, retries_exhausted or required_not_implemented. review.review_triggers lists the open triggers. review.not_covered lists checks that did not run and do not block READY in this release (supplier_registry, bank_details_changed).
What fails a check. A carrier that fails its own check digits (carrier_check_digits) or a duplicate (duplicate_document) is REJECTED and not stored. A document number with wrong check digits, an NF-e key that disagrees with the printed fields, or totals that do not add up (arithmetic, one centavo of tolerance per comparison) is check_failed. The total is composed the way an NF-e composes vNF: subtotal_minor minus discount_minor and tax_relief_deducted_minor, plus taxes_added_minor, freight_minor, insurance_minor and other_charges_minor. taxes_included_minor is informational and in no sum.
Duplicates. A payable is a duplicate when another payable of the SAME project that is open or already paid shares a duplicity axis with it: document_hash, the boleto (a 47- or 48-digit linha digitável and the 44-digit barcode it expands from are the same boleto), the Pix txid, the NF-e access key, or the supplier document together with invoice number and série. The answer is 409 payable_duplicate and nothing is stored; details.existing_payable_id names the payable that holds the axis. A payable in another project never collides and is never named.
Idempotency. Send an Idempotency-Key header to make a retry safe. The same key with the same body answers 200 with idempotent_replay: true and the payable as it is now, never a duplicate. The same key with a different body answers 409 idempotency_key_conflict. Without a key, a retry of a create that succeeded answers payable_duplicate naming the payable it created.
Scope: payables:write.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
attribution | object | yes | — |
carriers | object | no | — |
doc_type | "invoice" | "danfe_nfe" | "boleto" | "unknown" | yes | — |
document_hash | string | no | — |
due_date | object | no | — |
extraction | object | no | — |
invoice_number | object | no | — |
issue_date | object | no | — |
items | array of object | no | — |
rail_quote | — | no | — |
recipient | object | no | — |
schema_version | "payable.v1" | yes | — |
serie | object | no | — |
supplier | object | yes | — |
totals | object | yes | — |
Responses
| Status | Body | Description |
|---|---|---|
200 | object | OK |
201 | object | OK |
400 | object | The body did not match the schema, carried rail_quote, or the Idempotency-Key header is empty or longer than 255 characters. details.issues names paths and codes, never the values sent. |
409 | object | payable_duplicate: the payable is REJECTED as a duplicate and was not stored. details.axes names the axis, details.existing_payable_id the payable of this project that holds it, and details.validation the verdict. idempotency_key_conflict: the key was used with a different body. |
422 | object | payable_carrier_malformed: a carrier failed its own check digits, so the payable is REJECTED and was not stored; details.carriers names the carrier and the failure. payable_no_duplicate_key: the payable carries no duplicity axis. payable_channel_unsupported: upload was sent. payable_attribution_mismatch: attribution.credential_id names another API key. |
503 | object | The key that protects supplier documents could not be read. Nothing was stored; retry later with the same Idempotency-Key. |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
attribution | object | yes | — |
carriers | object | no | — |
created_at | string | yes | ISO 8601 instant the payable was created. |
doc_type | "invoice" | "danfe_nfe" | "boleto" | "unknown" | yes | — |
document_hash | string | no | — |
due_date | object | no | — |
extraction | object | no | — |
idempotent_replay | boolean | yes | True when this answer replays an earlier call made with the same Idempotency-Key. |
invoice_number | object | no | — |
issue_date | object | no | — |
items | array of object | no | — |
payable_id | string | yes | — |
rail_quote | object | no | — |
recipient | object | no | — |
review | object | yes | — |
schema_version | "payable.v1" | yes | — |
serie | object | no | — |
status | "RECEIVED" | "EXTRACTING" | "EXTRACTED" | "VALIDATING" | "VALIDATED" | "NEEDS_REVIEW" | "READY" | "APPROVED" | "EXECUTED" | "REJECTED" | "FAILED_EXTRACTION" | "EXPIRED" | yes | — |
supplier | object | yes | — |
totals | object | yes | — |
updated_at | string | yes | ISO 8601 instant of the last change to the payable. |
validation | object | yes | — |
curl -X POST https://api.codespar.dev/v1/payables \
-H "Authorization: Bearer $CODESPAR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"schema_version": "payable.v1",
"doc_type": "invoice",
"attribution": {
"channel": "upload",
"credential_id": "credential_0000000000000000",
"connection_id": "conn_0000000000000000",
"actor": "string"
},
"document_hash": "string",
"supplier": {
"document": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"name": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
}
},
"recipient": {
"document": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"name": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
}
},
"invoice_number": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"serie": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"issue_date": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"due_date": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"items": [
{
"description": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"quantity": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"unit_amount_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"total_amount_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
}
}
],
"totals": {
"subtotal_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"discount_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"tax_relief_deducted_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"freight_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"insurance_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"other_charges_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"taxes_added_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"taxes_included_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"grand_total_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"currency": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
}
},
"carriers": {
"boleto": "string",
"br_code": "string",
"nfe": "string"
},
"extraction": {
"model": "string",
"model_version": "string",
"input_tokens": 0,
"output_tokens": 0,
"reasoning_tokens": 0
}
}'POST /v1/payables HTTP/1.1
Host: api.codespar.dev
Authorization: Bearer $CODESPAR_API_KEY
Content-Type: application/json
{
"schema_version": "payable.v1",
"doc_type": "invoice",
"attribution": {
"channel": "upload",
"credential_id": "credential_0000000000000000",
"connection_id": "conn_0000000000000000",
"actor": "string"
},
"document_hash": "string",
"supplier": {
"document": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"name": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
}
},
"recipient": {
"document": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"name": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
}
},
"invoice_number": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"serie": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"issue_date": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"due_date": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"items": [
{
"description": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"quantity": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"unit_amount_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"total_amount_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
}
}
],
"totals": {
"subtotal_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"discount_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"tax_relief_deducted_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"freight_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"insurance_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"other_charges_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"taxes_added_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"taxes_included_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"grand_total_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"currency": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
}
},
"carriers": {
"boleto": "string",
"br_code": "string",
"nfe": "string"
},
"extraction": {
"model": "string",
"model_version": "string",
"input_tokens": 0,
"output_tokens": 0,
"reasoning_tokens": 0
}
}import os
import requests
res = requests.post(
"https://api.codespar.dev/v1/payables",
headers={"Authorization": f"Bearer {os.environ['CODESPAR_API_KEY']}"},
json={
"schema_version": "payable.v1",
"doc_type": "invoice",
"attribution": {
"channel": "upload",
"credential_id": "credential_0000000000000000",
"connection_id": "conn_0000000000000000",
"actor": "string"
},
"document_hash": "string",
"supplier": {
"document": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"name": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
}
},
"recipient": {
"document": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"name": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
}
},
"invoice_number": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"serie": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"issue_date": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"due_date": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"items": [
{
"description": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"quantity": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"unit_amount_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"total_amount_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
}
}
],
"totals": {
"subtotal_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"discount_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"tax_relief_deducted_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"freight_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"insurance_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"other_charges_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"taxes_added_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"taxes_included_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"grand_total_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"currency": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
}
},
"carriers": {
"boleto": "string",
"br_code": "string",
"nfe": "string"
},
"extraction": {
"model": "string",
"model_version": "string",
"input_tokens": 0,
"output_tokens": 0,
"reasoning_tokens": 0
}
},
)
res.raise_for_status()
data = res.json()const res = await fetch("https://api.codespar.dev/v1/payables", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.CODESPAR_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"schema_version": "payable.v1",
"doc_type": "invoice",
"attribution": {
"channel": "upload",
"credential_id": "credential_0000000000000000",
"connection_id": "conn_0000000000000000",
"actor": "string"
},
"document_hash": "string",
"supplier": {
"document": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"name": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
}
},
"recipient": {
"document": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"name": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
}
},
"invoice_number": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"serie": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"issue_date": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"due_date": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"items": [
{
"description": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"quantity": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"unit_amount_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"total_amount_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
}
}
],
"totals": {
"subtotal_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"discount_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"tax_relief_deducted_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"freight_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"insurance_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"other_charges_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"taxes_added_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"taxes_included_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"grand_total_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"currency": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
}
},
"carriers": {
"boleto": "string",
"br_code": "string",
"nfe": "string"
},
"extraction": {
"model": "string",
"model_version": "string",
"input_tokens": 0,
"output_tokens": 0,
"reasoning_tokens": 0
}
}),
});
const data = await res.json();const r = await cs.api.response("post", "/v1/payables", {
body: {
schema_version: "payable.v1",
doc_type: "invoice",
attribution: {
channel: "upload",
credential_id: "credential_0000000000000000",
connection_id: "conn_0000000000000000",
actor: "string"
},
document_hash: "string",
supplier: {
document: {
value: "string",
from: "parser_local",
evidence: {
page: 0,
excerpt: "string"
},
confidence: 0
},
name: {
value: "string",
from: "parser_local",
evidence: {
page: 0,
excerpt: "string"
},
confidence: 0
}
},
recipient: {
document: {
value: "string",
from: "parser_local",
evidence: {
page: 0,
excerpt: "string"
},
confidence: 0
},
name: {
value: "string",
from: "parser_local",
evidence: {
page: 0,
excerpt: "string"
},
confidence: 0
}
},
invoice_number: {
value: "string",
from: "parser_local",
evidence: {
page: 0,
excerpt: "string"
},
confidence: 0
},
serie: {
value: "string",
from: "parser_local",
evidence: {
page: 0,
excerpt: "string"
},
confidence: 0
},
issue_date: {
value: "string",
from: "parser_local",
evidence: {
page: 0,
excerpt: "string"
},
confidence: 0
},
due_date: {
value: "string",
from: "parser_local",
evidence: {
page: 0,
excerpt: "string"
},
confidence: 0
},
items: [
{
description: {
value: "string",
from: "parser_local",
evidence: {
page: 0,
excerpt: "string"
},
confidence: 0
},
quantity: {
value: 1000,
from: "parser_local",
evidence: {
page: 0,
excerpt: "string"
},
confidence: 0
},
unit_amount_minor: {
value: 1000,
from: "parser_local",
evidence: {
page: 0,
excerpt: "string"
},
confidence: 0
},
total_amount_minor: {
value: 1000,
from: "parser_local",
evidence: {
page: 0,
excerpt: "string"
},
confidence: 0
}
}
],
totals: {
subtotal_minor: {
value: 1000,
from: "parser_local",
evidence: {
page: 0,
excerpt: "string"
},
confidence: 0
},
discount_minor: {
value: 1000,
from: "parser_local",
evidence: {
page: 0,
excerpt: "string"
},
confidence: 0
},
tax_relief_deducted_minor: {
value: 1000,
from: "parser_local",
evidence: {
page: 0,
excerpt: "string"
},
confidence: 0
},
freight_minor: {
value: 1000,
from: "parser_local",
evidence: {
page: 0,
excerpt: "string"
},
confidence: 0
},
insurance_minor: {
value: 1000,
from: "parser_local",
evidence: {
page: 0,
excerpt: "string"
},
confidence: 0
},
other_charges_minor: {
value: 1000,
from: "parser_local",
evidence: {
page: 0,
excerpt: "string"
},
confidence: 0
},
taxes_added_minor: {
value: 1000,
from: "parser_local",
evidence: {
page: 0,
excerpt: "string"
},
confidence: 0
},
taxes_included_minor: {
value: 1000,
from: "parser_local",
evidence: {
page: 0,
excerpt: "string"
},
confidence: 0
},
grand_total_minor: {
value: 1000,
from: "parser_local",
evidence: {
page: 0,
excerpt: "string"
},
confidence: 0
},
currency: {
value: "string",
from: "parser_local",
evidence: {
page: 0,
excerpt: "string"
},
confidence: 0
}
},
carriers: {
boleto: "string",
br_code: "string",
nfe: "string"
},
extraction: {
model: "string",
model_version: "string",
input_tokens: 0,
output_tokens: 0,
reasoning_tokens: 0
}
}
});
// r.status is one of the documented statuses (200, 422),
// each with its own body shape in r.data; nothing here throws on 422.
if (r.ok) {
console.log(r.data);
}{
"schema_version": "payable.v1",
"doc_type": "invoice",
"attribution": {
"channel": "upload",
"credential_id": "credential_0000000000000000",
"connection_id": "conn_0000000000000000",
"actor": "string"
},
"document_hash": "string",
"supplier": {
"document": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"name": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
}
},
"recipient": {
"document": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"name": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
}
},
"invoice_number": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"serie": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"issue_date": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"due_date": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"items": [
{
"description": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"quantity": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"unit_amount_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"total_amount_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
}
}
],
"totals": {
"subtotal_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"discount_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"tax_relief_deducted_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"freight_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"insurance_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"other_charges_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"taxes_added_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"taxes_included_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"grand_total_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"currency": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
}
},
"carriers": {
"boleto": "string",
"br_code": "string",
"nfe": "string"
},
"extraction": {
"model": "string",
"model_version": "string",
"input_tokens": 0,
"output_tokens": 0,
"reasoning_tokens": 0
},
"payable_id": "payable_0000000000000000",
"status": "RECEIVED",
"rail_quote": {
"beneficiary": {
"value": "string",
"from": "trilho"
},
"beneficiary_document_masked": {
"value": "string",
"from": "trilho"
},
"final_beneficiary": {
"value": "string",
"from": "trilho"
},
"final_beneficiary_document_masked": {
"value": "string",
"from": "trilho"
},
"amount_minor": {
"value": 1000,
"from": "trilho"
},
"discount_minor": {
"value": 1000,
"from": "trilho"
},
"interest_minor": {
"value": 1000,
"from": "trilho"
},
"fine_minor": {
"value": 1000,
"from": "trilho"
},
"due_date": {
"value": "string",
"from": "trilho"
},
"quoted_at": "2026-01-15T12:00:00.000Z"
},
"validation": {
"carrier_check_digits": {
"outcome": "ok",
"detail": "string"
},
"document_check_digits": {
"outcome": "ok",
"detail": "string"
},
"nfe_key_consistency": {
"outcome": "ok",
"detail": "string"
},
"arithmetic": {
"outcome": "ok",
"detail": "string"
},
"duplicate_document": {
"outcome": "ok",
"detail": "string"
},
"amount_matches_rail": {
"outcome": "ok",
"detail": "string"
},
"beneficiary_document_matches_supplier": {
"outcome": "ok",
"detail": "string"
},
"due_date_state": {
"outcome": "ok",
"detail": "string"
},
"pix_key_owner_matches_supplier": {
"outcome": "ok",
"detail": "string"
},
"supplier_registry": {
"outcome": "ok",
"detail": "string"
},
"bank_details_changed": {
"outcome": "ok",
"detail": "string"
}
},
"review": {
"validation_status": "REJECTED",
"review_by": [
{
"code": "string",
"cause": "check_failed"
}
],
"rejected_by": [
"string"
],
"awaiting": [
"string"
],
"not_covered": [
"string"
],
"review_triggers": [
"string"
]
},
"created_at": "string",
"updated_at": "string",
"idempotent_replay": true
}GET /v1/payables/{payableId}
https://api.codespar.dev/v1/payables/{payableId}Read a payable
The payable, its status, the outcome of every check in validation, and why it has that status in review. Reading never re-runs a check or changes the status. Every payable this endpoint creates is NEEDS_REVIEW for now. The amount, payee and due-date checks (amount_matches_rail, beneficiary_document_matches_supplier, due_date_state, and pix_key_owner_matches_supplier when the payable carries a Pix BR Code) always block READY, because the amount and the payee of a payment come from the payment rail, and the rail consult is not wired to this endpoint yet. They appear in review.review_by with cause required_not_implemented. No check can be left without an answer in this release, so VALIDATING is not returned either.
Status. Two fields answer two questions. review.validation_status is what the checks alone say: REJECTED (a check that rejects failed), NEEDS_REVIEW (a check failed, or a required check has no answer it can have), VALIDATING (a required, implemented check did not answer and will be retried) or VALIDATED (every required check passed). status is what the payable may do: READY only from VALIDATED with no review trigger open, and NEEDS_REVIEW when a trigger is open. The trigger this API evaluates is new_supplier: this project has no executed payable for the supplier's document, or the payable names no supplier document. It is evaluated per project, never across projects.
Why things are in review. review.review_by lists each check that sends the payable to a person and its cause: check_failed, retries_exhausted or required_not_implemented. review.review_triggers lists the open triggers. review.not_covered lists checks that did not run and do not block READY in this release (supplier_registry, bank_details_changed).
A payable of another project, of another organization and an id that is not a payable id all answer the same 404.
Scope: payables:read.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
payableId | string | yes | pbl_ followed by 16 characters. |
Responses
| Status | Body | Description |
|---|---|---|
200 | object | OK |
404 | object | No payable with this id in this project. |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
attribution | object | yes | — |
carriers | object | no | — |
created_at | string | yes | ISO 8601 instant the payable was created. |
doc_type | "invoice" | "danfe_nfe" | "boleto" | "unknown" | yes | — |
document_hash | string | no | — |
due_date | object | no | — |
extraction | object | no | — |
invoice_number | object | no | — |
issue_date | object | no | — |
items | array of object | no | — |
payable_id | string | yes | — |
rail_quote | object | no | — |
recipient | object | no | — |
review | object | yes | — |
schema_version | "payable.v1" | yes | — |
serie | object | no | — |
status | "RECEIVED" | "EXTRACTING" | "EXTRACTED" | "VALIDATING" | "VALIDATED" | "NEEDS_REVIEW" | "READY" | "APPROVED" | "EXECUTED" | "REJECTED" | "FAILED_EXTRACTION" | "EXPIRED" | yes | — |
supplier | object | yes | — |
totals | object | yes | — |
updated_at | string | yes | ISO 8601 instant of the last change to the payable. |
validation | object | yes | — |
curl -X GET https://api.codespar.dev/v1/payables/{payableId} \
-H "Authorization: Bearer $CODESPAR_API_KEY"GET /v1/payables/{payableId} HTTP/1.1
Host: api.codespar.dev
Authorization: Bearer $CODESPAR_API_KEYimport os
import requests
res = requests.get(
"https://api.codespar.dev/v1/payables/{payableId}",
headers={"Authorization": f"Bearer {os.environ['CODESPAR_API_KEY']}"},
)
res.raise_for_status()
data = res.json()const res = await fetch("https://api.codespar.dev/v1/payables/{payableId}", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.CODESPAR_API_KEY}`,
},
});
const data = await res.json();const result = await cs.api.get("/v1/payables/{payableId}", {
path: {
payableId: "payable_0000000000000000"
}
});{
"schema_version": "payable.v1",
"doc_type": "invoice",
"attribution": {
"channel": "upload",
"credential_id": "credential_0000000000000000",
"connection_id": "conn_0000000000000000",
"actor": "string"
},
"document_hash": "string",
"supplier": {
"document": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"name": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
}
},
"recipient": {
"document": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"name": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
}
},
"invoice_number": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"serie": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"issue_date": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"due_date": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"items": [
{
"description": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"quantity": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"unit_amount_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"total_amount_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
}
}
],
"totals": {
"subtotal_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"discount_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"tax_relief_deducted_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"freight_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"insurance_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"other_charges_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"taxes_added_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"taxes_included_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"grand_total_minor": {
"value": 1000,
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
},
"currency": {
"value": "string",
"from": "parser_local",
"evidence": {
"page": 0,
"excerpt": "string"
},
"confidence": 0
}
},
"carriers": {
"boleto": "string",
"br_code": "string",
"nfe": "string"
},
"extraction": {
"model": "string",
"model_version": "string",
"input_tokens": 0,
"output_tokens": 0,
"reasoning_tokens": 0
},
"payable_id": "payable_0000000000000000",
"status": "RECEIVED",
"rail_quote": {
"beneficiary": {
"value": "string",
"from": "trilho"
},
"beneficiary_document_masked": {
"value": "string",
"from": "trilho"
},
"final_beneficiary": {
"value": "string",
"from": "trilho"
},
"final_beneficiary_document_masked": {
"value": "string",
"from": "trilho"
},
"amount_minor": {
"value": 1000,
"from": "trilho"
},
"discount_minor": {
"value": 1000,
"from": "trilho"
},
"interest_minor": {
"value": 1000,
"from": "trilho"
},
"fine_minor": {
"value": 1000,
"from": "trilho"
},
"due_date": {
"value": "string",
"from": "trilho"
},
"quoted_at": "2026-01-15T12:00:00.000Z"
},
"validation": {
"carrier_check_digits": {
"outcome": "ok",
"detail": "string"
},
"document_check_digits": {
"outcome": "ok",
"detail": "string"
},
"nfe_key_consistency": {
"outcome": "ok",
"detail": "string"
},
"arithmetic": {
"outcome": "ok",
"detail": "string"
},
"duplicate_document": {
"outcome": "ok",
"detail": "string"
},
"amount_matches_rail": {
"outcome": "ok",
"detail": "string"
},
"beneficiary_document_matches_supplier": {
"outcome": "ok",
"detail": "string"
},
"due_date_state": {
"outcome": "ok",
"detail": "string"
},
"pix_key_owner_matches_supplier": {
"outcome": "ok",
"detail": "string"
},
"supplier_registry": {
"outcome": "ok",
"detail": "string"
},
"bank_details_changed": {
"outcome": "ok",
"detail": "string"
}
},
"review": {
"validation_status": "REJECTED",
"review_by": [
{
"code": "string",
"cause": "check_failed"
}
],
"rejected_by": [
"string"
],
"awaiting": [
"string"
],
"not_covered": [
"string"
],
"review_triggers": [
"string"
]
},
"created_at": "string",
"updated_at": "string"
}Wallets
15 operations under /v1/wallets (GET POST DELETE): parameters, status codes, refusal bodies, and the same request in curl, HTTP, Python and TypeScript.
Consumer Payments
2 operations under /v1/consumer-payments (POST): parameters, status codes, refusal bodies, and the same request in curl, HTTP, Python and TypeScript.