> ## 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 receiving invoices guide

> Import received CFDI documents from Mexico's SAT into your Invopop workspace.

<Warning>
  This guide uses the [SW Sapien app](/apps/sw-sapien), which is not available by default. Contact us if you are interested in using it.
</Warning>

## Introduction

The SAT (*Servicio de Administración Tributaria*) provides mechanisms for bulk downloading CFDI (*Comprobante Fiscal Digital por Internet*) documents, both issued and received. Importing these documents into Invopop lets you convert them to [GOBL](https://docs.gobl.org) format and take advantage of processing capabilities such as accounts payable workflows, PDF generation, and integrations with external systems.

This guide walks you through configuring your Invopop workspace to automatically import **received** invoices from SAT on a recurring schedule. The process uses three apps working together:

* **[Cron](/apps/cron):** Schedules the import workflow to run automatically at a regular interval (*e.g.*, daily).
* **[SW Sapien](/apps/sw-sapien):** Downloads CFDIs in bulk from SAT through [SW Sapien's](https://sw.com.mx/) Efisco service, a trusted third-party provider that handles SAT authentication.
* **[SAT Mexico](/apps/sat-mexico):** Converts CFDI XML documents to GOBL format.

<Note>
  The SW Sapien app also supports importing *issued* invoices. See the [SW Sapien app documentation](/apps/sw-sapien) for configuration details.
</Note>

## Prerequisites

Before you begin, make sure you have:

* An **Invopop workspace**. See the [quickstart guide](/get-started/quickstart) if you need to create one.
* An **SW Sapien Efisco account** with API credentials. Visit [sw.com.mx](https://sw.com.mx/) to create an account and obtain your API token.
* The **RFC** (*Registro Federal de Contribuyentes*) of the entity whose received invoices you want to import.
* The entity's **e.firma (FIEL)** certificate. This digital certificate issued by SAT is required to authorize bulk CFDI downloads on behalf of the entity.

## How it works

The import process follows three main stages:

1. **Scheduling:** The [Cron app](/apps/cron) creates a job for the import workflow at each configured interval, passing the time window (`from` and `upto`) to process.
2. **Downloading:** Each import job runs the [SW Sapien app](/apps/sw-sapien) to request CFDIs from SAT via Efisco for the given time window. Once the download is ready, it uploads each CFDI file and creates a conversion job.
3. **Converting:** Each conversion job runs the [SAT Mexico app's](/apps/sat-mexico) import action to convert the CFDI XML into GOBL format.

## Setup

Configure your Invopop workspace for receiving CFDI imports by following these steps in the [Invopop Console](https://console.invopop.com):

<Steps>
  <Step title="Connect the SAT Mexico app">
    Navigate to **Configuration** → **Apps**, locate **SAT Mexico** in the app discovery list, and click **Connect**.

    <Tip>
      If you already use the SAT Mexico app for issuing invoices, you can skip this step. The same app handles both sending and importing.
    </Tip>
  </Step>

  <Step title="Connect the SW Sapien app">
    In the same **Apps** section, locate **SW Sapien** and click **Connect**. The app will move to the "Enabled Apps" section.

    Next, click **Configure** and enter your SW Sapien API credentials:

    * **API Token**: Your SW Sapien Efisco API token.

    <Note>
      You can obtain your API token from the [SW Sapien portal](https://portal.sw.com.mx/) under **Configuración** → **Credenciales de acceso**.
    </Note>
  </Step>

  <Step title="Connect the Cron app">
    Still in the **Apps** section, locate **Cron** and click **Connect**. No additional configuration is needed at this stage.
  </Step>

  <Step title="Set up the CFDI Import Workflow">
    This workflow converts individual CFDI documents to GOBL format. It will be triggered automatically for each downloaded CFDI.

    <Tabs>
      <Tab title="Template">
        <Card iconType="duotone" title="SAT import CFDI workflow" icon="code-branch" href="https://console.invopop.com/redirect/workflows/new?template=sat-convert-cfdi" cta="Add to my workspace">
          Import a CFDI document and convert it to GOBL format.
        </Card>
      </Tab>

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

        ```json Example SAT import CFDI workflow theme={"system"}
        {
            "name": "SAT import CFDI",
            "description": "Import a CFDI received through SAT",
            "schema": "bill/invoice",
            "steps": [
                {
                    "id": "6346e330-14cc-11f1-85d2-9d77c04210bc",
                    "name": "Import CFDI from SAT",
                    "provider": "sat-mx.import"
                },
                {
                    "id": "74f01110-14cc-11f1-85d2-9d77c04210bc",
                    "name": "Set state",
                    "provider": "silo.state",
                    "summary": "Set state to `received`{.state .received}",
                    "config": {
                        "state": "received"
                    }
                }
            ],
            "rescue": [
                {
                    "id": "e5f6a7b0-1a2b-11f0-b001-4a5b6c7d8e9f",
                    "name": "Set state",
                    "provider": "silo.state",
                    "summary": "Set state to `error`{.state .error}",
                    "config": {
                        "state": "error"
                    }
                }
            ]
        }
        ```
      </Tab>

      <Tab title="Build from scratch">
        Before starting, review the [workflows guide](/guides/features/workflows) to understand the general setup process.

        In [Console](https://console.invopop.com), create a new workflow and choose [Empty Invoice workflow](https://console.invopop.com/redirect/workflows/new?template=empty-invoice) as the base. Then name it something descriptive like "SAT Convert CFDI".

        The workflow needs these steps:

        1. **Import CFDI from SAT** - Uses the SAT Mexico app to convert the CFDI XML to GOBL format.
        2. **Set state** - To "received".

        In the **Error Handling** section, add a **Set state** step and select `Error`.
      </Tab>
    </Tabs>

    <Tip>
      You can extend the conversion workflow with additional steps to suit your needs, such as generating a PDF, sending a [webhook](/guides/webhooks) notification, forwarding the invoice by [email](/apps/email), or storing a copy in [Google Drive](/apps/google-drive).
    </Tip>

    <Tip>
      Remember the name you give this workflow. You will need to select it by name when configuring the import workflow in the next step.
    </Tip>
  </Step>

  <Step title="Set up the Efisco bulk import CFDIs workflow">
    This workflow uses the SW Sapien app to download CFDIs from SAT and dispatch conversion jobs for each one. It will be executed periodically by the Cron app.

    <Tabs>
      <Tab title="Template">
        <Card iconType="duotone" title="Efisco bulk import CFDIs workflow" icon="code-branch" href="https://console.invopop.com/redirect/workflows/new?template=sw-sapien-import-cfdi" cta="Add to my workspace">
          Download CFDIs from SAT via SW Sapien and dispatch import CFDI job.
        </Card>

        After adding the template, open the **Bulk import CFDIs from Efisco** step and set the **Import Workflow** field to the CFDI Conversion Workflow created in the previous step.
      </Tab>

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

        ```json Example SW Sapien bulk import CFDIs workflow theme={"system"}
        {
            "name": "SW Sapien bulk import CFDIs",
            "description": "Bulk-import CFDIs from SAT via SW Sapien Efisco",
            "schema": "org/party",
            "steps": [
                {
                    "id": "28b5e810-14cc-11f1-85d2-9d77c04210bc",
                    "name": "Bulk import CFDIs from Efisco",
                    "provider": "sw-sapien.efisco.import",
                    "summary": "Received → no workflow",
                    "config": {
                        "document_type": "Recepcion",
                        "workflow_id": ""
                    }
                }
            ],
            "rescue": [
                {
                    "id": "a7b8c9d0-2b3c-11f0-c002-5b6c7d8e9f0a",
                    "name": "Set state",
                    "provider": "silo.state",
                    "summary": "Set state to `error`{.state .error}",
                    "config": {
                        "state": "error"
                    }
                }
            ]
        }
        ```

        After pasting the code, switch to the form view, open the **Bulk import CFDIs from Efisco** step and set the **Import Workflow** field to the CFDI Conversion Workflow created in the previous step.
      </Tab>

      <Tab title="Build from scratch">
        Before starting, review the [workflows guide](/guides/features/workflows) to understand the general setup process.

        In [Console](https://console.invopop.com), create a new workflow and choose [Empty Party workflow](https://console.invopop.com/redirect/workflows/new?template=empty-party) as the base. Then name it something descriptive like "SW Sapien Import CFDIs".

        The workflow needs a single step:

        1. **Bulk import CFDIs from Efisco** - Configure with:
           * **Document Type**: Select `Received` to import invoices received by the party.
           * **Import Workflow**: Select the CFDI Conversion Workflow created in the previous step.

        In the **Error Handling** section, add a **Set state** step and select `Error`.
      </Tab>
    </Tabs>

    <Tip>
      Remember the name of this workflow. You will need to select it by name when configuring the subscription workflow in the next step.
    </Tip>
  </Step>

  <Step title="Set up the Party Subscription Workflow">
    This workflow subscribes a party to periodic CFDI imports using the Cron app. Run it once per party you want to receive invoices for.

    <Tabs>
      <Tab title="Template">
        <Card iconType="duotone" title="Subscribe party to CFDI import workflow" icon="code-branch" href="https://console.invopop.com/redirect/workflows/new?template=mx-subscribe-import" cta="Add to my workspace">
          Subscribe a party to daily CFDI bulk imports.
        </Card>

        After adding the template, open the **Subscribe to Periodic Import** step and set the **Workflow** field to the bulk import CFDI workflow created in the previous step.
      </Tab>

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

        ```json Example SW Sapien subscribe to CFDI import workflow theme={"system"}
        {
            "name": "SW Sapien subscribe to CFDI import",
            "description": "Subscribe a party to periodic CFDI bulk imports",
            "schema": "org/party",
            "steps": [
                {
                    "id": "2ab3c280-164e-11f1-a769-19319c292fdf",
                    "name": "Subscribe to periodic execution",
                    "provider": "cron.subscribe",
                    "summary": "Hourly → SW Sapien bulk import CFDIs",
                    "config": {
                        "interval": "hourly",
                        "workflow_id": "f907561b-81c2-4bd5-9199-95638ed60669"
                    }
                },
                {
                    "id": "3a99bc90-164e-11f1-a769-19319c292fdf",
                    "name": "Set state",
                    "provider": "silo.state",
                    "summary": "Set state to `registered`{.state .registered}",
                    "config": {
                        "state": "registered"
                    }
                }
            ],
            "rescue": [
                {
                    "id": "d0e1f2a0-3c4d-11f0-d003-6c7d8e9f0a1b",
                    "name": "Set state",
                    "provider": "silo.state",
                    "summary": "Set state to `error`{.state .error}",
                    "config": {
                        "state": "error"
                    }
                }
            ]
        }
        ```

        After pasting the code, switch to the form view, open the **Subscribe to Periodic Import** step and set the **Workflow** field to the bulk import CFDI workflow created in the previous step.
      </Tab>

      <Tab title="Build from scratch">
        Before starting, review the [workflows guide](/guides/features/workflows) to understand the general setup process.

        In [Console](https://console.invopop.com), create a new workflow and choose [Empty Party workflow](https://console.invopop.com/redirect/workflows/new?template=empty-party) as the base. Then name it something descriptive like "Subscribe to CFDI Import".

        The workflow needs these steps:

        1. **Subscribe to Periodic Import** - Uses the Cron app. Configure with:
           * **Workflow**: Select the bulk import CFDI workflow created in the previous step.
           * **Interval**: Select the desired frequency (for example, `daily`).
        2. **Set state** - To "registered".

        In the **Error Handling** section, add a **Set state** step and select `Error`.
      </Tab>
    </Tabs>
  </Step>

  <Step title="Set up the Party Registration Workflow">
    This workflow registers a party with SW Sapien's Efisco service by generating a link where the party's e.firma (FIEL) certificate can be uploaded. Run it once per party before subscribing them to periodic imports.

    <Tabs>
      <Tab title="Template">
        <Card iconType="duotone" title="SW Sapien register party workflow" icon="code-branch" href="https://console.invopop.com/redirect/workflows/new?template=sw-sapien-register-party" cta="Add to my workspace">
          Register a party with SW Sapien's Efisco service for CFDI downloads.
        </Card>
      </Tab>

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

        ```json Example SW Sapien register party workflow theme={"system"}
        {
            "name": "SW Sapien register party",
            "description": "Register a party with SW Sapien Efisco to enable CFDI downloads",
            "schema": "org/party",
            "steps": [
                {
                    "id": "aaa044b0-14cc-11f1-85d2-9d77c04210bc",
                    "name": "Set state",
                    "provider": "silo.state",
                    "summary": "Set state to `processing`{.state .processing}",
                    "config": {
                        "state": "processing"
                    }
                },
                {
                    "id": "ae845cb0-14cc-11f1-85d2-9d77c04210bc",
                    "name": "Register supplier with Efisco",
                    "provider": "sw-sapien.efisco.register"
                }
            ],
            "rescue": [
                {
                    "id": "a3b4c5d0-4d5e-11f0-e004-7d8e9f0a1b2c",
                    "name": "Set state",
                    "provider": "silo.state",
                    "summary": "Set state to `error`{.state .error}",
                    "config": {
                        "state": "error"
                    }
                }
            ]
        }
        ```
      </Tab>

      <Tab title="Build from scratch">
        Before starting, review the [workflows guide](/guides/features/workflows) to understand the general setup process.

        In [Console](https://console.invopop.com), create a new workflow and choose [Empty Party workflow](https://console.invopop.com/redirect/workflows/new?template=empty-party) as the base. Then name it something descriptive like "SW Sapien Register Party".

        The workflow needs these steps:

        1. **Set state** - To "processing".
        2. **Register supplier with Efisco** - Initiates the registration of the party with SW Sapien's Efisco service.

        In the **Error Handling** section, add a **Set state** step and select `Error`.
      </Tab>
    </Tabs>
  </Step>
</Steps>

## Running

With all workflows in place, you can now register parties and start receiving invoices. For each entity whose invoices you want to import, you need to register them with SW Sapien's Efisco service and then subscribe them to periodic imports.

### Register a receiving party

<Steps>
  <Step title="Create the party">
    In the left sidebar, click **Parties**.

    Click **+New party** and enter the party's data manually using the console, or switch to developer mode (`</>` icon) to paste the data directly. At a minimum, provide:

    * **Name** of the company
    * **Tax ID Country** with `MX`
    * **Tax ID Code** with the entity's RFC (*Registro Federal de Contribuyentes*)

    Here is an example party for reference:

    ```json SAT Mexico party example theme={"system"}
    {
      "$schema": "https://gobl.org/draft-0/org/party",
      "uuid": "018fbeda-bc61-7000-b66d-398ce3e21c43",
      "name": "ESCUELA KEMPER URGATE",
      "tax_id": {
        "country": "MX",
        "code": "EKU9003173C9"
      },
      "ext": {
        "mx-cfdi-fiscal-regime": "601"
      }
    }
    ```

    Click **Build**, verify there are no errors, then click **Save**.
  </Step>

  <Step title="Run the Registration Workflow">
    With the party entry selected, click **Select Workflow** and execute the **SW Sapien Register Party** workflow.

    After it completes, the party's state will change to `Processing` and a registration link will appear in the **Meta** tab of the entry.
  </Step>

  <Step title="Complete the e.firma (FIEL) upload">
    Open the **Details** window and click on **Meta**. You will see a **Registration Link** with a URL.

    <Info>
      You can access the registration link via the API by [fetching the silo entry](/api-ref/silo/entries/fetch-an-entry) and locating the meta entry where the key is `registration-link`.
    </Info>

    Visit that URL to access the registration form. Fill in the entity's **RFC** and upload the **e.firma (FIEL)** certificate files (`.cer` and `.key`) along with the private key password.

    <Note>
      This form can be shared directly with the entity if required.
    </Note>

    When you click **Save**, the certificate details are securely sent to SW Sapien's Efisco service, which will use them to authenticate bulk CFDI download requests from SAT on behalf of the entity.

    <Note>
      You can also upload the e.firma certificate programmatically using the [Upload e.firma certificate](/api-ref/apps/sw-sapien/certificate-upload) API endpoint. This is useful for automating onboarding or integrating the registration process into your own application.
    </Note>
  </Step>

  <Step title="Subscribe the party to imports">
    Once the e.firma has been uploaded, execute the **Subscribe to CFDI Import** workflow on the same party entry.

    Once the workflow completes successfully, the party's state will change to `Registered` and the Cron app will begin scheduling import jobs at the configured interval.
  </Step>
</Steps>

### Monitor imported invoices

Once the subscription is active, the [Cron app](/apps/cron) will automatically create an import job at each configured interval (for example, daily). Here is what happens during each cycle:

1. **Cron creates an import job** with a time window (`from` and `upto`) corresponding to the scheduled interval. You can see these jobs as they are created in the **Workflows** → **History** section of the Console.

2. **The import step shifts the window 72 hours into the past.** This is because SAT allows invoices to be issued with a date up to 72 hours before the current time. By shifting the window, the import ensures it only downloads consolidated data where all invoices for that period have been finalized.

<Note>
  For example, if Cron schedules a job on March 10 covering March 9–10, the actual download request to SAT will cover March 6–7. This three-day lag guarantees completeness.
</Note>

3. **The import job enters a `Queued` state** while the SW Sapien app requests the CFDIs from SAT via Efisco. This is an asynchronous process: SAT may take anywhere from a few minutes to several hours (and in exceptional cases, up to six days) to make the download available. The job remains queued until the data is ready.

4. **Once the download completes**, the import step retrieves the CFDIs and dispatches a separate conversion job for each one. These conversion jobs will also appear in **Workflows** → **History**.

5. **Each conversion job** runs the CFDI Conversion Workflow, which converts the CFDI XML to [GOBL](https://docs.gobl.org) format and marks the document with the state `Received`. The resulting silo entries will appear in the **Invoices** section of the Console.

If errors occur during any stage, the rescue steps in the corresponding workflow will set the document state to `Error`, allowing you to identify and resolve issues through the Console or API.

### Run the CFDI import manually

For testing purposes, you can trigger the EFisco bulk CFDI import workflow manually instead of waiting for the Cron app to execute it on schedule.

<Steps>
  <Step title="Open the workflow">
    Navigate to the **Workflows** section in the Console and locate the build CFDI import workflow you created during setup. Click on it to open its details.
  </Step>

  <Step title="Run the workflow">
    Click the <kbd>Run</kbd> button and configure the execution:

    * **Document**: Enter the party entry whose RFC you want to import invoices for.
    * **Arguments**: Add the following two parameters:
      * `from`: The start of the time window in ISO 8601 format, for example `2025-03-01T00:00:00Z`.
      * `upto`: The end of the time window in ISO 8601 format, for example `2025-03-02T00:00:00Z`.

    <Note>
      The import step applies the 72-hour shift described above. For example, if you set `from` and `upto` to cover March 9–10, the actual download request to SAT will cover March 6–7.
    </Note>
  </Step>
</Steps>

### Unsubscribe a party

To stop importing invoices for a specific party, create a workflow with the Cron **Unsubscribe** action and execute it on the party's entry. This removes the subscription and no further import jobs will be scheduled.

## FAQ

<FAQ />

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" /> [Issuing invoices](/guides/mx-sat-issuing)<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>
