Byt client_id og client_secret til et Bearer-token, der er gyldigt i én time, kun server-til-server.
← Tilbage til API-dokumentationen
Din første faktura i 6 trin
- Opret legitimationsoplysninger i panelet under Fakturering → Indstillinger → API-adgang, og kopiér client_secret med det samme — det vises kun én gang.
- Send POST /v1/auth/token med grant_type client_credentials, client_id og client_secret.
- Du får access_token, token_type Bearer, expires_in 3600 og listen over tildelte scopes tilbage.
- Læg tokenet i en Authorization: Bearer <access_token>-header på alle andre kald.
- Kontrollér, hvad du faktisk fik, med GET /v1/me: tenant, scopes og de aktuelle hastighedskvoter.
Alle endpoints
| Metode | Endpoint | Scope | Idempotency-Key | Anmodninger / minut |
|---|---|---|---|---|
| POST | /auth/token Byt legitimationsoplysninger til et adgangstoken | — | — | 120 |
| GET | /me Tenant, scopes og aktuelle grænser | invoices:read | — | 120 |
Hvad 4invoices API'et er
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"
# → tenant, tildelte scopes og de aktuelle hastighedskvoterjavascript
// Gem tokenet i cache; udsted ikke et nyt pr. anmodning.
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
Scopes
- invoices:read
- invoices:write
- clients:read
- clients:write
- efactura:read
- efactura:submit
Kun server-til-server. Kald aldrig API'et fra browser-JavaScript: client_secret ville nå den besøgende, og CORS blokerer alligevel alle origins.
Fejl
| Status | Type | Kode |
|---|---|---|
| 401 | authentication_error | invalid_client |
| 401 | authentication_error | token_expired |
| 401 | authentication_error | invalid_token |
| 403 | permission_error | insufficient_scope |
Almindelige fejl
- Token-endpointet har sin egen grænse pr. IP. Ét token pr. proces, fornyet før udløb — ikke ét pr. anmodning.
- client_secret gemmes kun som hash; mister du det, opretter du nye legitimationsoplysninger og tilbagekalder de gamle.
- Opret separate legitimationsoplysninger til ERP-systemet, webshoppen og interne scripts, hver med minimale scopes. Tilbagekaldelse af én påvirker ikke de andre.
- CORS tillader ingen browser-origin: API'et er server-til-server by design.
Spørgsmål og svar for udviklere
Hvad sker der, hvis client_secret er forkert?
Du får 401 med koden invalid_client. Et for kort secret fejler tidligere, ved validering, med 422 validation_failed og param client_secret.
Findes der en separat sandbox?
Nej. Der er én produktionsvært. Test med proformaer (document_kind proforma) og med /invoices/preview-totals, som ikke forbruger et fiskalt nummer.
Kan jeg indskrænke scopes på eksisterende legitimationsoplysninger?
Ja, fra panelet. Tokens, der allerede er udstedt, beholder de scopes, de blev oprettet med, indtil de udløber inden for en time.