Last updated

Extract Fiscal Information in Mexico (API)

In this guide, we walk you through everything you need to extract fiscal data about your users using our API. This includes:

  • A general overview of the data flow
  • Creating a link using our API
  • Getting fiscal information:
    • Historic Updates (all links)
    • Recurrent Updates (just for recurrent links)

Prerequisites

Before you proceed with your integration, make sure that you have Gone through our getting started guide. In the getting started guide, you will create a Belvo account, generate some sandbox API keys, and set up a webhook URL. For testing purposes and developing your integration, we highly recommend using the Sandbox environment where possible.

General flow of data

Belvo uses asynchronous workflows to improve your data flow (check the diagram below).

Whenever you create a link, Belvo automatically extracts all the fiscal data for you in the background, and once we have all the data, we notify you via a webhook that the data is ready to be retrieved.

What's a link?

A link is Belvo's term for a connection between your user (RFC) and the fiscal institution (SAT). Whenever you want to extract information from a new user, you will need to create a link.

To create a link, you just need to make the following POST Register a new link request:

Sandbox Request URL
curl --location 'https://sandbox.belvo.com/api/links/' \
--header 'Content-Type: application/json' \
--header 'Authorization: Basic BASE64(SECRET_ID:SECRET_PASSWORD)' \
--data '{see_example_below}'
Sandbox Request Body
{
  "institution": "tatooine_mx_fiscal",
  "username": "PFIS010101000",
  "password": "individual",
  "access_mode": "single",
  "credentials_storage": "store",
  "stale_in": "300d",
  "external_id": "HJLSI-897809",
  "fetch_resources": [
    "FINANCIAL_STATEMENTS",
    "INVOICES",
    "TAX_RETENTIONS",
    "TAX_RETURNS",
    "TAX_STATUS",
    "TAX_COMPLIANCE_STATUS"
  ]
}
ParameterTypeRequiredDescriptionExample
institutionstringtrueThe institution where you want to create the link. You can choose either:
  • tatooine_mx_fiscal for Sandbox
  • sat_mx_fiscal for Production
tatooine_mx_fiscal
usernamestringtrueThe username of the individual or business. If you're testing out in our Sandbox environment, you can use the following credentials to mock data:
  • individuals:PFIS010101000
  • businesses:PMO010101000
PFIS010101000
passwordstringtrueThe password of the individual or business. If you're testing out in our Sandbox environment, you can use the following credentials to mock data:
  • individuals: individual
  • businesses: business
individual
access_modestringtrueThe type of link to create (single or recurrent). For fiscal data, we recommend using recurrent links as you will receive updates regarding any new invoices orrecurrent
credentials_storagestringfalseThe credentials_storage parameter allows you to control for how long Belvo stores the encrypted login credentials. For more information, check out the credentials_storage section of our Data retention controls article.store
stale_instringfalseThe stale_in parameter allows you to control for how long Belvo stores user-derived data. For more information, check out the stale_in section of our Data retention controls article.300d
external_idstringhighly recommendedYour internal reference for this user. This is extremely useful as you can the data that Belvo retrieves for this user in your system.COHORT_32_User_6790023X5
fetch_resourcesarraytrueThe resources you want Belvo to retrieve. For fiscal institutions, we recommend: ["FINANCIAL_STATEMENTS", "INVOICES", "TAX_RETENTIONS", "TAX_RETURNS", "TAX_STATUS", "TAX_COMPLIANCE_STATUS"]["FINANCIAL_STATEMENTS", "INVOICES", "TAX_RETENTIONS", "TAX_RETURNS", "TAX_STATUS", "TAX_COMPLIANCE_STATUS"]

Once you create a link, you will need to save the id of the link that your receive in the response:

Example Link Response
{
  "id": "2f8ca7a1-c28f-46f2-bb41-21633099a280", // <-- Save this ID.
  "institution": "tatooine_mx_fiscal",
  "access_mode": "single",
  "status": "valid",
  "refresh_rate": null,
  "created_by": "6e9be884-4781-4143-b673-aca02475ee8c",
  "last_accessed_at": "2024-06-26T16:25:54.344113Z",
  "external_id": "HJLSI-897809",
  "created_at": "2024-06-26T16:25:54.334413Z",
  "institution_user_id": "BidIxnZkKvQx0_F0oSYVx6Jnsh4Zmoat2ot2iOoG018=",
  "credentials_storage": "store",
  "stale_in": null,
  "fetch_resources": [
    "FINANCIAL_STATEMENTS",
    "INVOICES",
    "TAX_RETENTIONS",
    "TAX_RETURNS",
    "TAX_STATUS",
    "TAX_COMPLIANCE_STATUS"
  ]
}

