Platforms with workers
The weekly cycle of a delivery, ride-hailing or crowdsourcing platform that pays independent workers.
Most platforms run the same cycle every week or month. Every step below is one API call; batches do the same from a CSV file when you issue thousands of invoices at once.
Register the worker once
POST /workers returns enrollment.url, a signed link valid for 7 days. If it expires, POST /workers/{id}/enrollment creates a new one. The worker opens it, accepts the terms and the privacy notice and, if you use direct invoicing or CSD generation, uploads their e.firma. Nothing that acts on their SAT account happens without this consent. Planned
Validate before each payment
Two or three days before you pay, call POST /fiscal-validations with the worker's CURP. The result tells you whether the RFC is active, the tax regimes, and the exact name and postal code the SAT has on file. Add POST /social-security-validations if you also need the NSS. Live
Decide the withholding
This is your business rule. The ISR and VAT you withhold depend on the worker's regime and on whether they have an active RFC. heru gives you the inputs; the decision stays with you.
Issue the invoice and the retention certificate
After the last trip of the period, call POST /invoices with the worker in third_party.worker_id (heru invoices on their behalf) or in issuer.worker_id (they invoice with their own CSD), and, once a month, POST /retention-certificates with the worker in receiver.worker_id and the services of the month; the retention certificates guide covers the complement, the rates and the monthly batch. Use the name, postal code and regime from step 2: CFDI 4.0 rejects any receiver data that differs from the SAT's records. Building
curl -X POST https://api.dev.b2b.heru.app/v1/invoices \
-H "Authorization: Bearer $TOKEN" \
-H "Idempotency-Key: INV-2026-000213" \
-H "Content-Type: application/json" \
-d '{
"external_id": "INV-2026-000213",
"receiver": { "rfc": "PDE180514R21", "name": "PLATAFORMA DEMO", "tax_regime": "601", "postal_code": "11000" },
"items": [{ "description": "Servicio de entrega a domicilio", "quantity": 1, "unit_code": "E48",
"unit_price": "1077.59", "product_code": "78101800", "tax_object": "02" }],
"payment_form": "03",
"third_party": { "worker_id": "wrk_01m4ra8w0he5esnnsew0v9ffkv" }
}'You send only the worker_id: heru fills the worker's RFC, name, regime and postal code, and checks their consent before stamping.
Show them in your app
The response of POST /invoices and POST /retention-certificates already carries the stamped CFDI and its UUID. GET /invoices/{id}/download?format=pdf (or format=xml) gives you a link valid for 15 minutes that you can open in your app or send to the worker.
Close the month
GET /reports/retentions?period=2026-10 returns what you withheld from each worker during the month, for your month-end close. Planned
Validate a worker
curl -X POST https://api.b2b.heru.app/v1/fiscal-validations \
-H "Authorization: Bearer $TOKEN" \
-H "Idempotency-Key: FV-2026-004413" \
-H "Content-Type: application/json" \
-d '{"external_id": "FV-2026-004413", "curp": "HEGL900101HDFRRS06"}'When the data does not match
| Case | What heru returns | What we suggest |
|---|---|---|
| Name, postal code or regime differ from yours | The SAT values in result | Invoice with the SAT values and ask the worker to confirm them in your app. |
| CURP not found | completed with code: CURP_NOT_FOUND | Ask the worker to check it. Do not issue. |
| No RFC, or RFC suspended | completed, with result.rfc_valid or result.rfc_active set to false | Apply your withholding policy for workers without an active RFC. Direct invoicing is not possible. |
| The tax regime could not be determined with the SAT | completed, with result.regimes empty | Do not issue yet. Ask the worker to confirm their regime with the SAT, then validate again. |
| SAT unavailable | partially_completed with code: SAT_SOURCES_PENDING, then a second webhook | Wait for the follow-up. We retry automatically. |
| An invoice is rejected | 422 with code: SAT_REJECTED and the SAT rule in sat_code | Fix the data and resend with the same external_id. |
| The PAC or the SAT do not answer | 503 with code: STAMP_UNAVAILABLE; nothing is created | Retry after Retry-After with the same Idempotency-Key. |
Fiscal validations are not on the v1 API yet; until they open, your account team runs them for you.
Who issues the invoice
| You send | Who issues it | What you need from the worker |
|---|---|---|
issuer.worker_id | The worker, with their own CSD | Consent and a CSD. heru can generate the CSD from their e.firma. |
third_party.worker_id | heru, por cuenta de terceros | Consent, and third_party_invoicing.eligible set to true in the fiscal validation. |
| Retention certificate | You, as the platform that withholds | Only the validated fiscal data. |