Разменяте client_id и client_secret за Bearer токен с валидност един час, само сървър-към-сървър.
← Обратно към API документацията
Първата фактура в 6 стъпки
- Създайте идентификационните данни в панела в Фактуриране → Настройки → API достъп и веднага копирайте client_secret — показва се само веднъж.
- Изпратете POST /v1/auth/token с grant_type client_credentials, client_id и client_secret.
- Получавате access_token, token_type Bearer, expires_in 3600 и списъка с предоставените обхвати.
- Поставете токена в заглавка Authorization: Bearer <access_token> при всяко друго извикване.
- Проверете какво точно сте получили с GET /v1/me: тенант, обхвати и текущите кошници за лимит.
Всички endpoint-и
| Метод | Endpoint | Scope | Idempotency-Key | Заявки / минута |
|---|---|---|---|---|
| POST | /auth/token Размяна на идентификационните данни за токен за достъп | — | — | 120 |
| GET | /me Наемател, scope-ове и текущи лимити | invoices:read | — | 120 |
Какво е 4invoices API
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"
# → наемател, предоставените scope-ове и текущите лимитиjavascript
// Кеширайте токена; не създавайте нов при всяка заявка.
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
Scope-ове
- invoices:read
- invoices:write
- clients:read
- clients:write
- efactura:read
- efactura:submit
Само сървър-към-сървър. Никога не извиквайте API от браузърен JavaScript: client_secret ще стигне до посетителя, а CORS блокира всеки източник.
Грешки
| Статус | Тип | Код |
|---|---|---|
| 401 | authentication_error | invalid_client |
| 401 | authentication_error | token_expired |
| 401 | authentication_error | invalid_token |
| 403 | permission_error | insufficient_scope |
Често срещани грешки
- Токен endpoint-ът има собствен лимит по IP. Един токен на процес, опресняван преди изтичане — не по един на заявка.
- client_secret се съхранява само като хеш; ако го загубите, създавате нови идентификационни данни и отменяте старите.
- Издайте отделни идентификационни данни за ERP системата, магазина и вътрешните скриптове, всеки с минимални обхвати. Отмяната на едните не засяга останалите.
- CORS не допуска нито един браузър origin: API-то е сървър-към-сървър по замисъл.
Въпроси и отговори за разработчици
Какво става, ако client_secret е грешен?
Получавате 401 с code invalid_client. Твърде кратка тайна се отхвърля по-рано, при валидацията, с 422 validation_failed и param client_secret.
Има ли отделна тестова среда?
Не. Има един продукционен хост. Тествайте с проформи (document_kind проформа) и с /invoices/preview-totals, който не изразходва фискален номер.
Мога ли да стесня обхвати на съществуващи идентификационни данни?
Да, от панела. Вече издадените токени запазват обхвати, с които са създадени, до изтичането си — в рамките на един час.