Get a download link
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.
Returns a signed link to the stamped certificate on download.heru.app, valid for 15 minutes. format=xml is the CFDI as the SAT stored it, the document with fiscal validity; format=pdf is a printable version with the SAT seal and the QR to verify it. The files are never at a public address: request a new link each time someone needs them.
Needs the retention_certificates:download scope.
oauth2 retention_certificates:downloadAuthorizationBearer <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:download
id*stringThe retention certificate id.
^rtc_[0-7][0-9a-hjkmnp-tv-z]{25}$format*stringxml or pdf.
"xml""pdf"The link to the file.
application/json- response
url*stringSigned link to the file on download.heru.app. It works for anyone who has it until expires_at, so you can hand it to the worker or the customer. Request a new one after it expires.
uriexpires_at*stringWhen the link stops working. Each operation says how long its links last: 15 minutes for invoices, retention certificates and signed documents, 24 hours for IMSS documents.
date-timecontent_type*string"application/pdf""application/xml"filename*stringSuggested file name, e.g. the folio fiscal and the extension.
curl -X GET 'https://api.dev.b2b.heru.app/v1/retention-certificates/rtc_01m4rdmjy8fr1tn1re492c0z4j/download?format=pdf'{ "url": "https://download.heru.app/retention-certificates/rtc_01m4rdmjy8fr1tn1re492c0z4j/5829F7E9-4996-450C-BE13-9EE83FD56065.pdf?Expires=1791818348&KeyName=b2b-files&Signature=Hq3sY8pLmN2vKx9wQ7tB4cR6zA1d", "expires_at": "2026-10-12T15:19:08.000Z", "content_type": "application/pdf", "filename": "5829F7E9-4996-450C-BE13-9EE83FD56065.pdf"}Get a retention certificateGET
Returns the certificate with its status, the withheld taxes, the complement and the folio fiscal. Needs the `retention_certificates:read` scope.
Upload a batchPOST
For high volumes, up to 100 million rows per file. Every row is checked for format and catalogs while the batch validates, so `errors` lists what to fix before anything is stamped. The receiver is not verified against the SAT: the file is expected to contain data already checked with fiscal validations, and a document the stamping authority refuses ends `failed` in the report with its reason. Each party is identified by its RFC or its heru id, and with neither the row is invalid. Create the batch with its `type` and, optionally, `defaults` for the columns you would repeat on every row; PUT the CSV, plain or gzip, to `upload_url` within 24 hours; wait for `ready` and process it with `POST /batches/{id}/process`. Each type has its own columns, listed in the [batches guide](/guides/batches). The same documents can go through the JSON endpoints one by one. A batch lives 20 days at most from this call: one still unfinished at that point is cancelled as `POST /batches/{id}/cancel` would. Needs the `batches:write` scope, plus the scope that creating each document needs one by one: `invoices:write` or `retention_certificates:write`.