Done! Belvo will now connect to the institution and asynchronously load the data for the resources your requested in fetch_resources. We will send you a webhook once we have retrieved the data for the given link, and you can then extract it with a GET request

Wait for webhooks to get historical fiscal data

As soon as you create your fiscal link, Below will asynchronously retrieve historical data for each resource you added in the fetch_resources array. As soon as Belvo retrieves the data, you will receive a webhook indicating that the data is ready to be retrieved:

ResourceNumber of WebhooksWebhook Code
FINANCIAL_STATEMENTS1historical_update
INVOICES4-8initial_inflow_update, initial_outflow_update, historical_inflow_update, historical_outflow_update
TAX_RETENTIONS1historical_update
TAX_RETURNS2historical_update
TAX_STATUS1historical_update
TAX_COMPLIANCE_STATUS1historical_update

Financial Statements

As soon as your fiscal link is created, we asynchronously load the last three years of financial statements and will send you the following webhook:

Webhook CodeDescription
historical_updateThe last three years of financial statements.

In the webhook payload we include the number of financial statements received.

Financial Statements Historical Update Example
{
  "webhook_id": "aadf41a1fc8e4f79a49f7f04027ac999",
  "webhook_type": "FINANCIAL_STATEMENTS",
  "webhook_code": "historical_update",
  "process_type": "historical_update",
  "link_id": "2f8ca7a1-c28f-46f2-bb41-21633099a280",
  "request_id": "4363b08b-51eb-4350-9c74-5df5ac92a7f6",
  "external_id": "COHORT_32_User_6790023X5",
  "data": {
    "new_financial_statements": 3
  }
}

Once you receive the notification, you can get further details by making the following request:

Financial Statements Get Request
curl --request GET \
-u [Secret Key ID]:[Secret Key PASSWORD] \
'https://api.belvo.com/api/financial-statements/?link=link_id'
Query ParameterDescriptionExample
linkThe link_id you received in the webhook notification.2f8ca7a1-c28f-46f2-bb41-21633099a280

Invoices

Due to the number of invoices an individual or business may have, and to optimize the extraction process, you will receive several different types of Invoice webhooks after you create the link.

Last 30 days of data

As soon as your fiscal recurrent link is created, we asynchronously load the last 30 days of invoice history. You will receive two notifications via a webhook whenever the last 30 days of invoices are available for you to access.

Webhook CodeDescription
initial_inflow_updateThe last 30 days of INFLOW (received) invoices.
initial_outflow_updateThe last 30 days of OUTFLOW (sent) invoices.

We include the number of invoices found during this period for the invoice type, as well as the dates for the first and last invoice in the range.

Invoices Initial Inflow Update Example
{
  "webhook_id": "ccc9c589bfcb44bc99ce749229ccf142",
  "webhook_type": "INVOICES",
  "process_type": "historical_update",
  "webhook_code": "initial_inflow_update",
  "link_id": "2f5d361d-dad6-45d4-a0bf-26d479766067",
  "request_id": "4363b08b-51eb-4350-9c74-5df5ac92a7f6",
  "external_id": "your_external_id",
  "data": {
    "total_invoices": 3456,
    "first_invoice_date": "2021-04-05",
    "last_invoice_date": "2021-05-05"
  }
}

Once you receive the notification, you can get further details by making the following request:

Invoices Get Request
curl --request GET \
-u [Secret Key ID]:[Secret Key PASSWORD] \

# Request Inflow Invoices
'https://api.belvo.com/api/invoices/?type=INFLOW&link=link_id&invoice_date__range=first_invoice_date,last_invoice_date'

