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

# CFDI cancellation guide

> Cancel CFDI invoices and payment receipts in Mexico using the SAT Mexico app.

export const WorkflowDiagram = ({workflow}) => {
  const stateColors = {
    processing: "yellow",
    sent: "blue",
    received: "blue",
    registered: "green",
    completed: "green",
    error: "red"
  };
  const StateChip = ({state, label}) => <Badge size="sm" color={stateColors[state] || "gray"} icon="square-small" iconType="solid">
      {label.charAt(0).toUpperCase() + label.slice(1)}
    </Badge>;
  const providerIcons = {
    "silo.state": "https://silo.invopop.com/images/status.svg",
    "silo.close": "https://silo.invopop.com/images/check-badge.svg",
    "silo.if": "https://assets.invopop.com/apps/silo/if.svg",
    "silo.folder": "https://silo.invopop.com/images/folder.svg",
    "silo.modify": "https://silo.invopop.com/images/modify.svg",
    "silo.correct": "https://silo.invopop.com/images/replace.svg",
    "silo.sleep": "https://assets.invopop.com/icons/sleep.svg",
    silo: "https://assets.invopop.com/apps/silo/icon.svg",
    "sequence.enumerate": "https://sequence.invopop.com/images/enumerate.svg",
    "transform.job.create": "https://transform.invopop.com/images/jobs.svg",
    webhook: "https://webhook.invopop.com/icon.svg",
    lookup: "magnifying-glass",
    dropbox: "https://dropbox.invopop.com/icon.png",
    pdf: "https://pdf.invopop.com/file-pdf.svg",
    peppol: "https://assets.invopop.com/apps/peppol/icon.svg",
    ubl: "https://assets.invopop.com/apps/ubl/logo.svg",
    cii: "https://assets.invopop.com/apps/cii/logo.svg",
    "gov-co": "https://assets.invopop.com/flags/co.svg",
    "gov-dk": "https://assets.invopop.com/flags/dk.svg",
    "gov-fi": "https://assets.invopop.com/flags/fi.svg",
    "gov-fr": "https://assets.invopop.com/flags/fr.svg",
    "chorus-pro": "https://assets.invopop.com/apps/chroruspro/icon.svg",
    "gov-es": "https://assets.invopop.com/apps/gov-es/icon.svg",
    "gov-es.sii": "https://assets.invopop.com/apps/sii/icon.svg",
    "gov-es.ticketbai": "https://assets.invopop.com/apps/ticketbai/icon.svg",
    "gov-es.facturae": "https://assets.invopop.com/apps/facturae/icon.svg",
    verifactu: "https://assets.invopop.com/apps/verifactu/icon.svg",
    "gov-pl": "https://assets.invopop.com/apps/ksef/icon.svg",
    "gov-sa": "https://assets.invopop.com/apps/zatca/icon.svg",
    "gov-ar": "https://assets.invopop.com/apps/arca/icon.svg",
    "at-pt": "https://assets.invopop.com/apps/at-pt/icon.svg",
    "sat-mx": "https://assets.invopop.com/apps/sat-mexico/icon.svg",
    "sw-sapien": "https://assets.invopop.com/apps/sw-sapien/icon.svg",
    "sdi-it": "https://assets.invopop.com/apps/sdi-italy/icon.svg",
    "ticket-it": "https://assets.invopop.com/apps/agenzia-entrate/icon.svg",
    "nfe-br": "https://assets.invopop.com/apps/notas-fiscais-eletronicas-brazil/icon.svg",
    chargebee: "https://assets.invopop.com/apps/chargebee/icon.svg",
    stripe: "https://assets.invopop.com/apps/stripe/icon.svg",
    email: "https://assets.invopop.com/apps/email/icon.svg",
    cron: "https://assets.invopop.com/apps/cron/icon.svg",
    tables: "https://assets.invopop.com/apps/tables/icon.svg",
    ilyda: "https://assets.invopop.com/apps/ilyda/icon.svg",
    invoicexpress: "https://assets.invopop.com/apps/invoicexpress/icon.svg"
  };
  const iconFor = provider => {
    const parts = (provider || "").split(".");
    for (let i = parts.length; i > 0; i--) {
      const url = providerIcons[parts.slice(0, i).join(".")];
      if (url) return url;
    }
    return null;
  };
  const StepIcon = ({provider}) => {
    const url = iconFor(provider);
    return <span title={provider} className="flex h-7 w-7 shrink-0 items-center justify-center rounded-md border border-gray-950/10 bg-white dark:border-white/10 dark:bg-white/5">
        {url && url.startsWith("http") ? <img src={url} alt="" className="h-4 w-4" /> : null}
        {url && !url.startsWith("http") ? <Icon icon={url} iconType="solid" size={14} /> : null}
      </span>;
  };
  const renderSummary = summary => {
    const nodes = [];
    const re = /`([^`]+)`(\{[^}]*\})?/g;
    let last = 0;
    let m;
    let k = 0;
    while ((m = re.exec(summary)) !== null) {
      if (m.index > last) nodes.push(summary.slice(last, m.index));
      const attrs = m[2] || "";
      if (attrs.indexOf(".state") >= 0) {
        const state = (attrs.match(/\.state\s+\.([\w-]+)/) || [])[1] || m[1];
        nodes.push(<StateChip key={k++} state={state} label={m[1]} />);
      } else if (attrs) {
        nodes.push(<span key={k++} className="text-sm font-medium text-gray-700 dark:text-gray-300">
            {m[1]}
          </span>);
      } else {
        nodes.push(<code key={k++} className="text-sm rounded bg-gray-100 px-1 font-mono text-sm dark:bg-white/10">
            {m[1]}
          </code>);
      }
      last = m.index + m[0].length;
    }
    if (last < summary.length) nodes.push(summary.slice(last));
    return nodes;
  };
  const NoteRow = ({text}) => <div className="mt-4 mb-1 font-mono text-sm leading-5 text-gray-400 dark:text-gray-500">{"// " + text}</div>;
  const renderSteps = (steps, counter) => (steps || []).map(step => {
    counter.n += 1;
    const n = counter.n;
    const branches = (step.next || []).filter(b => b.steps && b.steps.length > 0);
    return <div key={step.id || "step-" + n}>
          {step.notes ? <NoteRow text={step.notes} /> : null}
          <div className="mt-2.5 flex items-center">
            <span className="absolute left-0 w-10 text-center font-mono text-sm text-gray-400 select-none dark:text-gray-500">
              {n}
            </span>
            <div className="flex min-w-0 flex-1 items-center gap-2 rounded-xl border border-gray-950/5 bg-white px-2 py-2 dark:border-white/10 dark:bg-gray-900">
              <StepIcon provider={step.provider} />
              <span className="text-sm shrink-0 font-medium text-gray-900 dark:text-gray-100">{step.name}</span>
              {step.summary ? <span className="text-sm min-w-0 truncate text-gray-500 dark:text-gray-400">{renderSummary(step.summary)}</span> : null}
            </div>
          </div>
          {branches.length > 0 ? <div className="ml-5 border-l border-gray-200 -my-1 py-1 pl-6 dark:border-white/10">
              {branches.map((branch, bi) => <div key={branch.code || branch.status || bi}>
                  <div className="mt-4">
                    <span className="rounded-md bg-gray-200/70 px-2 py-1 font-mono text-sm text-gray-600 dark:bg-white/10 dark:text-gray-300">
                      {branch.code || branch.status}
                    </span>
                  </div>
                  {renderSteps(branch.steps, counter)}
                </div>)}
            </div> : null}
        </div>;
  });
  const counter = {
    n: 0
  };
  const wf = workflow || ({});
  return <div className="not-prose relative my-5 rounded-2xl border border-gray-950/5 bg-gray-50 py-3 pr-4 pb-5 pl-12 dark:border-white/10 dark:bg-white/[0.03]">
      {renderSteps(wf.steps, counter)}
      {wf.rescue && wf.rescue.length > 0 ? <div className="mt-6 border-t border-dashed border-gray-300 dark:border-white/10">
          <NoteRow text="If any step fails" />
          {renderSteps(wf.rescue, counter)}
        </div> : null}
    </div>;
};

export const mxSatCancelWorkflow = {
  "name": "SAT cancel CFDI",
  "description": "Cancel a CFDI at the SAT from a status document",
  "schema": "bill/status",
  "steps": [{
    "id": "5b1f2a40-8a2e-11f0-9c6e-2f6a1c0d4e11",
    "name": "Sign envelope",
    "provider": "silo.close"
  }, {
    "id": "6c2e3b50-8a2e-11f0-9c6e-2f6a1c0d4e11",
    "name": "Cancel CFDI at SAT",
    "provider": "sat-mx.cancel"
  }, {
    "id": "7d3f4c60-8a2e-11f0-9c6e-2f6a1c0d4e11",
    "name": "Set state",
    "config": {
      "state": "completed"
    },
    "provider": "silo.state",
    "summary": "Set state to `completed`{.state .completed}"
  }],
  "rescue": [{
    "id": "8e405d70-8a2e-11f0-9c6e-2f6a1c0d4e11",
    "name": "Set state",
    "config": {
      "state": "error"
    },
    "provider": "silo.state",
    "summary": "Set state to `error`{.state .error}"
  }]
};

## Introduction

A CFDI stamped by the SAT can only be withdrawn by requesting its cancellation. The request carries a reason (*motivo*), and for most B2B invoices and payment receipts the receiver must accept it within three business days, otherwise it is accepted automatically. See [Cancellations in Mexico](/compliance/mexico#cancellations) for the rules.

In this guide you'll learn how to cancel invoices and payment receipts (*comprobantes de pago*) issued with the [SAT Mexico app](/apps/sat-mexico). A cancellation is requested with a GOBL [status document](https://docs.gobl.org/draft-0/bill/status) that references the CFDI to cancel.

## Prerequisites

* **A document issued through Invopop**: the CFDI must have been stamped by the SAT Mexico app, following the [CFDI issuing guide](/guides/mx-sat-issuing), and its `sat-uuid` stamp is needed to reference it.
* **The cancellation reason**: one of the four SAT motivos listed below.
* **For motivo 01**: the replacement CFDI, already issued with the original in its `preceding` list and relation type `04` (`mx-cfdi-rel-type`).

## Setup

All of the following steps must be carried out from the [Invopop Console](https://console.invopop.com).

<Steps>
  <Step title="Set up the SAT cancel CFDI workflow">
    <Card iconType="duotone" title="SAT cancel CFDI workflow" icon="code-branch" href="https://console.invopop.com/redirect/workflows/new?template=mx-sat-cancel" horizontal>
      Add to my workspace →
    </Card>

    <Tabs>
      <Tab title="Workflow">
        <WorkflowDiagram workflow={mxSatCancelWorkflow} />
      </Tab>

      <Tab title="Code">
        Copy and paste into a new [Empty Status workflow](https://console.invopop.com/redirect/workflows/new?template=empty-status) code view.

        ```json SAT cancel CFDI workflow theme={"system"}
        {
            "name": "SAT cancel CFDI",
            "description": "Cancel a CFDI at the SAT from a status document",
            "schema": "bill/status",
            "steps": [
                {
                    "id": "5b1f2a40-8a2e-11f0-9c6e-2f6a1c0d4e11",
                    "name": "Sign envelope",
                    "provider": "silo.close"
                },
                {
                    "id": "6c2e3b50-8a2e-11f0-9c6e-2f6a1c0d4e11",
                    "name": "Cancel CFDI at SAT",
                    "provider": "sat-mx.cancel"
                },
                {
                    "id": "7d3f4c60-8a2e-11f0-9c6e-2f6a1c0d4e11",
                    "name": "Set state",
                    "config": {
                        "state": "completed"
                    },
                    "provider": "silo.state",
                    "summary": "Set state to `completed`{.state .completed}"
                }
            ],
            "rescue": [
                {
                    "id": "8e405d70-8a2e-11f0-9c6e-2f6a1c0d4e11",
                    "name": "Set state",
                    "config": {
                        "state": "error"
                    },
                    "provider": "silo.state",
                    "summary": "Set state to `error`{.state .error}"
                }
            ]
        }
        ```
      </Tab>
    </Tabs>
  </Step>
</Steps>

### How it works

<Steps>
  <Step title="Sign envelope">
    The status document is signed. Only signed status documents can be cancelled.
  </Step>

  <Step title="Cancel CFDI at SAT">
    The app checks the CFDI's current status at the SAT and sends the cancellation request. The SAT acknowledgement (*acuse*) is attached to the status document as `cancel-acuse.xml`. The step then waits for the outcome, checking every minute, or every four hours while the receiver has to accept.
  </Step>

  <Step title="Set state">
    Once the SAT confirms the cancellation, the status document is set to `completed`. If the request fails or the receiver rejects it, the rescue step sets it to `error`.
  </Step>
</Steps>

## Cancel a document

Create a status document of type `update` with one `rejected` line referencing the CFDI to cancel, then run the cancel workflow on it.

<Info>
  The recommended approach for running jobs is to perform two steps: first upload the document to the [silo](/api-ref/silo/entries/create-an-entry-put), then [create a job](/api-ref/transform/jobs/create-a-job-post).
</Info>

The `rejected` line must include:

* `doc.code` with the document's code, and the `sat-uuid` stamp of the CFDI.
* `ext` with the reason in `mx-cfdi-cancel-reason`.

| Reason | Description | Replacement line |
| - | - | - |
| `01` | Issued with errors, with relation | Required |
| `02` | Issued with errors, without relation | No |
| `03` | The operation was not carried out | No |
| `04` | Nominative operation included in a global invoice | No |

For motivo `01`, add a second line with key `issued` that references the replacement CFDI and its `sat-uuid` stamp. Each status document cancels a single CFDI.

<AccordionGroup>
  <Accordion title="Cancellation without replacement (motivo 02)">
    ```json theme={"system"}
    {
      "$schema": "https://gobl.org/draft-0/bill/status",
      "$addons": ["mx-cfdi-v4"],
      "type": "update",
      "code": "CANCEL-0001",
      "supplier": {
        "name": "ESCUELA KEMPER URGATE",
        "tax_id": { "country": "MX", "code": "EKU9003173C9" }
      },
      "lines": [
        {
          "key": "rejected",
          "doc": {
            "code": "0001",
            "stamps": [{ "prv": "sat-uuid", "val": "fbff00b3-6577-437b-b15e-cbf25be09663" }]
          },
          "ext": { "mx-cfdi-cancel-reason": "02" }
        }
      ]
    }
    ```
  </Accordion>

  <Accordion title="Cancellation with substitution (motivo 01)">
    ```json theme={"system"}
    {
      "$schema": "https://gobl.org/draft-0/bill/status",
      "$addons": ["mx-cfdi-v4"],
      "type": "update",
      "code": "CANCEL-0002",
      "supplier": {
        "name": "ESCUELA KEMPER URGATE",
        "tax_id": { "country": "MX", "code": "EKU9003173C9" }
      },
      "lines": [
        {
          "key": "rejected",
          "doc": {
            "code": "0001",
            "stamps": [{ "prv": "sat-uuid", "val": "fbff00b3-6577-437b-b15e-cbf25be09663" }]
          },
          "ext": { "mx-cfdi-cancel-reason": "01" }
        },
        {
          "key": "issued",
          "doc": {
            "code": "0002",
            "stamps": [{ "prv": "sat-uuid", "val": "1c996ae9-7ebf-4bcc-a1a8-9c0289bcefc9" }]
          }
        }
      ]
    }
    ```
  </Accordion>
</AccordionGroup>

<Warning>
  A newly issued CFDI can take a few minutes to be available for cancellation. If the job fails with a message asking to wait, run it again after a few minutes.
</Warning>

### Outcomes

The cancel step ends with one of these results, and the error codes can be used to route the workflow:

| Result | Code | Meaning |
| - | - | - |
| OK | | The SAT cancelled the CFDI. |
| KO | `cancel-rejected` | The receiver rejected the cancellation, so the CFDI remains valid. |
| KO | `already-cancelled` | The CFDI was already cancelled before this status document. |
| KO | `cancel-in-process` | Another cancellation request for the CFDI is still waiting for the receiver. |
| KO | `not-cancellable` | The CFDI has related documents in force, such as an active payment receipt, and cannot be cancelled until they are cancelled. |

## FAQ

<AccordionGroup>
  <Accordion title="Do I have to issue B2C invoices in Mexico?">
    Individual CFDIs are not required for sales under MXN \$100, but those sales must still be included in the global CFDI. Often issuing all invoices will simplify your operation.
  </Accordion>

  <Accordion title="Does Invopop support the white label (B2B2B) model in Mexico?">
    Yes. We obtain the supplier's CSD (digital seal) and credentials to issue invoices in that company's name. Read more in our [white label use case](/guides/white-label).
  </Accordion>

  <Accordion title="Can I issue a PPD invoice through Invopop?">
    Yes. The `mx-cfdi-v4` addon supports both PUE and PPD on the original invoice, and Invopop also issues the subsequent payment receipts (REPs / Pago / comprobante de pago) that must be emitted as payments are collected. Model each receipt as a GOBL [`bill.Payment`](https://docs.gobl.org/draft-0/bill/payment) referencing the PPD invoices being settled and run it through the SAT issue payment workflow. See the [payment receipt example](/guides/mx-sat-issuing) in the issuing guide.
  </Accordion>

  <Accordion title="My customer paid late and now I have to cancel and re-issue?">
    Yes, if the original was issued as PUE and payment is not received by the last day of the issuance month, rule 2.7.1.32 RMF requires cancelling the original and re-issuing as PPD with `FormaPago = 99`, then issuing REPs as payments come in. This is calendar-driven, not payment-event-driven, and it surprises most non-Mexican implementations. The conservative approach is to issue PPD whenever there is any uncertainty about same-month payment.
  </Accordion>

  <Accordion title="What happens if I miss the REP deadline?">
    REPs must be issued by the fifth calendar day of the month following payment receipt (rule 2.7.1.35 RMF). Missing the deadline does not invalidate the underlying invoice, but it prevents the customer from deducting the expense in the correct period and exposes the issuer to fines. This is a recurring source of friction and the reason customers will sometimes refuse to accept cancellations from a supplier with poor REP discipline.
  </Accordion>

  <Accordion title="How do I configure my workspace for Mexican invoicing?">
    Install the SAT Mexico app (uses SW Sapien as PAC) plus the SW Sapien app for credentials. Onboard each issuing supplier with their CSD certificate and `mx-cfdi-issue-place`. Run invoices through the Issue CFDI workflow.
  </Accordion>

  <Accordion title="Where can I find the mapping of GOBL fields to CFDI?">
    The library that transforms GOBL into CFDI documents is publicly available as an open-source project and can be found at [github.com/invopop/gobl.cfdi](https://github.com/invopop/gobl.cfdi).

    For further details on how GOBL prepares data for conversion, see the [Mexico Tax Regime](https://github.com/invopop/gobl/blob/main/regimes/mx/README.md).
  </Accordion>

  <Accordion title="The PAC keeps rejecting my invoice with a postal code error">
    The most common cause is a mismatch between the receiver's postal code in the CFDI and the postal code SAT has on file for that RFC. Resolution: ask the customer for their CIF (Constancia de Situación Fiscal) and use the postal code printed there, exactly. Secondary causes:

    * The postal code is real but not yet in `c_CodigoPostal`. Use the closest catalog code from the place of issuance.
    * The receiver is `XAXX010101000` or `XEXX010101000` and `DomicilioFiscalReceptor` differs from `LugarExpedicion`. They must be equal for generic RFCs.
    * The branch issuing the document is configured with the matriz's postal code instead of its own.
  </Accordion>

  <Accordion title="How do I issue invoices with the 8% tax rate in border zones?">
    In Mexico, a reduced VAT rate of 8% applies to transactions in border zones (northern and southern border regions). To successfully issue invoices with this rate, **both** of the following conditions must be met:

    1. The supplier's RFC must be enabled by the SAT to invoice with the reduced rate in border zones.
    2. Both the `mx-cfdi-issue-place` field and the customer's postal code (when included) must correspond to border zones.

    If either condition is not met, the SAT will reject the invoice with an error.
  </Accordion>

  <Accordion title="What does the CFDI40999 error mean and how do I resolve it?">
    CFDI40999 is a generic "unclassified error" returned by the SAT when no other, more specific error code applies. This error can have multiple causes.

    A common scenario is invoicing in border zones with the reduced 8% VAT rate. If you receive this error in that context, verify:

    1. **RFC registration**: The supplier's RFC must be registered in the taxpayers registry for the appropriate border region tax incentive. Without this registration, the SAT will reject all invoices with the reduced rate. See [SAT's registration requirements and procedures](https://www.sat.gob.mx/minisitio/EstimulosFiscalesFronteraNorteSur/) for more information.
    2. **Issue place postal code**: The [`mx-cfdi-issue-place`](https://docs.gobl.org/addons/mx-cfdi-v4#place-of-issue) field must contain a postal code from a municipality within a border zone.
    3. **Tax rate**: Ensure you're applying the correct percentage (typically 8%) for the border zone.

    If the error persists after verifying these points, or you're getting this error for other reasons, please reach out to our support team.
  </Accordion>

  <Accordion title="I'm getting the error 'Access denied, supplier XXX is not registered in this workspace'. What should I do?">
    This error appears when you try to issue an invoice for a supplier (identified by its RFC) that has not been registered in your workspace. Before you can issue on a supplier's behalf, its CSD certificate must be uploaded and validated through the registration flow.

    To fix it, make sure the supplier is correctly registered by following the [Register a supplier](/guides/mx-sat-supplier#register-a-supplier) steps in the supplier registration guide.

    In **Sandbox** you may also hit this error for suppliers that were registered in the past. This is due to a change in how supplier registration is now enforced before sending invoices. To resolve it, open the supplier's Silo Entry in the Console and run the registration process again from the start, completing every step.
  </Accordion>

  <Accordion title="Why does my customer's UsoCFDI keep getting rejected?">
    The UsoCFDI must be allowed for the receiver's `RegimenFiscal`. The catalog defines the valid combinations; not every code works for every régimen. For example, D01–D10 (personal deductions) are only valid for individuals, never for legal entities. RESICO contributors (régimen 626) have a restricted set. When in doubt, default to `S01` (Sin efectos fiscales) — it is always valid but produces a non-deductible invoice for the receiver. Always ask the customer which UsoCFDI they need before issuing.
  </Accordion>

  <Accordion title="How does Invopop handle time zones for Mexican invoices?">
    By default, Invopop uses Mexico City's time zone (UTC-6) when automatically setting the [`issue_date`](https://docs.gobl.org/draft-0/bill/invoice#issue-date) and [`issue_time`](https://docs.gobl.org/draft-0/bill/invoice#issue-time) fields. However, the SAT validates these fields based on the time zone of the postal code specified in [`mx-cfdi-issue-place`](https://docs.gobl.org/addons/mx-cfdi-v4#place-of-issue).

    If the issuing location is in a different time zone, the SAT may reject the invoice with an error indicating the timestamp is in the future, as it only allows up to 5 minutes ahead of the local time.

    To avoid this, explicitly set `issue_date` and `issue_time` in your GOBL invoice using the local time zone of the issuing location when operating outside Mexico City's time zone.
  </Accordion>

  <Accordion title="My foreign-currency invoice is failing validation">
    For non-MXN invoices, `TipoCambio` must be present and use the FIX rate published by Banxico in the DOF the day prior to the operation (Article 20 CFF, Article 56 Ley Aduanera). Common errors:

    * Using the day-of rate instead of the prior day's.
    * Quoting the inverse (USD per MXN instead of MXN per USD).
    * Setting `TipoCambio` on an MXN invoice (it must be 1 or absent).
    * Rounding inconsistently between line totals and document totals — Anexo 20 has specific rounding rules.
  </Accordion>

  <Accordion title="Where do I find Mexico-specific GOBL documentation?">
    See the [Mexico tax regime in GOBL](https://docs.gobl.org/regimes/mx) for tax categories, RFC structure, and CFDI extensions. The [`mx-cfdi-v4`](https://docs.gobl.org/addons/mx-cfdi-v4) addon documents required fields including UsoCFDI, RegimenFiscal, and place-of-issue.
  </Accordion>
</AccordionGroup>

More available in our [Mexico FAQ](/faq/mexico) section

***

<AccordionGroup>
  <Accordion title="🇲🇽 Invopop resources for Mexico">
    | | |
    | - | - |
    | Compliance | <Icon icon="https://assets.invopop.com/flags/mx.svg" /> [Invoicing compliance in Mexico](/compliance/mexico)<br /> <Icon icon="timeline" /> [Compliance timeline](/timelines/mexico) |
    | Apps | <Icon icon="https://assets.invopop.com/apps/sat-mexico/icon.svg" /> [SAT Mexico](/apps/sat-mexico)<br /> <Icon icon="https://assets.invopop.com/apps/sw-sapien/icon.svg" /> [SW Sapien](/apps/sw-sapien)<br /> <Icon icon="https://assets.invopop.com/apps/cron/icon.svg" /> [Cron](/apps/cron) |
    | Guides | <Icon icon="book" /> [Supplier registration](/guides/mx-sat-supplier)<br /> <Icon icon="book" /> [Issuing documents](/guides/mx-sat-issuing)<br /> <Icon icon="book" /> [Cancelling documents](/guides/mx-sat-cancelling)<br /> <Icon icon="book" /> [Receiving invoices](/guides/mx-sat-receiving) |
    | FAQ | <Icon icon="square-question" /> [Mexico FAQ](/faq/mexico) |
    | GOBL | <Icon icon="https://assets.invopop.com/icons/gobl.svg" />  [Mexico Tax Regime](https://docs.gobl.org/regimes/mx)<br /> <Icon icon="https://assets.invopop.com/icons/gobl.svg" /> [Mexican SAT CFDI Addon](https://docs.gobl.org/addons/mx-cfdi-v4) |
    | GitHub | <Icon icon="github" /> [gobl.cfdi](https://github.com/invopop/gobl.cfdi) |
  </Accordion>
</AccordionGroup>

<Card title="Participate in our community" icon="forumbee" href="https://community.invopop.com" arrow="true" horizontal>
  Ask and answer questions about invoicing in Mexico →
</Card>


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