Skip to main content
Mexico example. This walkthrough uses the Mexican CFDI flow. For another issuing country, start with shared fields and country rules.
Case: a Mexican customer paid MXN 1,160 by bank transfer for one hour of consulting. You need an income CFDI (I) with MXN 1,000 subtotal and MXN 160 IVA. Use a test key for your first run. Complete the customer recipe and save its CLIENT_ID. For stamping, the customer needs valid fiscal data and the issuing team needs its invoicing provider and CSD configured. Complete issuer setup first. A contact-only customer is enough to save a draft, but not to complete the fiscal flow. For a synthetic run, use the test fiscal customer.
Before creating a test draft, confirm the team’s notification routing with the account owner. send_email: false, ignore_emails: true and automation_type: "none" do not suppress every account notification workflow. Invoice creation can attempt an account marketing event even in test mode; these flags are not a guarantee of a notification-free run. Use an approved sandbox with known recipients. This is a source-reviewed behavior; the recipe tests did not verify marketing delivery.

1. Save the request as a file

This is a paid-in-full example: PUE describes the payment timing; 03 means bank transfer. Use the customer’s actual use, and the product and taxes appropriate to your sale.
Expected: HTTP 201, data.status: "draft", a draft ID, and livemode: false with a test key. Saving the draft has not issued a CFDI.

2. Preview and review

Expected: HTTP 200 and message: "Preview PDF generated". Inspect the returned recipient, items, currency, and taxes. The tested response contains a base64 PDF at data.pdf. Save it locally:
Open preview.pdf to review it. A preview is not a stamped invoice.
When updating a draft, send the complete intended draft body, including items. A notes-only PUT cleared the items in our staging test. Several omitted fields also receive defaults, so do not treat this operation as a partial PATCH. Read the draft back and compare it before stamping.

3. Issue the reviewed draft

Run this step only for the draft you intend to issue. Verify that the draft itself has livemode: false during testing: a test key alone does not change the stored draft’s mode.
Observed test result: HTTP 200, status: "valid", livemode: false, subtotal 1000, taxes 160, total 1160, and a UUID. The response did not contain data.id. Keep the UUID; fetching the issued invoice with the former draft ID returned 404.

4. Fetch the invoice and its files

Both returned 200 in the test flow. The files response contains a data array; entries have filename, type, and content. See the files contract for encoding and options. Keep file contents and any signed download URLs private. If stamping times out, reconcile the result before retrying. If you only need to discard an unissued draft, use Delete a draft; cancelling an issued CFDI is a different operation.