heruAPI
Retention certificates

Cancel a retention certificate

LiveServed by the v1 API in development with the same checks as production; production opens on the same contract. The capabilities from before v1 keep running in production at the path your account team gives you.

DELETE
/retention-certificates/{id}

Asks the SAT to cancel the certificate. Retention certificates need no acceptance from the receiver: the answer is 202 with status cancellation_requested, the SAT confirms within seconds and retention_certificate.cancelled fires with status cancelled.

To correct a certificate, issue the new one first with the old one in related_certificates (relationship 04), then cancel the old one with reason 01 and the new folio fiscal in replacement_uuid. heru checks that the replacement is stamped and relates this one. The cancelled certificate is not deleted: it keeps its files and its cancellation.

Needs the retention_certificates:cancel scope.

Authorization

oauth2 retention_certificates:cancel
headerAuthorizationBearer <token>

OAuth 2.0 client credentials. Exchange your client_id and client_secret at /oauth/token of the environment for a bearer token valid for one hour. The playground of every operation asks for your own client and keeps it in your browser tab only.

Scope: retention_certificates:cancel

Path parameters

id*string

The retention certificate id.

Match^rtc_[0-7][0-9a-hjkmnp-tv-z]{25}$

Query parameters

reason*string

SAT c_MotivoCancelacion: 01 issued with errors and replaced by a new certificate; 02 issued with errors, not replaced; 03 the operation did not happen.

Value in"01""02""03"
replacement_uuid?string

Folio fiscal of the new retention certificate that replaces this one. Required with reason 01, and not allowed with any other reason.

Formatuuid

Response body

The cancellation was sent to the SAT.

application/json
  1. response
id*string
Match^rtc_[0-7][0-9a-hjkmnp-tv-z]{25}$
external_id*string

Your own id, as you sent it.

status*string

stamped once the SAT accepted it; cancellation_requested while the SAT processes a cancellation; cancelled when the SAT confirmed it.

Value in"stamped""cancellation_requested""cancelled"
uuid*string

Folio fiscal the SAT assigned.

Formatuuid
verification_url*string

SAT page that verifies the certificate; tt is the total of the operation.

Formaturi
stamp*

The SAT stamp (TimbreFiscalDigital). Print it on your own representation of the CFDI.

issuer*
receiver*
place_of_issue*string

Postal code where it was issued.

period*

Months the withholdings cover.

retention_code*string
description?string|null
amounts*

Amounts of the operation the withholdings come from.

withheld_taxes*array<>
total_withheld*string

Sum of withheld_taxes.

Match^[0-9]+(\.[0-9]{1,6})?$
related_certificates*array<>

Certificates this one replaces. Empty when there are none.

platform?|

The complement, with retention_code 26. Null otherwise.

cancellation?|

Null until you request a cancellation.

