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

# The Full Loop

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

export const ApiExample = ({method = "GET", path, params, body, reference, tenantKey}) => {
  const baseUrl = "https://api.cadanapay.com";
  const query = params ? "?" + Object.entries(params).map(([k, v]) => `${k}=${v}`).join("&") : "";
  const url = `${baseUrl}${path}${query}`;
  const isPlatformPath = (/^\/(v1\/)?platform(\/|$)/).test(path || "");
  const includeTenantKey = tenantKey === undefined ? !isPlatformPath : tenantKey;
  let curl = `curl -X ${method} '${url}' \\\n  -H 'Authorization: Bearer YOUR_API_KEY'`;
  if (includeTenantKey) {
    curl += ` \\\n  -H 'X-MultiTenantKey: YOUR_BUSINESS_TENANT_KEY'`;
  }
  if (body) {
    const formatted = JSON.stringify(body, null, 2);
    curl += ` \\\n  -H 'Content-Type: application/json' \\\n  -d '${formatted}'`;
  }
  return <div>
      <CodeBlock language="bash" filename="bash" wrap>
        {curl}
      </CodeBlock>
      {reference && <div style={{
    marginTop: "-0.5rem",
    marginBottom: "1rem"
  }}>
          <a href={reference} style={{
    fontSize: "0.875rem"
  }}>
            Try it in the playground →
          </a>
        </div>}
    </div>;
};

