Skip to main content

Query status

The API exposes five read-only query endpoints, one per document type. All accept the identifier as UUID or external_ref and have no side effects (they don't count as retries or trigger MH operations).

EndpointQueries
GET /status/{id_or_ref}Invoices (01), CCF (03), Export (11), NC (05)
GET /credit-memo/status/{id_or_ref}NC-specific alias — returns extra metadata about the adjusted CCF
GET /suex/status/{id_or_ref}Excluded Subject (14)
GET /invalidate/status/{id_or_ref}Invalidation state for sale/CCF
GET /invalidate/suex/status/{id_or_ref}Invalidation state for SUEX

Main endpoint: /status/{id_or_ref}

The most used. Works for any sale document (including NC, though /credit-memo/status brings extra metadata for NCs).

Technical details

MethodGET
URLhttps://ocote.io/api/connect/status/{id_or_ref}
Query paramsinclude_dte (bool, default false)
AuthenticationHeader Authorization: Bearer odt_...

Query param include_dte

By default the response does not include the full signed DTE or the raw MH response — those fields can be several KB and most queries (polling, reconciliation) don't need them. Add them explicitly only when needed:

GET /api/connect/status/SALE-2026-0042?include_dte=1

With include_dte=1, the response includes two extra fields:

  • schema (object) — the full signed JSON of the DTE.
  • response (object) — raw MH response (stamp or rejection structure).

Example

curl
curl "https://ocote.io/api/connect/status/SALE-2026-0042" \
-H "Authorization: Bearer odt_xxx"
Node.js (axios)
const { data } = await axios.get(
'https://ocote.io/api/connect/status/SALE-2026-0042',
{ headers: { Authorization: `Bearer ${process.env.OCOTE_API_KEY}` } }
);
Python (requests)
r = requests.get(
"https://ocote.io/api/connect/status/SALE-2026-0042",
headers={"Authorization": f"Bearer {API_KEY}"},
)

Response

{
"document_id": "a1b2c3d4-1234-5678-9abc-def012345678",
"external_ref": "SALE-2026-0042",
"doc_type": "01",
"control_number": "DTE-01-M001P001-000000000000123",
"reception_stamp": "20260421154532...",

"success": true,
"posted": true,
"invalidated": false,

"customer_name": "Juan Pérez",
"created": "2026-04-21T10:42:00-06:00",
"posted_date": "2026-04-21T10:42:15-06:00",

"amount_taxable": 7.96,
"amount_vat": 1.04,
"amount_gross": 9.00,
"amount_retention": 0.00,
"amount_total": 9.00,

"amount": 9.00,
"amount_ret": 0.00,

"ticket_url": "https://ocote.io/api/connect/file/a1b2c3d4-.../...?type=ticket&key=odt_xxx",
"json_url": "https://ocote.io/api/connect/file/a1b2c3d4-.../...?type=json&key=odt_xxx",

"dte_success": true,
"contingency": false,
"rejected": false,
"dte_state": "",
"dte_message": "",
"observaciones": [],
"codigo_msg": ""
}

See Responses and states for full flag semantics.

Deprecated fields

amount and amount_ret are aliases of amount_total and amount_retention respectively. Kept for backward compatibility with clients already consuming the endpoint. New integrations should use the canonical names.

/credit-memo/status/{id_or_ref}

Dedicated to Credit Notes. The response includes references to the adjusted CCF:

{
"document_id": "63e82935-9d98-43db-b2b8-bc669364885c",
"external_ref": "NC-ENLACES-TEST-001",
"doc_type": "05",
"control_number": "DTE-05-M001P002-000000000000001",
"reception_stamp": "20260421145823...",

"success": true,
"posted": true,

"ccf_document_id": "a1b2c3d4-1234-5678-9abc-def012345678",
"ccf_external_ref": "CCF-ENLACES-TEST-001",
"ccf_control_number": "DTE-03-M001P002-000000000000008",
"ccf_adjusted_amount": 339.00,
"ccf_fully_adjusted": false,

"amount_taxable": 300.00,
"amount_vat": 39.00,
"amount_gross": 339.00,
"amount_retention": 0.00,
"amount_total": 339.00,

"dte_success": true,
"contingency": false,
"rejected": false
}

If you query a CCF or an invoice with /credit-memo/status/..., the API responds 404. The endpoint is NC-specific.

/suex/status/{id_or_ref}

Dedicated to Excluded Subject. The amount fields are different:

{
"document_id": "b2c3d4e5-...",
"external_ref": "SUEX-2026-0015",
"doc_type": "14",
"control_number": "DTE-14-M001P001-000000000000015",

"success": true,
"posted": true,
"invalidated": false,

"amount": 1500.00,
"amount_irs": 150.00,
"total_pay": 1350.00,

"suex_name": "Ana María González Rodríguez",
"created": "2026-04-21T10:42:15-06:00",
"posted_date": "2026-04-21T10:42:18-06:00",

"invoice_url": "https://ocote.io/api/v2/suex-history/b2c3d4e5-.../file?type=invoice",
"json_url": "https://ocote.io/api/v2/suex-history/b2c3d4e5-.../file?type=json",

"dte_success": true,
"contingency": false,
"rejected": false
}

See Excluded Subject (14) for detail on amount_irs (10% income-tax withholding) and total_pay (net to transfer to the subject).

Invalidation status endpoints

After invalidating a document, you can query the state of that specific operation (distinct from the document's general state).

/invalidate/status/{id_or_ref} (sales)

Returns whether the invalidation was successful, whether it generated an automatic NC, and the MH state of the invalidation.

curl "https://ocote.io/api/connect/invalidate/status/SALE-2026-0042" \
-H "Authorization: Bearer odt_xxx"

Relevant response fields:

FieldDescription
invalidatedtrue if the document was marked invalidated.
created_credit_memotrue if an automatic NC was generated (out-of-window CCF).
credit_memo_id, credit_memo_control_numberIDs of the generated NC.
dte_successMH accepted the invalidation.
contingency, rejectedMH state of the invalidation.

/invalidate/suex/status/{id_or_ref} (SUEX)

Same structure, without the credit_memo_* block (SUEX does not use NC).

  • After issuing a document successfully, you don't need to query — the POST response already has everything.
  • For documents in contingency, hourly polling is enough. See Contingency > Responsible polling.
  • To reconcile documents in your DB against Ocote, iterate over your external_refs and query each — no batch endpoint.
  • Don't use /status as a replacement for your DB. Persist document_id/external_ref locally; the API is for spot queries, not your primary source of truth.

See also