Skip to main content

Prerequisites

1

API key from Dashboard

Get your API key from the Cadana Dashboard. See Authentication for details.
2

Business with workers in supported jurisdictions

At least one business must be created with workers onboarded in a supported jurisdiction.

Core Concepts

The Statutory Compliance API handles the post-payroll compliance lifecycle — filing statutory returns with government authorities and remitting payments. For filing data, it acts as the single front door: you submit all required data through the statutory endpoints, and the API handles the rest. The developer workflow is:
  1. Discover — Call the required-fields endpoint to see what’s needed for each jurisdiction
  2. Check — Call the requirements endpoint to see what’s still missing for a specific person or business
  3. Submit — Send the missing data through the statutory PUT endpoints
  4. File & Remit — Cadana handles filing with authorities and government payments

Step 1: Discover Jurisdictions

List every jurisdiction the Statutory API supports, along with the filing types available in each. Response:
{
  "data": [
    {
      "countryCode": "MX",
      "countryName": "Mexico",
      "currency": "MXN",
      "filingTypesCount": 4,
      "payrollFrequency": "MONTHLY",
      "status": "live"
    },
    {
      "countryCode": "BR",
      "countryName": "Brazil",
      "currency": "BRL",
      "filingTypesCount": 4,
      "payrollFrequency": "MONTHLY",
      "status": "live"
    }
  ]
}

Step 2: Understand a Jurisdiction

Once you know which jurisdictions are available, drill into a specific country to see its filing types, deadlines, and cadence. Response:
{
  "data": [
    {
      "id": "ft_mx_isr_monthly",
      "name": "ISR Withholding",
      "description": "Monthly income tax withholding return",
      "governmentFormName": "Declaración Provisional ISR",
      "authority": { "id": "auth_mx_sat", "name": "Servicio de Administración Tributaria", "abbreviation": "SAT" },
      "frequency": "MONTHLY",
      "dueDay": 17,
      "includesRemittance": true,
      "legislativeReference": "Ley del Impuesto Sobre la Renta (LISR), Artículo 96"
    },
    {
      "id": "ft_mx_imss_bimonthly",
      "name": "IMSS Contributions",
      "description": "Social security contributions",
      "authority": { "id": "auth_mx_imss", "name": "Instituto Mexicano del Seguro Social", "abbreviation": "IMSS" },
      "frequency": "BIMONTHLY",
      "dueDay": 17,
      "includesRemittance": true,
      "legislativeReference": "Ley del Seguro Social (LSS), Artículo 39"
    },
    {
      "id": "ft_mx_infonavit_bimonthly",
      "name": "INFONAVIT Contributions",
      "description": "Housing fund contributions",
      "authority": { "id": "auth_mx_infonavit", "name": "Instituto del Fondo Nacional de la Vivienda para los Trabajadores", "abbreviation": "INFONAVIT" },
      "frequency": "BIMONTHLY",
      "dueDay": 17,
      "includesRemittance": true,
      "legislativeReference": "Ley del INFONAVIT, Artículo 29"
    },
    {
      "id": "ft_mx_isn_monthly",
      "name": "ISN Payroll Tax",
      "description": "State-level payroll tax",
      "authority": { "id": "auth_mx_state", "name": "State Tax Authority", "abbreviation": "State" },
      "frequency": "MONTHLY",
      "dueDay": 17,
      "includesRemittance": true,
      "legislativeReference": "Ley de Hacienda del Estado (varies by state)"
    }
  ]
}

What Fields Are Required?