metadata?
created_at*string
Formatdate-time
stamped_at*string
Formatdate-time
updated_at*string
Formatdate-time
curl -X DELETE 'https://api.dev.b2b.heru.app/v1/retention-certificates/rtc_01m4rdmjy8fr1tn1re492c0z4j?reason=02'
{  "id": "rtc_01m4wvyy8pf369z5gc411pzxbn",  "external_id": "RET-2026-000007",  "status": "cancellation_requested",  "uuid": "9BD7A27B-665F-45DB-8346-40375C48AC03",  "verification_url": "https://prodretencionverificacion.clouda.sat.gob.mx/?id=9BD7A27B-665F-45DB-8346-40375C48AC03&re=PDP190820LK6&rr=JIVR851120N53&tt=25000.00&fe=3gqwnA==",  "stamp": {    "sat_certificate_number": "00001000000509465028",    "issuer_certificate_number": "00001000009130864141",    "pac_rfc": "SPR190613I52",    "issuer_seal": "lN8/Yr05gy5RqVSI4pmbKtdAgkGgyDsszb7dB98eyjENpb2OlmY7eRdbFQvZ+hIfGyy5kql8Ijp4Wv1gXP5oQuKXJDlhlU5Rm+jrmolZrKQ286dzPJsfJnS0JtAbueV/lPi2o+D+k6I3IZvtmDyD/kv0tz0LuNJjAGqebKEE2W6tMBz1ildgYQpt2qqwPeK64u2tOIO5/whvv4jYKOnqInf8dqlGLRJx9BEEUo3kWJkdwEOk4y9ITIWtfThzFz0Zg1WNWycv3iOIjMXiG3Mn2ar5pxdtWzft9aInPmg4rZh9SBCxTQPPAUotUPMJqTlPxdxQjpi/Z4TdujNJ3gqwnA==",    "sat_seal": "f09KPM5c84xojlItPIBClhcz1bF8lzsRVyKWWnFuCwfgbkht6WxLINqQpsOHh+qVVQuqxTiVJfjwyjoGMuXe1C/el6xw7o+XJiQoN/zX7VUBpo0SA4eiMGUGEK0UhEDBYpZPCq7clyv28wCxR2x0E8j+dijjASCOSKqWRgarkTIzPaZVq9+GPx2ZtGPuN5L48ReymGcAX8A3ulj3bIW4BtjsuxFCiP3v+jxLjthKmU+8cg+T48x3BMD2hpynRgmdnUOs4h3g5ZOr18yNYY14Oi0O0uwiA7Rj0M2K9ibAxNMD5gyJQqTAYQPr/irE1WTPnuQotx7DqUFdX8T8pq0Bow==",    "original_chain": "||1.1|9BD7A27B-665F-45DB-8346-40375C48AC03|2026-10-16T19:03:07|SPR190613I52|lN8/Yr05gy5RqVSI4pmbKtdAgkGgyDsszb7dB98eyjENpb2OlmY7eRdbFQvZ+hIfGyy5kql8Ijp4Wv1gXP5oQuKXJDlhlU5Rm+jrmolZrKQ286dzPJsfJnS0JtAbueV/lPi2o+D+k6I3IZvtmDyD/kv0tz0LuNJjAGqebKEE2W6tMBz1ildgYQpt2qqwPeK64u2tOIO5/whvv4jYKOnqInf8dqlGLRJx9BEEUo3kWJkdwEOk4y9ITIWtfThzFz0Zg1WNWycv3iOIjMXiG3Mn2ar5pxdtWzft9aInPmg4rZh9SBCxTQPPAUotUPMJqTlPxdxQjpi/Z4TdujNJ3gqwnA==|00001000000509465028||"  },  "issuer": {    "rfc": "PDP190820LK6",    "name": "PLATAFORMA DEMO PAGOS",    "tax_regime": "601",    "postal_code": "11000"  },  "receiver": {    "rfc": "JIVR851120N53",    "name": "ROBERTO CARLOS JIMENEZ VARGAS",    "tax_regime": "606",    "postal_code": "64000",    "email": null  },  "place_of_issue": "11000",  "period": {    "start_month": "10",    "end_month": "10",    "year": "2026"  },  "retention_code": "05",  "description": "Retención de ISR e IVA por arrendamiento de local comercial",  "amounts": {    "total": "25000.00",    "taxable": "25000.00",    "exempt": "0.00"  },  "withheld_taxes": [    {      "tax": "ISR",      "base": "25000.00",      "rate": "0.10",      "amount": "2500.00",      "payment_type": "04"    },    {      "tax": "VAT",      "base": "25000.00",      "rate": "0.106667",      "amount": "2666.67",      "payment_type": "01"    }  ],  "total_withheld": "5166.67",  "related_certificates": [],  "platform": null,  "cancellation": {    "reason": "01",    "replacement_uuid": "82DCF3C3-2BFF-4DFA-BC55-0455D4FFCF86",    "requested_at": "2026-10-16T19:03:08Z",    "cancelled_at": null  },  "metadata": {},  "created_at": "2026-10-16T19:03:07Z",  "stamped_at": "2026-10-16T19:03:07Z",  "updated_at": "2026-10-16T19:03:08Z"}

Issue a retention certificatePOST

Issues the CFDI de retenciones e información de pagos: the certificate you give every month to the merchants and workers you withheld ISR and VAT from. **Who issues it.** Whoever withheld: your company, sealed with the CSD heru holds for it (see [Companies](/companies)), or `issuer.merchant_id` when a merchant withheld. heru never issues it in its own name. **Who receives it.** A worker or merchant you registered (`receiver.worker_id`, `receiver.merchant_id`), one of your companies, or any taxpayer by RFC, name, regime and postal code exactly as the SAT has them. **Platforms (retention_code 26).** Send one month in `period` and the services in `platform.services`. heru builds the complemento de servicios de plataformas tecnológicas and computes `amounts` and `withheld_taxes` with the SAT rules: the ISR rate of the service type and year, the VAT withheld on the VAT transferred, and cash services left out of both bases. Send them too if you want heru to check your own numbers. The [retention certificates guide](/guides/retention-certificates) walks through a merchant and a courier. **Checked before stamping.** Every SAT rule of the CFDI and the complement runs before the PAC sees it. A mistake answers `422` with the field and the value the SAT expects; nothing is stamped. **Synchronous.** heru stamps with the PAC before answering, usually in 2 to 5 seconds, and returns the certificate with its folio fiscal; `retention_certificate.stamped` follows. If the PAC or the SAT do not answer in time you get `503` and nothing is created: retry after `Retry-After` with the same `Idempotency-Key`. For a month of certificates, use a [batch](/guides/batches). **Files.** `GET /retention-certificates/{id}/download` returns a signed link to the XML or the PDF, valid for 15 minutes. Needs the `retention_certificates:write` scope.

List retention certificatesGET

Most recent first. For the monthly reconciliation, filter by `period` and page through with `cursor`; add `status=stamped` to leave out cancellations. Needs the `retention_certificates:read` scope.

© 2026 Kuarto Inc. (heru)heru.appQuestions about your integration? Contact your heru account team.