Skip to content

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.

{
"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"
}
FieldTypeDescription
idstringUnique connection identifier
companyIdstringThe company this connection belongs to
countryCodestringISO 3166-1 alpha-2 country code
statusstringConnection status (see below)
tokenExpiresAtstring|nullWhen the current auth token expires (ISO 8601)
lastErrorMessagestring|nullMost recent error message, if any
createdAtstringISO 8601 creation timestamp
authorizationUrlstringOAuth URL to redirect the user (only on creation, country-dependent)
StatusDescription
pending_setupConnection created, waiting for OAuth authorization or certificate upload
activeConnection is live and can submit invoices
expiredAuth token has expired and needs to be refreshed
errorConnection encountered an error (see lastErrorMessage)

POST /v1/connections

Initializes a connection between a company and a country’s government e-invoicing system. The response depends on the country:

  • Romania (RO): Returns an authorizationUrl for 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.

FieldTypeRequiredDescription
companyIdstringYesCompany ID to connect
countryCodestringYesTarget country code (RO, IT, BE, PL, FR, DE)
Terminal window
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"
}
}

The ANAF OAuth2 flow works as follows:

  1. Call POST /v1/connections with countryCode: "RO" to get the authorizationUrl
  2. Redirect the user to the authorization URL
  3. The user authenticates with their ANAF digital certificate (USB token or cloud cert)
  4. ANAF redirects back to Mandato’s callback endpoint with an authorization code
  5. Mandato exchanges the code for access and refresh tokens
  6. The connection status changes from pending_setup to active
  7. A connection.active webhook event is fired
// Step 1: Create the connection
const { 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 completes
CountryToken lifetimeRefresh token lifetimeAuto-refresh
Romania (RO)90 days365 daysYes
Italy (IT)N/A (certificate-based)N/AN/A
Poland (PL)24 hours30 daysYes

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.

StatusTypeDescription
400validation_errorMissing or invalid fields
404not_foundCompany not found or belongs to a different account

GET /v1/connections

Returns all connections across all companies in your account.

Terminal window
curl https://api.getmandato.dev/v1/connections \
-H "Authorization: Bearer sk_test_your_key"
{
"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 /v1/connections/:id

Retrieves a single connection by ID. Use this to check the current status and token expiration.

ParameterTypeDescription
idstringConnection ID (e.g., conn_a1b2c3d4e5f6)
Terminal window
curl https://api.getmandato.dev/v1/connections/conn_a1b2c3d4e5f6 \
-H "Authorization: Bearer sk_test_your_key"
{
"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"
}
}
StatusTypeDescription
404not_foundConnection not found or belongs to a different account

DELETE /v1/connections/:id

Removes 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.

ParameterTypeDescription
idstringConnection ID
Terminal window
curl -X DELETE https://api.getmandato.dev/v1/connections/conn_a1b2c3d4e5f6 \
-H "Authorization: Bearer sk_test_your_key"
{
"data": {
"id": "conn_a1b2c3d4e5f6",
"deleted": true
}
}
StatusTypeDescription
404not_foundConnection not found or belongs to a different account