# Request Outflow Invoices
'https://api.belvo.com/api/invoices/?type=OUTFLOW&link=link_id&invoice_date__range=first_invoice_date,last_invoice_date'
Query ParameterDescriptionExample
typeThe type of invoice. Can be either INFLOW or OUTFLOW. If you receive a initial_inflow_update webhook, this should be set to INFLOW. If you receive a initial_outflow_update webhook, this should be set to OUTFLOW.INFLOW
linkThe link_id you received in the webhook notification.2f5d361d-dad6-45d4-a0bf-26d479766067
invoice_date__rangeThe date range that you want to get invoices for. This should be the first_invoice_date and last_invoice_date you received in the webhook notification.2017-07-31,2018-07-31

Last 3 years of data

As soon as your fiscal recurrent link is created, we asynchronously load the last three years of INFLOW and OUTFLOW invoice history for SAT. After the initial 30 days, for each of the last three years, you will receive up to two webhook notifications: one for inflow invoices (historical_inflow_update) and one for outflow invoices (historical_outflow_update). This means you could receive up to 6 additional webhook notifications for the historical data.

For each year Belvo extracts data for, you will receive the following webhooks:

Webhook CodeDescription
historical_inflow_updateThe last 1 year of INFLOW (received) invoices.
historical_outflow_updateThe last 1 year of OUTFLOW (sent) invoices.

In the webhook payload we include the number of invoices found during this period for the invoice type, as well as the dates for the first and last invoice in the range.

Invoices Historical Inflow Update Example
{
  "webhook_id": "ccc9c589bfcb44bc99ce749229ccf142",
  "webhook_type": "INVOICES",
  "process_type": "historical_update",
  "webhook_code": "historical_inflow_update",
  "link_id": "2f5d361d-dad6-45d4-a0bf-26d479766067",
  "request_id": "4363b08b-51eb-4350-9c74-5df5ac92a7f6",
  "external_id": "your_external_id",
  "data": {
    "total_invoices": 5333, // Total number of invoices found
    "first_invoice_date": "2017-07-31", // First inflow invoice found
    "last_invoice_date": "2018-07-31" // Last inflow invoice found
  }
}

Once you receive the notification, you can get further details by making the following request:

Invoices Get Request
curl --request GET \
-u [Secret Key ID]:[Secret Key PASSWORD] \

# Request Inflow Invoices
'https://api.belvo.com/api/invoices/?type=INFLOW&link=link_id&invoice_date__range=first_invoice_date,last_invoice_date'

# Request Outflow Invoices
'https://api.belvo.com/api/invoices/?type=OUTFLOW&link=link_id&invoice_date__range=first_invoice_date,last_invoice_date'
Query ParameterDescriptionExample
typeThe type of invoice. Can be either INFLOW or OUTFLOW. If you receive a historical_inflow_update webhook, this should be set to INFLOW. If you receive a historical_outflow_update webhook, this should be set to OUTFLOW.INFLOW
linkThe link_id you received in the webhook notification.2f5d361d-dad6-45d4-a0bf-26d479766067
invoice_date__rangeThe date range that you want to get invoices for. This should be the first_invoice_date and last_invoice_date you received in the webhook notification.2017-07-31,2018-07-31

Tax Retentions

As soon as your fiscal link is created, we asynchronously load the last one year of tax retentions and will send you the following webhook:

Webhook CodeDescription
historical_updateThe last one year of Tax Retentions.

In the webhook payload we include the total number of tax retentions found for the last year, along with the date range that we retrieved data for.

Tax Retentions Historical Update
{
  "webhook_id": "03d1ca0d62db4f769488265d141047b7",
  "webhook_type": "TAX_RETENTIONS",
  "process_type": "historical_update",
  "webhook_code": "historical_update",
  "link_id": "2f5d361d-dad6-45d4-a0bf-26d479766067",
  "request_id": "4363b08b-51eb-4350-9c74-5df5ac92a7f6",
  "external_id": "your_external_id",
  "data": {
    "total_tax_retentions": 1, // The total number of tax retentions
    "first_tax_retention_date": "2023-06-01", // The date of the first tax retention found
    "last_tax_retention_date": "2023-08-20" // The date of the last tax retention found
  }
}

Once you receive the notification, you can get further details by making the following request:

Tax Retentions Get Request
curl --request GET \
-u [Secret Key ID]:[Secret Key PASSWORD] \
'https://api.belvo.com/api/tax-retentions/?link=link_id'
Query ParameterDescriptionExample
linkThe link_id you received in the webhook notification.2f5d361d-dad6-45d4-a0bf-26d479766067

