Invalidate DTE
The API offers two invalidation endpoints, depending on the document type:
POST /invalidate/{id_or_ref}— for Invoice (01), CCF (03), Export (11), and Credit Note (05).POST /invalidate/suex/{id_or_ref}— dedicated for Excluded Subject (14).
They are separate routes because SUEX lives in a different model (PurchaseHeader) and requires dedicated endpoints.
MH invalidation windows
MH allows direct invalidation only within certain time windows:
| Type | Direct invalidation window | What happens out of window |
|---|---|---|
| Invoice (01) | 90 business days from issuance | MH rejects the invalidation. |
| CCF (03) | Rest of issuance day + 24 h of next day | The API automatically generates a Credit Note to cancel the CCF (available for 90 business days from CCF issuance). |
| Export (11) | See MH regulation | Contact Ocote. |
| Credit Note (05) | See MH regulation | Contact Ocote. |
| SUEX (14) | See MH regulation | Contact Ocote. |
If you call /invalidate/{ccf_id} and the CCF is outside the invalidation window, the API does not fail. It detects the situation, creates a Credit Note that adjusts the CCF in full, and returns created_credit_memo: true with the UUID and control number of the generated Credit Note. From your side the only action was a POST to /invalidate — the API handles the rest.
Invalidate Invoice, CCF, Export, or NC
Technical details
| Method | POST |
| URL | https://ocote.io/api/connect/invalidate/{id_or_ref} |
| Body | None. |
| Authentication | Header Authorization: Bearer odt_... |
The {id_or_ref} in the URL can be either the document UUID or your external_ref.
Request
No body required. Everything goes in the URL:
curl -X POST https://ocote.io/api/connect/invalidate/SALE-2026-0042 \
-H "Authorization: Bearer odt_xxx"
const { data } = await axios.post(
'https://ocote.io/api/connect/invalidate/SALE-2026-0042',
null,
{ headers: { Authorization: `Bearer ${process.env.OCOTE_API_KEY}` } }
);
r = requests.post(
f"https://ocote.io/api/connect/invalidate/SALE-2026-0042",
headers={"Authorization": f"Bearer {API_KEY}"},
)
Response
| Field | Type | Description |
|---|---|---|
success | bool | true if the operation was registered in Ocote (includes contingency). |
message | string | Descriptive message. |
document_id | string (UUID) | ID of the affected document. |
invalidated | bool | true if the API attempted invalidation. Combined with dte_success tells you if it was stamped. |
created_credit_memo | bool | true if an automatic Credit Note was generated (out-of-window CCF case). |
credit_memo_id | string | UUID of the generated Credit Note (empty if none). |
credit_memo_control_number | string | Correlative of the Credit Note (DTE-05-...). |
dte_success | bool | MH accepted the invalidation. |
contingency | bool | MH did not respond; the invalidation will be revalidated. |
rejected | bool | MH rejected the invalidation. |
dte_state, dte_message, observaciones, codigo_msg | — | Diagnostic info on rejection. See Responses and states. |
Response examples
CCF within window, direct invalidation successful:
{
"success": true,
"message": "Documento invalidado",
"document_id": "a1b2c3d4-...",
"invalidated": true,
"created_credit_memo": false,
"credit_memo_id": "",
"credit_memo_control_number": "",
"dte_success": true,
"contingency": false,
"rejected": false
}
CCF out of window, Credit Note automatically generated:
{
"success": true,
"message": "CCF fuera de ventana. Nota de Credito generada automaticamente.",
"document_id": "a1b2c3d4-...",
"invalidated": true,
"created_credit_memo": true,
"credit_memo_id": "b2c3d4e5-...",
"credit_memo_control_number": "DTE-05-M001P002-000000000000007",
"dte_success": true,
"contingency": false,
"rejected": false
}
Already invalidated (idempotency):
{
"success": true,
"message": "Documento ya invalidado",
"document_id": "a1b2c3d4-...",
"invalidated": true,
"created_credit_memo": false,
"dte_success": true,
"contingency": false,
"rejected": false
}
Calling /invalidate on an already-invalidated document is safe: returns current state with no side effects. See Retry and idempotency > Invalidation.
Invalidate Excluded Subject
Technical details
| Method | POST |
| URL | https://ocote.io/api/connect/invalidate/suex/{id_or_ref} |
| Body | None. |
| Authentication | Header Authorization: Bearer odt_... |
curl -X POST https://ocote.io/api/connect/invalidate/suex/SUEX-2026-0015 \
-H "Authorization: Bearer odt_xxx"
Same response structure but no Credit Note is ever generated — the NC mechanism is exclusive to CCFs. If the SUEX is out of window, MH rejects and you get rejected: true.
Validation errors
| HTTP | Message | Cause |
|---|---|---|
| 404 | Documento no encontrado | The id_or_ref does not exist in your company. |
| 400 | Documento no puede ser invalidado | Document is in an incompatible state (not processed, already NC, etc.). |
| 400 | MH-specific message | See observaciones in the response for detail. |
Messages are in Spanish.
See also
- Credit Note (05) — when you need explicit control over adjusted lines.
- Retry and idempotency — retry behavior on invalidations.
- Responses and states — full flag semantics.
- Query status — endpoint to verify state post-invalidation.