> ## Documentation Index
> Fetch the complete documentation index at: https://docs.newinvoice.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Going live

> Everything up to now ran in test mode. To stamp CFDIs that are real at the SAT you switch your keys from test to live and register real fiscal material.

Everything up to now ran in **test mode**. To stamp CFDIs that are real at the SAT you switch your
keys from test to live and register real fiscal material. This is the checklist and the gotchas.

## Test and live are separate worlds

Test and live are **fully isolated** — separate data, separate resources, and separate keys.
`sk_test_` keys stamp on the PAC's production host flagged `prueba=true`, which is not reported to
the SAT; `sk_live_` keys route to live stamping at the SAT. A test key never sees live data and
vice-versa, but not every operation is sandboxed: see
[what is and isn't sandboxed](https://docs.newinvoice.dev/guides/testing.md#what-is-and-isnt-sandboxed). Do the whole dance in test
first, then switch to your `sk_live_` keys.

## What you pay for

Live stamps count against your plan. Live downloads with a SAT password also need a subscription,
and cost **$0.696 MXN per XML delivered** plus **$114.84 MXN per active RFC per month** (less from the 10th RFC on Growth and
Scale), IVA included. See [the pricing table and an example](https://docs.newinvoice.dev/guides/massive-download.md#pricing). Test mode is free.

## 1. Register live CSDs

* In **live mode** the API rejects an expired or not-yet-valid CSD (422 `fiscal_profile.csd_expired`)
  — upload a current CSD (Certificado de Sello Digital) issued to the emitter's RFC. (Test mode
  tolerates expired/test CSDs; live mode does not.)
* The CSD is used to compute the *sello* **locally**; the private key never leaves this server and
  never reaches the PAC.
* You also need the taxpayer's **FIEL (e.firma)** — it signs the carta manifiesto that authorizes
  stamping (step 2 below), and the same FIEL is reused for descarga masiva. You can attach it here
  at registration or supply it inline when you sign the manifiesto.

## 2. Sign the carta manifiesto (per taxpayer)

Every new live profile is created **on hold**: it comes back `status: "requires_action"` with a single
`sign_manifest` action under `next_actions` (`pending_actions` on retrieve/list), and it **cannot
stamp** until the manifiesto is signed. The SAT requires each taxpayer to authorize a PAC to
certify their CFDIs, and a **separate carta manifiesto must be signed per RFC** before that RFC's
CFDIs can be stamped. This API signs it for you — no browser portal needed. The manifiesto is
signed with the taxpayer's **FIEL (e.firma)**, not the CSD.

This gate is **live-only**, so test mode will not have exercised it. Attempting to stamp against an
on-hold live profile returns **409 `fiscal_profile.manifest_required`**.

**One call, uploading the FIEL files** (they are also stored on the profile for descarga masiva):

```bash theme={null}
curl -s -X POST https://api.newinvoice.dev/v1/fiscal_profiles/$FP_ID/manifest \
  -H "authorization: Bearer $API_KEY" \
  -F "email=legal@yourcompany.mx" \
  -F "password=$FIEL_PASS" \
  -F "cer=@fiel.cer" \
  -F "key=@fiel.key"
```

(Prefer JSON? POST `{ "fiel": { "cer_base64", "key_base64", "password" }, "email" }` as
`application/json`.) If the profile already has a stored FIEL, omit it and just POST
`{ "email": "..." }` (or `-F "email=..."`). On success the response is a `manifest` object
(`status: "signed"`, `signed_at`, the signed `xml_base64` + `pdf_base64`), the profile's
`manifest_status` moves `pending_signature → signed` (so the profile flips to `status: "active"`
and its `pending_actions` empty out), and a `fiscal_profile.manifest_signed` webhook fires. An
"already signed" result is treated as idempotent success. Signing is once per profile — every stamp
call re-checks it. `email` receives the signed XML + PDF; it
falls back to the `MANIFEST_EMAIL` env default when omitted.

Notes:

* Prefer a **current, non-expired FIEL** — an expired e.firma is rejected.
* For descarga masiva there is no separate manifiesto — uploading the FIEL is itself the
  authorization.

## 3. Switch to live keys

There is nothing to configure on your side — the live PAC is already wired. The moment you send an
`sk_live_` key, that traffic is routed to live stamping at the SAT; test keys keep stamping with
`prueba=true`. Point your production integration at your `sk_live_` key and keep the `sk_test_` key
for staging.

## 4. Verify before you cut over

* `GET /v1/balance` returns your real remaining stamps.
* Stamp a known-good invoice for a real emitter/receptor and confirm the UUID resolves at the SAT
  (`POST /v1/validations` enriches with live SAT status).
* Confirm your webhook endpoints are **https** and every POST carries an `Idempotency-Key`.

## Descarga masiva at go-live

Descarga masiva has **no sandbox** — it only runs in production against a live FIEL stored on the
profile. Design around the SAT limits before you rely on it: only **2 identical lifetime requests**,
a **200,000 XML** cap per request, and package URLs that **expire in \~5 minutes**. See
[`massive-download.md`](https://docs.newinvoice.dev/guides/massive-download).

## Failure modes to expect (and how the API surfaces them)

* **Auth (code 1)** — non-retryable; fix creds, do not loop (repeated failures lock the account). → 401/403.
* **Contract expired / no transactions (code 2)** — renew stamping balance. → mapped `pac.contract_invalid`.
* **Certificate problems (30x)** — revoked/expired/mismatched CSD; re-register. → non-retryable.
* **Duplicate (307)** — not an error; resolved as a success-replay of the prior stamp.
* **Maintenance (5)** — a retryable `502`; retry with backoff.
* **Outcome unknown (timeout, network failure, internal error 4)** — `422 pac.stamp_outcome_unknown`. The CFDI may exist, so do not create it again: recover with `POST /v1/invoices/:id/stamp`.

Full mapping: [`../errors.md`](https://docs.newinvoice.dev/concepts/errors).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.