Byt client_id och client_secret mot en Bearer-token som gäller en timme, enbart server-till-server.
← Tillbaka till API-dokumentationen
Din första faktura i 6 steg
- Skapa inloggningsuppgifter i panelen under Fakturering → Inställningar → API-åtkomst och kopiera client_secret direkt — det visas bara en gång.
- Skicka POST /v1/auth/token med grant_type client_credentials, client_id och client_secret.
- Du får tillbaka access_token, token_type Bearer, expires_in 3600 och listan över beviljade scopes.
- Lägg token i en Authorization: Bearer <access_token>-header på varje övrigt anrop.
- Kontrollera vad du faktiskt fick med GET /v1/me: tenant, scopes och de aktuella hastighetsgrupperna.
Alla endpoints
| Metod | Endpoint | Scope | Idempotency-Key | Förfrågningar / minut |
|---|---|---|---|---|
| POST | /auth/token Byt inloggningsuppgifter mot en åtkomsttoken | — | — | 120 |
| GET | /me Tenant, scopes och aktuella gränser | invoices:read | — | 120 |
Vad 4invoices API är
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, beviljade scopes och aktuella hastighetsgrupperjavascript
// Cacha token; skapa inte en ny per anrop.
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
Enbart server-till-server. Anropa aldrig API:t från webbläsarens JavaScript: client_secret skulle nå besökaren, och CORS blockerar ändå varje ursprung.
Fel
| Status | Typ | Kod |
|---|---|---|
| 401 | authentication_error | invalid_client |
| 401 | authentication_error | token_expired |
| 401 | authentication_error | invalid_token |
| 403 | permission_error | insufficient_scope |
Vanliga misstag
- Token-endpointen har en egen gräns per IP. En token per process, förnyad före utgång — inte en per anrop.
- client_secret lagras bara som hash; förlorar du den skapar du nya inloggningsuppgifter och återkallar de gamla.
- Skapa separata inloggningsuppgifter för ERP, butiken och interna skript, var och en med minimala scopes. Att återkalla en påverkar inte de andra.
- CORS tillåter inget webbläsarursprung: API:t är server-till-server by design.
Frågor och svar för utvecklare
Vad händer om client_secret är fel?
Du får 401 med koden invalid_client. Ett för kort secret misslyckas tidigare, vid validering, med 422 validation_failed och param client_secret.
Finns det en separat sandbox?
Nej. Det finns en produktionsvärd. Testa med proformor (document_kind proforma) och med /invoices/preview-totals, som inte förbrukar något fiskalt nummer.
Kan jag minska scopes för en befintlig uppgift?
Ja, från panelen. Tokens som redan utfärdats behåller de scopes de skapades med tills de går ut, inom en timme.