<Note>
  **Beta** — this functionality is fully supported today: statutory obligations are calculated, withheld, filed, and remitted for you as part of [Cadana's payroll process](/workforce/pay-workers-via-payroll). What's in beta is the standalone API surface on this page, which puts filings and remittances under your direct, self-serve control. Contact Cadana to enable it for your business.
</Note>

Every payroll run triggers statutory obligations -- taxes, social security, housing contributions. The Statutory Compliance API turns these into a four-phase cycle: **calculate, file, remit, prove**. This guide walks through all four phases with a real-world scenario.

## Scenario

Your business `biz_01ABC` runs payroll in Mexico for 15 employees. February 2026 payroll closes on February 28, producing four statutory filings:

| Filing                       | Authority                                   | Due Date       |
| :--------------------------- | :------------------------------------------ | :------------- |
| ISR (Income Tax Withholding) | SAT (Servicio de Administracion Tributaria) | March 17, 2026 |
| IMSS (Social Security)       | IMSS (Instituto Mexicano del Seguro Social) | March 17, 2026 |
| INFONAVIT (Housing Fund)     | INFONAVIT                                   | March 17, 2026 |
| ISN (Payroll Tax)            | State Treasury                              | March 17, 2026 |

***

## Step 1: Batch Create Filings from Payroll

After the payroll run completes, create all required filings for the period in a single call. Cadana automatically determines which filings are required based on the country, business registrations, and employee profiles.

<ApiExample method="POST" path="/v1/statutory/filings/batch" body={{ businessId: "biz_01ABC", periodStart: "2026-02-01", periodEnd: "2026-02-28", payrollRunIds: ["pr_01MNO"] }} reference="/api-reference/statutory/filings/create-all-filings-for-a-period" />

**Response:**

```json theme={null}
{
  "data": [
    { "id": "fil_01JKL" },
    { "id": "fil_02MNO" },
    { "id": "fil_03PQR" },
    { "id": "fil_04STU" }
  ]
}
```

### Filing Detail: ISR

Each filing returns the `breakdown` (the per-contribution lines that sum to the filing total) plus a derived `amounts` rollup. Retrieve the ISR filing to inspect the detail:

<ApiExample method="GET" path="/v1/statutory/filings/fil_01JKL" reference="/api-reference/statutory/filings/get-a-filing" />

**Response:**

```json theme={null}
{
  "id": "fil_01JKL",
  "businessId": "biz_01ABC",
  "source": "cadana",
  "filingTypeId": "ft_mx_isr_monthly",
  "filingTypeName": "ISR Withholding",
  "authorityId": "auth_mx_sat",
  "authorityName": "SAT",
  "countryCode": "MX",
  "period": {
    "start": "2026-02-01",
    "end": "2026-02-28",
    "label": "February 2026"
  },
  "status": "pending",
  "dueAt": "2026-03-17",
  "workerCount": 15,
  "amounts": {
    "currency": "MXN",
    "total": 82345.00
  },
  "breakdown": [
    { "personId": "per_01ABC", "employeeName": "María García López", "amount": 5489.67 },
    { "personId": "per_02DEF", "employeeName": "Juan Pérez Rivera",  "amount": 6121.40 },
    { "personId": "per_03GHI", "employeeName": "Ana Hernández",      "amount": 4998.20 }
  ],
  "payrollRunIds": ["pr_01MNO"],
  "createdAt": 1709280000,
  "updatedAt": 1709280000
}
```

<Note>
  All amounts in the API use regular decimal values (e.g., `82345.00`), not lowest-denomination integers. `amounts.total` is computed server-side from the `breakdown` lines.
</Note>

***

## Step 2: Review and Approve

Before Cadana submits a filing to the authority, it must be approved. This gives your finance team a chance to review the amounts.

### Check Filing Status

<ApiExample method="GET" path="/v1/statutory/filings/fil_01JKL" reference="/api-reference/statutory/filings/get-a-filing" />

### Approve the Filing

Once reviewed, approve it for submission:

<ApiExample method="POST" path="/v1/statutory/filings/fil_01JKL/approve" reference="/api-reference/statutory/filings/approve-a-filing-for-submission" />

The endpoint returns `204 No Content` on success. Fetch the filing to see the updated status:

<ApiExample method="GET" path="/v1/statutory/filings/fil_01JKL" reference="/api-reference/statutory/filings/get-a-filing" />

**Response:**

```json theme={null}
{
  "id": "fil_01JKL",
  "filingTypeId": "ft_mx_isr_monthly",
  "filingTypeName": "ISR Withholding",
  "authorityId": "auth_mx_sat",
  "authorityName": "SAT",
  "status": "approved",
  "dueAt": "2026-03-17",
  "amounts": { "currency": "MXN", "total": 82345.00 },
  "statusHistory": [
    { "from": "pending", "to": "in_review", "timestamp": 1709654400 },
    { "from": "in_review", "to": "approved", "timestamp": 1709656200 }
  ]
}
```

<Warning>
  Once approved, the filing is queued for submission. Review amounts carefully before approving -- reversals require contacting the tax authority directly.
</Warning>

***

## Step 3: Filing Submitted and Accepted

After approval, Cadana submits the filing to the relevant authority. The filing status transitions through `submitted` and then to `accepted` once the authority confirms receipt.

Poll the filing or listen for the `filing.accepted` webhook event:

```json theme={null}
{
  "id": "fil_01JKL",
  "filingTypeId": "ft_mx_isr_monthly",
  "filingTypeName": "ISR Withholding",
  "authorityId": "auth_mx_sat",
  "authorityName": "SAT",
  "status": "accepted",
  "dueAt": "2026-03-17",
  "filingReference": "0123456ABCD7890EF",
  "amounts": { "currency": "MXN", "total": 82345.00 },
  "statusHistory": [
    { "from": "pending", "to": "in_review", "timestamp": 1709654400 },
    { "from": "in_review", "to": "approved", "timestamp": 1709656200 },
    { "from": "approved", "to": "submitted", "timestamp": 1709658000 },
    { "from": "submitted", "to": "accepted", "timestamp": 1709658150 }
  ]
}
```

***

## Step 4: Create Remittance

Once a filing is accepted, pay the authority. Cadana handles FX conversion and routes the payment to the correct government account.

<ApiExample method="POST" path="/v1/statutory/remittances" body={{ businessId: "biz_01ABC", countryCode: "MX", filingIds: ["fil_01JKL"], fundFromCurrency: "USD" }} reference="/api-reference/statutory/remittances/create-a-remittance" />

**Response:**

```json theme={null}
{
  "id": "rem_01STU"
}
```

<Tip>
  When you fund from a different currency than the filing currency, Cadana automatically converts at the current rate. The `fundedAmount` shows exactly how much will be debited from your wallet, and `fxRate` shows the conversion rate applied. You can also fund in the local currency by setting `fundFromCurrency` to `"MXN"`.
</Tip>

***

## Step 5: Proof of Payment

After the remittance is processed, retrieve the proof of payment for your records.

### Check Remittance Status

<ApiExample method="GET" path="/v1/statutory/remittances/rem_01STU" reference="/api-reference/statutory/remittances/get-a-remittance" />

**Response:**

```json theme={null}
{
  "id": "rem_01STU",
  "businessId": "biz_01ABC",
  "filingIds": ["fil_01JKL"],
  "status": "completed",
  "countryCode": "MX",
  "amount": 82345.00,
  "fundedAmount": 4574.80,
  "fundedCurrency": "USD",
  "fxRate": 18.001,
  "authorityId": "auth_mx_sat",
  "authorityName": "SAT",
  "paymentMethod": "local_rails",
  "paymentReference": "REF-2026-0310-001",
  "receiptUrl": "https://api.cadanapay.com/v1/statutory/remittances/rem_01STU/receipt",
  "createdAt": "2026-03-10T09:00:00Z"
}
```

### Download Receipt

<ApiExample method="GET" path="/v1/statutory/remittances/rem_01STU/receipt" reference="/api-reference/statutory/remittances/download-remittance-receipt" />

The receipt is returned as a PDF document containing the authority's confirmation of payment, the amount, and the filing reference number.

***

## Step 6: Verify the Loop is Closed

After processing all four filings, check the overall status for the period:

<ApiExample method="GET" path="/v1/statutory/filings" params={{ businessId: "biz_01ABC", countryCode: "MX" }} reference="/api-reference/statutory/filings/list-filings" />

**Response:**

```json theme={null}
{
  "data": [
    {
      "id": "fil_01JKL",
      "businessId": "biz_01ABC",
      "countryCode": "MX",
      "source": "cadana",
      "filingTypeId": "ft_mx_isr_monthly",
      "filingTypeName": "ISR Withholding",
      "authorityName": "SAT",
      "status": "accepted",
      "period": { "start": "2026-02-01", "end": "2026-02-28", "label": "February 2026" },
      "dueAt": "2026-03-17",
      "workerCount": 15,
      "createdAt": 1709280000,
      "updatedAt": 1709658150
    },
    {
      "id": "fil_02MNO",
      "businessId": "biz_01ABC",
      "countryCode": "MX",
      "source": "cadana",
      "filingTypeId": "ft_mx_imss_bimonthly",
      "filingTypeName": "IMSS Contributions",
      "authorityName": "IMSS",
      "status": "accepted",
      "period": { "start": "2026-02-01", "end": "2026-02-28", "label": "February 2026" },
      "dueAt": "2026-03-17",
      "workerCount": 15,
      "createdAt": 1709280000,
      "updatedAt": 1709658200
    },
    {
      "id": "fil_03PQR",
      "businessId": "biz_01ABC",
      "countryCode": "MX",
      "source": "cadana",
      "filingTypeId": "ft_mx_infonavit_bimonthly",
      "filingTypeName": "INFONAVIT Contributions",
      "authorityName": "INFONAVIT",
      "status": "approved",
      "period": { "start": "2026-02-01", "end": "2026-02-28", "label": "February 2026" },
      "dueAt": "2026-03-17",
      "workerCount": 15,
      "createdAt": 1709280000,
      "updatedAt": 1709656200
    },
    {
      "id": "fil_04STU",
      "businessId": "biz_01ABC",
      "countryCode": "MX",
      "source": "cadana",
      "filingTypeId": "ft_mx_isn_monthly",
      "filingTypeName": "ISN Payroll Tax",
      "authorityName": "State",
      "status": "pending",
      "period": { "start": "2026-02-01", "end": "2026-02-28", "label": "February 2026" },
      "dueAt": "2026-03-17",
      "workerCount": 15,
      "createdAt": 1709280000,
      "updatedAt": 1709280000
    }
  ],
  "summary": {
    "total": 4,
    "pending": 1,
    "inReview": 0,
    "approved": 1,
    "submitted": 0,
    "accepted": 2,
    "blocked": 0,
    "cancelled": 0,
    "rejected": 0
  }
}
```

***

## Full Timeline

Here is the complete sequence of events for the ISR filing, from payroll close to proof of payment:

| Date   | Event                                               | Status       |
| :----- | :-------------------------------------------------- | :----------- |
| Mar 1  | Payroll run `pr_01MNO` closes; batch filing created | `pending`    |
| Mar 5  | Finance team reviews and approves ISR filing        | `approved`   |
| Mar 5  | Cadana submits to SAT                               | `submitted`  |
| Mar 5  | SAT confirms receipt                                | `accepted`   |
| Mar 10 | Remittance created; USD converted to MXN            | `processing` |
| Mar 10 | Payment delivered to SAT                            | `completed`  |
| Mar 10 | Receipt downloaded for records                      | --           |

***

## Alternative: External Payroll

If you run payroll outside of Cadana but still want Cadana to file with the authorities, provide each filing's `breakdown` explicitly instead of referencing a payroll run. Cadana will still drive the `pending → approved → submitted → accepted` lifecycle for you:

<ApiExample
  method="POST"
  path="/v1/statutory/filings/batch"
  body={{
businessId: "biz_01ABC",
periodStart: "2026-02-01",
periodEnd: "2026-02-28",
countryCode: "MX",
filings: [
  {
    filingTypeId: "ft_mx_isr_monthly",
    source: "cadana",
    currency: "MXN",
    breakdown: [
      { personId: "per_01ABC", amount: 5489.67 },
      { personId: "per_02DEF", amount: 6121.40 },
      { personId: "per_03GHI", amount: 4998.20 }
    ]
  },
  {
    filingTypeId: "ft_mx_imss_bimonthly",
    source: "cadana",
    currency: "MXN",
    breakdown: [
      { personId: "per_01ABC", amount: 3595.12 },
      { personId: "per_02DEF", amount: 4012.40 },
      { personId: "per_03GHI", amount: 3210.55 }
    ]
  }
]
}}
  reference="/api-reference/statutory/filings/create-all-filings-for-a-period"
/>

<Info>
  This is the **unbundled** model — you provide the amounts, Cadana handles filing, remittance, and proof. Use `payrollRunIds` when Cadana runs your payroll (bundled), or `filings` when you calculate externally (unbundled). Both follow the same approve-submit-accept cycle.

  If you've already filed with the authority yourself and just need remittance, set `source: "external"` on every entry (a batch must be all `cadana` or all `external` — mixing sources returns `400`) and provide a `filingReference` per entry — those filings are created directly in `accepted`. See the [Remittance walkthrough](/statutory/remittance#remittance-only-walkthrough-external-filing) for the full flow.
</Info>

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Getting Started" icon="rocket" href="/statutory/getting-started">
    Discover jurisdictions, required fields, and outstanding requirements
  </Card>

  <Card title="Statutory API Reference" icon="code" href="/api-reference/statutory">
    Full endpoint documentation for filings, remittances, and requirements
  </Card>
</CardGroup>