Tax Returns

As soon as your fiscal link is created, we asynchronously load the last five years of yearly tax returns as well as the 12 months of monthly tax returns. You will receive a historical_update notification for each type of tax return (yearly and monthly) whenever the tax return history is available for you to access.

Webhook CodeDescription
historical_updateThe last 5 years of yearly tax returns.
historical_updateThe last 12 months of monthly tax returns.

In the webhook payload we include the type of tax returns, total number of tax returns found, as well as the first and last year of the retrieved tax returns.

Tax Returns Yearly Historical Update
{
  "webhook_id": "80fa38b7cad34950b210626abd86bfe9",
  "webhook_type": "TAX_RETURNS",
  "process_type": "historical_update",
  "webhook_code": "historical_update",
  "link_id": "2f5d361d-dad6-45d4-a0bf-26d479766067",
  "request_id": "4363b08b-51eb-4350-9c74-5df5ac92a7f6",
  "external_id": "your_external_id",
  "data": {
    "type": "yearly", // either yearly or monthly
    "total_tax_returns": 2, // Total number of yearly tax returns found
    "first_tax_return_year": 2017, // First filed yearly tax return
    "last_tax_return_year": 2018 // Last filed yearly tax return
  }
}

Once you receive the notification, you can get further details by making the following request:

Tax Returns Get Request
curl --request GET \
-u [Secret Key ID]:[Secret Key PASSWORD] \
'https://api.belvo.com/api/tax-returns/?link=link_id&ejercicio__range=first_tax_return_year,last_tax_return_year'
Query ParameterDescriptionExample
linkThe link_id you received in the webhook notification.2f5d361d-dad6-45d4-a0bf-26d479766067
ejercicio__rangeThe date range that you want to get tax returns for. This should be the first_tax_return_year and last_tax_return_year you received in the webhook notification.2017,2020

Tax Status

As soon as your fiscal link is created, we asynchronously retrieve the Tax Status (Constancia de Situación Fiscal) document and will send you the following webhook:

Webhook CodeDescription
historical_updateThe latest Tax Status for the user.

In the webhook payload you will receive the total number of Tax Status documents for the user along with the last date that the Tax Status was updated.

Tax Status Historical Update
{
  "webhook_id": "03d1ca0d62db4f769488265d141047b7",
  "webhook_type": "TAX_STATUS",
  "webhook_code": "historical_update",
  "process_type": "historical_update",
  "link_id": "2f5d361d-dad6-45d4-a0bf-26d479766067",
  "request_id": "4363b08b-51eb-4350-9c74-5df5ac92a7f6",
  "external_id": "your_external_id",
  "data": {
    "total_tax_status": 1, // Number of tax status documents
    "last_status_change_date": "1995-08-01" // Year when the tax status was last changed
  }
}

Once you receive the notification, you can get further details by making the following request:

Tax Status Get Request
curl --request GET \
-u [Secret Key ID]:[Secret Key PASSWORD] \
'https://api.belvo.com/api/tax-status/?link=link_id'
Query ParameterDescriptionExample
linkThe link_id you received in the webhook notification.2f5d361d-dad6-45d4-a0bf-26d479766067

Tax Compliance Status

As soon as your fiscal link is created, we asynchronously retrieve the Tax Compliance Status (Opinión de Cumplimiento de Obligaciones Fiscales) document and will send you the following webhook:

Webhook CodeDescription
historical_updateThe current Tax Compliance Status for the user.

In the webhook payload you will receive the total number of Tax Compliance Status documents.

Tax Compliance Status Historical Update
{
  "webhook_id": "03d1ca0d62db4f769488265d141047b7",
  "webhook_type": "TAX_COMPLIANCE_STATUS",
  "process_type": "historical_update",
  "webhook_code": "historical_update",
  "link_id": "2f5d361d-dad6-45d4-a0bf-26d479766067",
  "request_id": "4363b08b-51eb-4350-9c74-5df5ac92a7f6",
  "external_id": "your_external_id",
  "data": {
    "total_tax_compliance_status": 1 // The total number of tax compliance statement documents
  }
}

