Connections
Connections link a company to a country’s government e-invoicing system. Each connection manages the authentication state (OAuth tokens, certificates) needed to submit invoices to that country.
A company must have an active connection for a country before you can submit invoices to that country.
Connection object
Section titled “Connection object”{ "id": "conn_a1b2c3d4e5f6", "companyId": "comp_a1b2c3d4e5f6", "countryCode": "RO", "status": "active", "tokenExpiresAt": "2025-04-15T10:00:00.000Z", "lastErrorMessage": null, "createdAt": "2025-01-15T10:00:00.000Z"}Fields
Section titled “Fields”| Field | Type | Description |
|---|---|---|
id | string | Unique connection identifier |
companyId | string | The company this connection belongs to |
countryCode | string | ISO 3166-1 alpha-2 country code |
status | string | Connection status (see below) |
tokenExpiresAt | string|null | When the current auth token expires (ISO 8601) |
lastErrorMessage | string|null | Most recent error message, if any |
createdAt | string | ISO 8601 creation timestamp |
authorizationUrl | string | OAuth URL to redirect the user (only on creation, country-dependent) |
Connection statuses
Section titled “Connection statuses”| Status | Description |
|---|---|
pending_setup | Connection created, waiting for OAuth authorization or certificate upload |
active | Connection is live and can submit invoices |
expired | Auth token has expired and needs to be refreshed |
error | Connection encountered an error (see lastErrorMessage) |
Create a connection
Section titled “Create a connection”POST /v1/connectionsInitializes a connection between a company and a country’s government e-invoicing system. The response depends on the country:
- Romania (RO): Returns an
authorizationUrlfor the ANAF OAuth2 flow. Redirect the user to this URL to authorize access. - Italy (IT): Returns setup instructions for SDI accreditation.
- Other countries: Behavior varies by country requirements.
If an active connection already exists for the company and country, the existing connection is returned.
Request body
Section titled “Request body”| Field | Type | Required | Description |
|---|---|---|---|
companyId | string | Yes | Company ID to connect |
countryCode | string | Yes | Target country code (RO, IT, BE, PL, FR, DE) |
Example request
Section titled “Example request”curl -X POST https://api.getmandato.dev/v1/connections \ -H "Authorization: Bearer sk_test_your_key" \ -H "Content-Type: application/json" \ -d '{ "companyId": "comp_a1b2c3d4e5f6", "countryCode": "RO" }'Example response (201 Created) — Romania
Section titled “Example response (201 Created) — Romania”For Romania, the response includes an OAuth authorization URL:
{ "data": { "id": "conn_a1b2c3d4e5f6", "companyId": "comp_a1b2c3d4e5f6", "countryCode": "RO", "status": "pending_setup", "tokenExpiresAt": null, "lastErrorMessage": null, "createdAt": "2025-01-15T10:00:00.000Z", "authorizationUrl": "https://logincert.anaf.ro/anaf-oauth2/v1/authorize?response_type=code&client_id=abc123&redirect_uri=https%3A%2F%2Fapi.getmandato.dev%2Fv1%2Fcallbacks%2Fanaf&state=conn_a1b2c3d4e5f6" }}OAuth2 flow (Romania)
Section titled “OAuth2 flow (Romania)”The ANAF OAuth2 flow works as follows:
- Call
POST /v1/connectionswithcountryCode: "RO"to get theauthorizationUrl - Redirect the user to the authorization URL
- The user authenticates with their ANAF digital certificate (USB token or cloud cert)
- ANAF redirects back to Mandato’s callback endpoint with an authorization code
- Mandato exchanges the code for access and refresh tokens
- The connection status changes from
pending_setuptoactive - A
connection.activewebhook event is fired
// Step 1: Create the connectionconst { data: connection } = await mandato.connections.create({ companyId: "comp_a1b2c3d4e5f6", countryCode: "RO",});
// Step 2: Redirect user to ANAF OAuth// In a web app:window.location.href = connection.authorizationUrl;
// Step 3-7: Mandato handles the callback automatically.// Poll the connection or listen for the webhook:const { data: updated } = await mandato.connections.get(connection.id);console.log(updated.status); // "active" after OAuth completesToken lifecycle
Section titled “Token lifecycle”| Country | Token lifetime | Refresh token lifetime | Auto-refresh |
|---|---|---|---|
| Romania (RO) | 90 days | 365 days | Yes |
| Italy (IT) | N/A (certificate-based) | N/A | N/A |
| Poland (PL) | 24 hours | 30 days | Yes |
Mandato automatically refreshes expiring tokens. If a refresh fails, the connection status changes to expired and a connection.expired webhook event is fired. You must then re-initiate the OAuth flow.
Error responses
Section titled “Error responses”| Status | Type | Description |
|---|---|---|
400 | validation_error | Missing or invalid fields |
404 | not_found | Company not found or belongs to a different account |
List connections
Section titled “List connections”GET /v1/connectionsReturns all connections across all companies in your account.
Example request
Section titled “Example request”curl https://api.getmandato.dev/v1/connections \ -H "Authorization: Bearer sk_test_your_key"Example response
Section titled “Example response”{ "data": [ { "id": "conn_a1b2c3d4e5f6", "companyId": "comp_a1b2c3d4e5f6", "countryCode": "RO", "status": "active", "tokenExpiresAt": "2025-04-15T10:00:00.000Z", "lastErrorMessage": null, "createdAt": "2025-01-15T10:00:00.000Z" }, { "id": "conn_f6e5d4c3b2a1", "companyId": "comp_f6e5d4c3b2a1", "countryCode": "IT", "status": "pending_setup", "tokenExpiresAt": null, "lastErrorMessage": null, "createdAt": "2025-01-20T11:00:00.000Z" } ]}Get a connection
Section titled “Get a connection”GET /v1/connections/:idRetrieves a single connection by ID. Use this to check the current status and token expiration.
Path parameters
Section titled “Path parameters”| Parameter | Type | Description |
|---|---|---|
id | string | Connection ID (e.g., conn_a1b2c3d4e5f6) |
Example request
Section titled “Example request”curl https://api.getmandato.dev/v1/connections/conn_a1b2c3d4e5f6 \ -H "Authorization: Bearer sk_test_your_key"Example response
Section titled “Example response”{ "data": { "id": "conn_a1b2c3d4e5f6", "companyId": "comp_a1b2c3d4e5f6", "countryCode": "RO", "status": "active", "tokenExpiresAt": "2025-04-15T10:00:00.000Z", "lastErrorMessage": null, "createdAt": "2025-01-15T10:00:00.000Z" }}Error responses
Section titled “Error responses”| Status | Type | Description |
|---|---|---|
404 | not_found | Connection not found or belongs to a different account |
Delete a connection
Section titled “Delete a connection”DELETE /v1/connections/:idRemoves a connection. The stored OAuth tokens and certificates are deleted. You will need to re-authorize the connection to submit invoices for that country again.
Path parameters
Section titled “Path parameters”| Parameter | Type | Description |
|---|---|---|
id | string | Connection ID |
Example request
Section titled “Example request”curl -X DELETE https://api.getmandato.dev/v1/connections/conn_a1b2c3d4e5f6 \ -H "Authorization: Bearer sk_test_your_key"Example response
Section titled “Example response”{ "data": { "id": "conn_a1b2c3d4e5f6", "deleted": true }}Error responses
Section titled “Error responses”| Status | Type | Description |
|---|---|---|
404 | not_found | Connection not found or belongs to a different account |