Before filing, you need to know which fields are required for tax calculation and statutory filing. The required-fields endpoint returns all fields needed in a given jurisdiction — each field includes an entity (who the field belongs to) and a scope (what it’s used for).
Use this response to build onboarding forms for each jurisdiction. Each field includes an entity value of "person" or "business", so you can render separate forms for worker data and employer data.
Response:
{
  "countryCode": "MX",
  "workerType": "employee",
  "version": 3,
  "fields": [
    {
      "key": "firstName",
      "name": "First Name",
      "description": "Worker's legal first name, required on all statutory returns",
      "type": "string",
      "required": true,
      "entity": "person",
      "scope": ["filing"]
    },
    {
      "key": "lastName",
      "name": "Last Name",
      "description": "Worker's legal last name, required on all statutory returns",
      "type": "string",
      "required": true,
      "entity": "person",
      "scope": ["filing"]
    },
    {
      "key": "jobTitle",
      "name": "Job Title",
      "description": "Worker's job title, required for statutory classification",
      "type": "string",
      "required": true,
      "entity": "person",
      "scope": ["filing"]
    },
    {
      "key": "startDate",
      "name": "Employment Start Date",
      "description": "Date the worker started employment, required for social security and filing",
      "type": "string",
      "required": true,
      "entity": "person",
      "scope": ["filing"]
    },
    {
      "key": "taxId",
      "name": "RFC (Registro Federal de Contribuyentes)",
      "description": "13-character tax ID for individuals",
      "type": "string",
      "pattern": "^[A-Z&Ñ]{4}\\d{6}[A-Z0-9]{3}$",
      "required": true,
      "entity": "person",
      "scope": ["calculation", "filing"]
    },
    {
      "key": "imssNumber",
      "name": "IMSS Social Security Number (NSS)",
      "description": "11-digit social security number",
      "type": "string",
      "required": true,
      "entity": "person",
      "scope": ["filing"]
    },
    {
      "key": "maritalStatus",
      "name": "Marital Status",
      "description": "Used for tax deduction eligibility under LISR",
      "type": "string",
      "required": true,
      "entity": "person",
      "scope": ["calculation"],
      "enum": ["single", "married", "divorced", "widowed"]
    },
    {
      "key": "state",
      "name": "State",
      "description": "ISO 3166-2 state code (e.g. MX-JAL)",
      "type": "string",
      "required": true,
      "entity": "person",
      "scope": ["calculation", "filing"]
    },
    {
      "key": "employerRfc",
      "name": "Employer RFC",
      "description": "Business tax ID for SAT filings",
      "type": "string",
      "required": true,
      "entity": "business",
      "scope": ["filing"]
    }
  ]
}
Each field has two key attributes:
  • entity — Who the field belongs to: person or business. This tells you which PUT endpoint to use.
  • scope — What it’s used for: filing fields go to the statutory PUT endpoint. calculation fields go to PUT /v1/persons/{id}/taxProfile.

How to Submit the Fields

The statutory service is the single front door for all filing data. You only need two endpoints: The workflow is:
  1. Discover what’s needed → GET /v1/statutory/jurisdictions/{cc}/required-fields
  2. Check what’s missing → GET /v1/statutory/requirements?personId=...&countryCode=...
  3. Submit what’s missing → each requirement’s resolutionGuide tells you which endpoint to call
The statutory PUT endpoint accepts all filing-scope fields — including fields like firstName or taxId that may already exist on the person record. Data already on the person record auto-populates and won’t appear as an outstanding requirement, so in practice you’re only submitting the fields that are actually missing. Both return 204 No Content on success.

Read Back Filing Data

The GET endpoint returns a merged view — fields you submitted via PUT combined with data already on the person or business record: Response:
{
  "entityType": "person",
  "entityId": "per_xyz789",
  "countryCode": "MX",
  "fields": {
    "firstName": "María",
    "lastName": "García",
    "taxId": "GAPM900101ABC",
    "imssNumber": "12345678901",
    "jobTitle": "Software Engineer",
    "startDate": "2026-03-01",
    "maritalStatus": "single",
    "state": "MX-JAL"
  }
}
Fields like firstName, taxId, and jobTitle were already on the person record from onboarding — they appear automatically in the merged response without needing to be submitted again.

Step 3: Check Requirements

After onboarding, use the requirements endpoint to see what’s still missing. This is the most reliable way to check whether a person or business is ready for statutory filing — you don’t need to manually cross-reference the required-fields list.

Business-Level Requirements