Once you receive the notification, you can get further details by making the following request:

Tax Compliance Status Get Request
curl --request GET \
-u [Secret Key ID]:[Secret Key PASSWORD] \
'https://api.belvo.com/api/tax-compliance-status/?link=link_id'
Query ParameterDescriptionExample
linkThe link_id you received in the webhook notification.2f5d361d-dad6-45d4-a0bf-26d479766067

Recurring updates

If you created a recurrent link (using access_mode: recurrent), you will receive webhooks for updated resources based on the refresh rate you established with Belvo (see the diagram in the General flow of data section).

The following webhooks are available for recurrent links:

ResourceNumber of WebhooksWebhook Code
INVOICES2-4new_invoices_available, invoices_cancelled
TAX_RETURNS2new_tax_returns_available

Invoices

According to your chosen refresh rate, Belvo will asynchronously retrieve data about any new or cancelled invoices that have appeared in the SAT system for a given link since the last update.

New Invoices

According to your chosen refresh rate, Belvo will asynchronously retrieve data about any new invoices that have appeared in the SAT system for a given link since the last update.

Webhook CodeDescription
new_invoices_availableA list of new invoices that were retrieved since the last update.

You can receive a new_invoices_available notification whenever new invoices are available for a fiscal recurrent link. You can receive more than one webhook event for a link at a time, depending on the type of invoices found. For example, you might receive a webhook event for INFLOW invoices and a separate one for OUTFLOW invoices.

We define new invoices as all new invoices found in the institution for this link since our last update. For example, if you have a daily refresh rate, it could be the new invoices from the last 24 hours or invoices added by the institution in the past 24 hours for previous days

In the webhook payload we include the number of invoices found since the last refresh, the type of invoices (INFLOW or OUTFLOW), as well as an array of invoice ids.

New Invoices Recurrent Update
{
  "webhook_id": "28364bef400f4374a80872b61ba204289",
  "webhook_type": "INVOICES",
  "process_type": "recurrent_update",
  "webhook_code": "new_invoices_available",
  "link_id": "0284557b-df47-450a-po09e-7875195c2259",
  "request_id": "4363b08b-51eb-4350-9c74-5df5ac92a7f6",
  "external_id": "your_external_id",
  "data": {
    "count": 5,
    "type": "INFLOW",
    "new_invoices": [
      // An array of invoice IDs
      "7d0afe4c-373d-490c-90e4-06xx4cdd4a17",
      "a53759bc-ca02-46f0-b1d5-31xxcd54db41",
      "64ecc7df-f322-4934-82f5-3b3ae675ef4a",
      "0452ae0d-ax2f-4093-888c-bb2ae826xa0b",
      "9c266fff-ee3d-4389-adb3-1c5690d3c032"
    ]
  }
}

Once you receive the notification, you can get further details for the new invoices by making the following request:

Invoices Get Request
curl --request GET \
-u [Secret Key ID]:[Secret Key PASSWORD] \
'https://api.belvo.com/api/invoices/?link=link_id&id__in=invoice_id_1,invoice_id_2,invoice_id_3'
Query ParameterDescriptionExample
linkThe link_id you received in the webhook notification.2f5d361d-dad6-45d4-a0bf-26d479766067
id__inThe list of invoice ids you received in the data.new_invoices of the webhook notification.24ccab1d-3a86-4136-a6eb-e04bf52b356f,beb2b197-3cf7-428d-bef3-f415c0d57509

Cancelled Invoices

According to your chosen refresh rate, Belvo will asynchronously retrieve data about any cancelled invoices that have appeared in the SAT system for a given link since the last update.

Webhook CodeDescription
invoices_cancelledA list of cancelled invoices that were retrieved since the last update.

We define canceled invoices as all existing invoices with a new "canceled" status in the institution for this link

In the webhook payload we include the type of cancelled invoices (INFLOW or OUTFLOW) as well as an array of invoice ids.

