Authentication
Every request to the Mandato API must include a valid API key. Keys are scoped to an account and determine which environment (test or production) the request targets.
API key format
Section titled “API key format”Mandato API keys use a prefix that indicates the environment:
| Prefix | Environment | Description |
|---|---|---|
sk_test_ | Test | Sandbox environment. No real government submissions. |
sk_live_ | Production | Real submissions to government e-invoicing systems. |
A full key looks like this:
sk_test_4f8a9b2c3d1e6f7a8b9c0d1e2f3a4b5csk_live_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6Authentication header
Section titled “Authentication header”Include your API key in the Authorization header as a Bearer token on every request:
curl https://api.getmandato.dev/v1/invoices \ -H "Authorization: Bearer sk_test_your_api_key_here"With the Node.js SDK, pass the key when constructing the client:
import { MandatoClient } from "@getmandato/sdk";
const mandato = new MandatoClient({ apiKey: "sk_test_your_api_key_here",});The SDK automatically includes the Authorization: Bearer header on every request.
Environments
Section titled “Environments”Mandato operates two fully isolated environments. The environment is determined by the API key prefix — there is no separate base URL.
Test environment (sk_test_)
Section titled “Test environment (sk_test_)”- Invoices are validated and converted to XML but not submitted to real government systems
- ANAF, SDI, KSeF, and other connections are simulated
- Useful for integration testing, CI/CD pipelines, and development
- Subject to sandbox limits (50 invoices/month on the free tier)
- Data is retained for 30 days
Production environment (sk_live_)
Section titled “Production environment (sk_live_)”- Invoices are validated, converted, and submitted to real government systems
- Requires active connections with valid OAuth tokens or certificates
- Usage counts toward your plan limits
- Data is retained for the legally required period (10 years for audit logs)
Managing API keys
Section titled “Managing API keys”Create a key via the dashboard
Section titled “Create a key via the dashboard”Log in to the dashboard, navigate to Settings > API Keys, and click Create API Key. Select the environment (test or production) and give it a descriptive name.
Create a key via the API
Section titled “Create a key via the API”You can also create keys programmatically. You need an existing key to authenticate.
const { data: newKey } = await mandato.apiKeys.create({ name: "CI/CD pipeline", environment: "test", expiresAt: "2026-01-01T00:00:00Z", // optional expiration});
// IMPORTANT: The full key is only returned onceconsole.log("New key:", newKey.key);console.log("Key ID:", newKey.id);console.log("Prefix:", newKey.keyPrefix);List existing keys
Section titled “List existing keys”List all keys for your account. The key value is masked — only the prefix is shown.
const { data: keys } = await mandato.apiKeys.list();
for (const key of keys) { console.log(`${key.name} (${key.keyPrefix}...) - ${key.environment}`); console.log(` Created: ${key.createdAt}`); console.log(` Last used: ${key.lastUsedAt ?? "never"}`); console.log(` Expires: ${key.expiresAt ?? "never"}`); console.log(` Revoked: ${key.revokedAt ?? "no"}`);}Revoke a key
Section titled “Revoke a key”Revoked keys are immediately invalidated and cannot be used again.
const { data: result } = await mandato.apiKeys.revoke("key_id_here");console.log("Revoked:", result.revoked); // trueSecurity best practices
Section titled “Security best practices”- Never commit API keys to source control. Use environment variables or a secrets manager.
const mandato = new MandatoClient({ apiKey: process.env.MANDATO_API_KEY!,});-
Use separate keys per environment. Have distinct keys for development, staging, and production.
-
Set expiration dates on keys that are used in automated pipelines or temporary integrations.
-
Revoke compromised keys immediately. If a key is leaked, revoke it through the dashboard or API and create a replacement.
-
Use the minimum number of keys necessary. Each key is a potential attack surface.
Error responses
Section titled “Error responses”If authentication fails, the API returns a 401 status:
{ "error": { "type": "authentication_error", "message": "Invalid API key", "requestId": "req_abc123" }}Common causes:
- Missing
Authorizationheader - Malformed header (must be
Bearer <key>, not just the key) - Revoked or expired key
- Key does not exist
Rate limiting
Section titled “Rate limiting”API keys are rate-limited per account. The current limits are returned in response headers:
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests per minute |
X-RateLimit-Remaining | Requests remaining in current window |
X-RateLimit-Reset | Unix timestamp when the window resets |
Retry-After | Seconds to wait (only on 429 responses) |
If you exceed the rate limit, you receive a 429 Too Many Requests response. The SDK automatically retries with exponential backoff.
Next steps
Section titled “Next steps”- Sandbox — Learn about the test environment and its limits
- API Keys reference — Full API reference for key management
- Error handling — Understanding error responses