If a person is linked to a sub-entity via jobInfo.entityId, the entity’s registration details (taxId, registrationNumber, address) are used for statutory requirements instead of the parent business’s. See Entity Management.
Response:
{
  "data": [
    {
      "category": "business_registration",
      "status": "outstanding",
      "name": "IMSS Employer Registration",
      "description": "IMSS employer registration number is required for social security filings",
      "affectedField": "imssRegistration",
      "resourceType": "business",
      "resourceId": "bus_abc123",
      "resolutionGuide": "Submit via PUT /v1/statutory/businesses/{id}/fields/{countryCode}"
    },
    {
      "category": "worker_data",
      "status": "outstanding",
      "name": "Social Security Number (NSS)",
      "description": "Worker NSS is required for IMSS and INFONAVIT filings",
      "affectedField": "socialSecurityId",
      "resourceType": "person",
      "resourceId": "per_xyz789",
      "resolutionGuide": "Submit via PUT /v1/statutory/persons/{id}/fields/{countryCode}",
      "affectedPersons": [
        {
          "personId": "per_xyz789",
          "personName": "María García",
          "missingField": "socialSecurityId",
          "missingFieldLabel": "IMSS Social Security Number (NSS)"
        }
      ]
    }
  ]
}
Each requirement includes a resolutionGuide that points to the statutory service’s field submission endpoint — PUT /v1/statutory/persons/{id}/fields/{cc} for person fields or PUT /v1/statutory/businesses/{id}/fields/{cc} for business fields. Once you submit the data, the requirement is resolved automatically.
Filings that depend on outstanding requirements will be in blocked status until the requirements are resolved. You do not need to manually retry — the Statutory API detects when missing data is submitted and unblocks filings automatically.

Per-Worker Requirements

You can also check requirements for a specific worker to see what’s missing before their next payroll run. Response:
{
  "data": [
    {
      "category": "worker_data",
      "status": "outstanding",
      "name": "Job Title",
      "description": "Worker's job title is required for statutory classification",
      "affectedField": "jobInfo.title",
      "resourceType": "person",
      "resourceId": "per_xyz789",
      "resolutionGuide": "Submit via PUT /v1/statutory/persons/{id}/fields/{countryCode}",
      "affectedPersons": [
        {
          "personId": "per_xyz789",
          "personName": "María García",
          "missingField": "jobInfo.title",
          "missingFieldLabel": "Job Title"
        }
      ]
    },
    {
      "category": "worker_data",
      "status": "outstanding",
      "name": "Social Security Number (NSS)",
      "description": "Worker NSS is required for IMSS and INFONAVIT filings",
      "affectedField": "socialSecurityId",
      "resourceType": "person",
      "resourceId": "per_xyz789",
      "resolutionGuide": "Submit via PUT /v1/statutory/persons/{id}/fields/{countryCode}",
      "affectedPersons": [
        {
          "personId": "per_xyz789",
          "personName": "María García",
          "missingField": "socialSecurityId",
          "missingFieldLabel": "IMSS Social Security Number (NSS)"
        }
      ]
    }
  ]
}
Filter by status=outstanding to find what still needs attention. Once you submit the missing data via the statutory PUT endpoint, requirements resolve automatically.

Step 4: Check the Compliance Calendar

Once requirements are met, list upcoming and active filings for a business. This gives you a view of the compliance calendar across all jurisdictions. Response:
{
  "data": [
    {
      "id": "fil_001",
      "businessId": "bus_abc123",
      "countryCode": "MX",
      "filingTypeId": "ft_mx_isr_monthly",
      "filingTypeName": "ISR Withholding",
      "authorityName": "SAT",
      "status": "pending",
      "period": { "start": "2024-06-01", "end": "2024-06-30", "label": "June 2024" },
      "dueAt": "2024-07-17",
      "workerCount": 12,
      "createdAt": "2024-07-01T00:00:00Z"
    },
    {
      "id": "fil_002",
      "businessId": "bus_abc123",
      "countryCode": "MX",
      "filingTypeId": "ft_mx_imss_bimonthly",
      "filingTypeName": "IMSS Contributions",
      "authorityName": "IMSS",
      "status": "blocked",
      "period": { "start": "2024-04-01", "end": "2024-06-30", "label": "Q2 2024" },
      "dueAt": "2024-07-17",
      "workerCount": 12,
      "createdAt": "2024-07-01T00:00:00Z"
    }
  ],
  "summary": {
    "total": 4,
    "pending": 2,
    "inReview": 0,
    "approved": 0,
    "submitted": 0,
    "accepted": 0,
    "blocked": 1,
    "cancelled": 0,
    "rejected": 0
  }
}
The summary object provides a quick overview of your compliance posture. Use blocked to surface filings that need attention.

Next Steps

The Full Loop

Walk through the complete calculate, file, remit, prove cycle

Statutory API Reference

Full endpoint documentation