Canvies client_id i client_secret per un token Bearer d'una hora, només de servidor a servidor.
← Torna a la documentació de l'API
La teva primera factura en 6 passos
- Crea la credencial al panell a Facturació → Configuració → Accés API i copia el client_secret de seguida — es mostra una sola vegada.
- Envia POST /v1/auth/token amb grant_type client_credentials, client_id i client_secret.
- Reps access_token, token_type Bearer, expires_in 3600 i la llista d'àmbits atorgats.
- Posa el token en una capçalera Authorization: Bearer <access_token> a cada altra crida.
- Comprova què has obtingut amb GET /v1/me: client, àmbits i grups de límits actuals.
Tots els punts finals
| Mètode | Punt final | Àmbit | Idempotency-Key | Peticions / minut |
|---|---|---|---|---|
| POST | /auth/token Canvia les credencials per un token d'accés | — | — | 120 |
| GET | /me Client, àmbits i límits actuals | invoices:read | — | 120 |
Què és l'API de 4invoices
bash
curl -sS -X POST https://api.4invoices.net/v1/auth/token \
-H 'Content-Type: application/json' \
-d '{
"grant_type": "client_credentials",
"client_id": "cli_XXXXXXXXXXXX",
"client_secret": "sec_XXXXXXXXXXXXXXXXXXXX"
}'
# → {"access_token":"eyJ...","token_type":"Bearer","expires_in":3600,
# "scope":"invoices:read invoices:write efactura:submit"}bash
curl -sS https://api.4invoices.net/v1/me \
-H "Authorization: Bearer $ACCESS_TOKEN"
# → client, àmbits atorgats i grups de límits de peticions actualsjavascript
// Guarda el token a la memòria cau; no en generis un per cada petició.
let cached = { token: "", expiresAt: 0 };
async function getToken() {
if (cached.token && Date.now() < cached.expiresAt - 60_000) return cached.token;
const res = await fetch("https://api.4invoices.net/v1/auth/token", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
grant_type: "client_credentials",
client_id: process.env.FOURINVOICES_CLIENT_ID,
client_secret: process.env.FOURINVOICES_CLIENT_SECRET,
}),
});
if (!res.ok) throw new Error(`token ${res.status}`);
const data = await res.json();
cached = { token: data.access_token, expiresAt: Date.now() + data.expires_in * 1000 };
return cached.token;
}https://api.4invoices.net/v1 · https://api.4invoices.net/v1/openapi.json
Àmbits
- invoices:read
- invoices:write
- clients:read
- clients:write
- efactura:read
- efactura:submit
Només de servidor a servidor. Mai no cridis l'API des del JavaScript del navegador: el client_secret arribaria al visitant, i de totes maneres CORS bloqueja tots els orígens.
Errors
| Estat | Tipus | Codi |
|---|---|---|
| 401 | authentication_error | invalid_client |
| 401 | authentication_error | token_expired |
| 401 | authentication_error | invalid_token |
| 403 | permission_error | insufficient_scope |
Errors habituals
- El punt final del token té el seu propi límit per IP. Un token per procés, renovat abans que caduqui — no un per petició.
- El client_secret es guarda només com a hash; si el perds, crees una nova credencial i revoques la vella.
- Emet credencials separades per a l'ERP, la botiga i els scripts interns, cadascuna amb àmbits mínims. Revocar-ne una no afecta les altres.
- CORS no permet cap origen del navegador: l'API és de servidor a servidor per disseny.
Preguntes i respostes per a desenvolupadors
Què passa si el client_secret és incorrecte?
Reps un 401 amb el codi invalid_client. Un secret massa curt falla abans, a la validació, amb 422 validation_failed i param client_secret.
Hi ha un sandbox separat?
No. Hi ha un únic host de producció. Prova amb proformes (document_kind proforma) i amb /invoices/preview-totals, que no consumeix cap número fiscal.
Puc reduir els àmbits d'una credencial existent?
Sí, des del panell. Els tokens ja emesos conserven els àmbits amb què es van crear fins que caduquin, en el termini d'una hora.