Cancelled Invoices Recurrent Update
{
  "webhook_id": "aadf41a1fc8e4f79a49f7f04027ac999",
  "webhook_type": "INVOICES",
  "process_type": "recurrent_update",
  "webhook_code": "invoices_cancelled",
  "link_id": "16f68516-bcbc-4cf7-b815-c500d4204e28",
  "request_id": "4363b08b-51eb-4350-9c74-5df5ac92a7f6",
  "external_id": "your_external_id",
  "data": {
    "type": "INFLOW",
    "cancelled_invoices": [
      // An array of invoice IDs
      "0a362860-c92f-4414-a731-a772e88ab54b",
      "0a376126-c23r-2131-b745-a876d77cd76c"
    ]
  }
}

Once you receive the notification, you can get further details for the cancelled invoices by making the following request:

Invoices Get Request
curl --request GET \
-u [Secret Key ID]:[Secret Key PASSWORD] \
'https://api.belvo.com/api/invoices/?link=link_id&id__in=invoice_id_1,invoice_id_2,invoice_id_3'
Query ParameterDescriptionExample
linkThe link_id you received in the webhook notification.2f5d361d-dad6-45d4-a0bf-26d479766067
id__inThe list of invoice ids you received in the data.cancelled_invoices of the webhook notification.24ccab1d-3a86-4136-a6eb-e04bf52b356f,beb2b197-3cf7-428d-bef3-f415c0d57509

Tax Returns

According to your chosen refresh rate, Belvo will asynchronously retrieve data about any new tax returns that have appeared in the SAT system for a given link since the last update.

Webhook CodeDescription
new_tax_returns_availableA count of new tax returns since the last update.

You can receive a new_tax_returns_available notification whenever new tax returns are available for a fiscal recurrent link. You can receive more than one webhook event for a link at a time, depending on the type of tax returns found. For example, you might receive a webhook event for monthly tax returns and a separate one for yearly tax returns.

We define new tax returns as all new tax returns found in the institution for this link since our last update. It could be new tax returns from the last year or also tax returns that were added by the institution for previous years or months

In the webhook payload we include the the type of tax returns (monthly or yearly) as well as the number of tax returns found since the last refresh.

New Yearly Tax Returns Update
{
  "webhook_id": "351610c401e34e728900495fda5b970a",
  "webhook_type": "TAX_RETURNS",
  "process_type": "recurrent_update",
  "webhook_code": "new_tax_returns_available",
  "link_id": "331ba983-0cfa-4186-93fc-936f3946cca3",
  "request_id": "4363b08b-51eb-4350-9c74-5df5ac92a7f6",
  "external_id": "your_external_id",
  "data": {
    "type": "yearly", // can be either yearly or monthly
    "new_tax_returns": 1 // Total number of new tax returns found
  }
}

Once you receive the notification, you can get further details by making the following request:

Tax Returns Get Request
curl --request GET \
-u [Secret Key ID]:[Secret Key PASSWORD] \
'https://api.belvo.com/api/tax-returns/?link=link_id&created_at__range=date1,date2'
Query ParameterDescriptionExample
linkThe link_id you received in the webhook notification.2f5d361d-dad6-45d4-a0bf-26d479766067
created_at__rangeThe date range you want to receive tax returns for. We recommend that date1 is the date when you previously received a notification and date2 is the date when you receive the current notification (both in YYYY-MM-DD format).2024-05-01,2024-06-01

Errors while extracting Financial Statements

In order to provide you greater visibility regarding the extraction of Financial Statement data, we have included a new error field in the response payload for each financial statement you will still receive.

If, for a given year where a financial statement is available, we are not able to retrieve data due to the institution not providing the information in the correct format, the error field will indicate the reason behind the unsuccessful extraction:

[
  {
    "id": "0d3ffb69-f83b-456e-ad8e-208d0998d71d",
    "link": "30cb4806-6e00-48a4-91c9-ca55968576c8",
    "collected_at": "2022-02-09T08:45:50.406032Z",
    "created_at": "2022-02-09T08:45:50.406032Z",
    "error": "Unable to validate if the user has an available financial statement for the specified year.",
    "year": 2020,
    "currency": "MXN",
    "balance_sheet": null,
    "income_statement": null
  }
]

The possible error messages are:

  • Unable to validate if the user has an available financial statement for the specified year.
  • No available financial statement found for the user for the specified year, preventing data extraction.
  • Unable to verify if the user has _conceptos vigentes_ for the specified year.
  • The fiscal institution provided the financial statement in an unrecognized format.

If you receive financial statement payloads with these errors, please contact our support team.