Guider
Kom igång
Den här guiden tar dig från ingenting till en bokförd verifikation via API:t. Du behöver ett företag i NONOX där du är ägare eller administratör, och en passkey på ditt konto. Testa gärna i ett eget företag först; det finns ännu ingen separat testmiljö.
1. Slå på NONOX Connect
API:t är en modul och är avstängt från början. Öppna Inställningar → Moduler och slå på NONOX Connect. Så länge modulen är avstängd svarar varje anrop för företaget 404, som om API:t inte fanns.
Under modulens inställningar kan företaget också begränsa vilka appar som får ansluta och vilka IP-adresser som får anropa API:t.
2. Skapa en API-nyckel
För ett eget skript är en API-nyckel det enklaste. Öppna Anslutningar och skapa en nyckel med:
- ett namn, till exempel "Testskript";
- behörigheterna
vouchers:view,vouchers:createochvouchers:post; - ett slutdatum (obligatoriskt, högst ett år bort).
Bekräfta med din passkey. Nyckeln börjar med nnx_ och visas en gång; kopiera den direkt. Lägg den i en miljövariabel så att den inte hamnar i koden:
export NONOX_TOKEN="nnx_..."Ska ett program som många företag använder ansluta, använd OAuth i stället: Autentisering (OAuth).
3. Se vilket företag nyckeln gäller
GET /company kräver ingen särskild behörighet och svarar med företaget och nyckeln. Det är ett bra första anrop för att se att allt fungerar.
curl "https://nonox.app/api/v1/company" \
-H "Authorization: Bearer $NONOX_TOKEN" \
-H "Accept: application/json"use Illuminate\Support\Facades\Http;
$response = Http::withToken(config('services.nonox.token'))
->acceptJson()
->get('https://nonox.app/api/v1/company');
$response->throw();
$data = $response->json('data');$client = new \GuzzleHttp\Client(['timeout' => 30]);
$response = $client->request('GET', 'https://nonox.app/api/v1/company', [
'headers' => [
'Authorization' => 'Bearer '.getenv('NONOX_TOKEN'),
'Accept' => 'application/json',
],
]);
$data = json_decode((string) $response->getBody(), true, flags: JSON_THROW_ON_ERROR)['data'];const response = await fetch('https://nonox.app/api/v1/company', {
headers: {
Authorization: `Bearer ${process.env.NONOX_TOKEN}`,
Accept: 'application/json',
},
});
if (!response.ok) {
const problem = await response.json();
throw new Error(`${problem.code}: ${problem.detail}`);
}
const { data } = await response.json();import os
import requests
response = requests.get(
"https://nonox.app/api/v1/company",
headers={
"Authorization": f"Bearer {os.environ['NONOX_TOKEN']}",
"Accept": "application/json",
},
timeout=30,
)
response.raise_for_status()
data = response.json()["data"]4. Skapa ett utkast
En verifikation skapas först som utkast. Belopp anges i hela öre: 125000 är 1 250,00 kr. Raderna kontrolleras som i appen (konton som finns och är aktiva, debet eller kredit på varje rad); balansen kontrolleras när utkastet bokförs.
Varje POST kräver en Idempotency-Key, så att ett nytt försök efter ett nätverksfel aldrig skapar två utkast. Läs mer i Idempotens.
curl -X POST "https://nonox.app/api/v1/vouchers" \
-H "Authorization: Bearer $NONOX_TOKEN" \
-H "Accept: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"voucher_date": "2026-03-02",
"description": "Kontantförsäljning",
"series": "A",
"rows": [
{
"account": 1930,
"debit_ore": 125000
},
{
"account": 3001,
"credit_ore": 100000
},
{
"account": 2611,
"credit_ore": 25000
}
]
}'use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;
$response = Http::withToken(config('services.nonox.token'))
->acceptJson()
->withHeaders(['Idempotency-Key' => (string) Str::uuid()])
->post('https://nonox.app/api/v1/vouchers', [
'voucher_date' => '2026-03-02',
'description' => 'Kontantförsäljning',
'series' => 'A',
'rows' => [
[
'account' => 1930,
'debit_ore' => 125000,
],
[
'account' => 3001,
'credit_ore' => 100000,
],
[
'account' => 2611,
'credit_ore' => 25000,
],
],
]);
$response->throw();
$data = $response->json('data');$client = new \GuzzleHttp\Client(['timeout' => 30]);
$response = $client->request('POST', 'https://nonox.app/api/v1/vouchers', [
'headers' => [
'Authorization' => 'Bearer '.getenv('NONOX_TOKEN'),
'Accept' => 'application/json',
'Idempotency-Key' => bin2hex(random_bytes(16)),
],
'json' => [
'voucher_date' => '2026-03-02',
'description' => 'Kontantförsäljning',
'series' => 'A',
'rows' => [
[
'account' => 1930,
'debit_ore' => 125000,
],
[
'account' => 3001,
'credit_ore' => 100000,
],
[
'account' => 2611,
'credit_ore' => 25000,
],
],
],
]);
$data = json_decode((string) $response->getBody(), true, flags: JSON_THROW_ON_ERROR)['data'];const response = await fetch('https://nonox.app/api/v1/vouchers', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.NONOX_TOKEN}`,
Accept: 'application/json',
'Idempotency-Key': crypto.randomUUID(),
'Content-Type': 'application/json',
},
body: JSON.stringify({
"voucher_date": "2026-03-02",
"description": "Kontantförsäljning",
"series": "A",
"rows": [
{
"account": 1930,
"debit_ore": 125000
},
{
"account": 3001,
"credit_ore": 100000
},
{
"account": 2611,
"credit_ore": 25000
}
]
}),
});
if (!response.ok) {
const problem = await response.json();
throw new Error(`${problem.code}: ${problem.detail}`);
}
const { data } = await response.json();import os
import uuid
import requests
response = requests.post(
"https://nonox.app/api/v1/vouchers",
headers={
"Authorization": f"Bearer {os.environ['NONOX_TOKEN']}",
"Accept": "application/json",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"voucher_date": "2026-03-02",
"description": "Kontantförsäljning",
"series": "A",
"rows": [
{
"account": 1930,
"debit_ore": 125000,
},
{
"account": 3001,
"credit_ore": 100000,
},
{
"account": 2611,
"credit_ore": 25000,
},
],
},
timeout=30,
)
response.raise_for_status()
data = response.json()["data"]Svaret är 201 Created med utkastet. Spara data.id.
5. Bokför utkastet
Bokföringen ger verifikationen nästa nummer i serien utan luckor, kontrollerar att den balanserar och att datumet ligger i ett öppet räkenskapsår utanför låsta perioder, och skriver behandlingshistorik. Det går inte att ångra: en bokförd verifikation kan bara rättas med en rättelseverifikation.
curl -X POST "https://nonox.app/api/v1/vouchers/0b9f3c1e-6a2d-4f7b-9c8e-1d2a3b4c5d6e/post" \
-H "Authorization: Bearer $NONOX_TOKEN" \
-H "Accept: application/json" \
-H "Idempotency-Key: $(uuidgen)"use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;
$response = Http::withToken(config('services.nonox.token'))
->acceptJson()
->withHeaders(['Idempotency-Key' => (string) Str::uuid()])
->post('https://nonox.app/api/v1/vouchers/0b9f3c1e-6a2d-4f7b-9c8e-1d2a3b4c5d6e/post');
$response->throw();
$data = $response->json('data');$client = new \GuzzleHttp\Client(['timeout' => 30]);
$response = $client->request('POST', 'https://nonox.app/api/v1/vouchers/0b9f3c1e-6a2d-4f7b-9c8e-1d2a3b4c5d6e/post', [
'headers' => [
'Authorization' => 'Bearer '.getenv('NONOX_TOKEN'),
'Accept' => 'application/json',
'Idempotency-Key' => bin2hex(random_bytes(16)),
],
]);
$data = json_decode((string) $response->getBody(), true, flags: JSON_THROW_ON_ERROR)['data'];const response = await fetch('https://nonox.app/api/v1/vouchers/0b9f3c1e-6a2d-4f7b-9c8e-1d2a3b4c5d6e/post', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.NONOX_TOKEN}`,
Accept: 'application/json',
'Idempotency-Key': crypto.randomUUID(),
},
});
if (!response.ok) {
const problem = await response.json();
throw new Error(`${problem.code}: ${problem.detail}`);
}
const { data } = await response.json();import os
import uuid
import requests
response = requests.post(
"https://nonox.app/api/v1/vouchers/0b9f3c1e-6a2d-4f7b-9c8e-1d2a3b4c5d6e/post",
headers={
"Authorization": f"Bearer {os.environ['NONOX_TOKEN']}",
"Accept": "application/json",
"Idempotency-Key": str(uuid.uuid4()),
},
timeout=30,
)
response.raise_for_status()
data = response.json()["data"]6. Läs tillbaka
Lista bokförda verifikationer, eller hämta bara det som ändrats sedan förra gången med updated_since. Se Sidindelning och synk.
curl "https://nonox.app/api/v1/vouchers?limit=50&updated_since=2026-03-01T00%3A00%3A00%2B01%3A00" \
-H "Authorization: Bearer $NONOX_TOKEN" \
-H "Accept: application/json"use Illuminate\Support\Facades\Http;
$response = Http::withToken(config('services.nonox.token'))
->acceptJson()
->get('https://nonox.app/api/v1/vouchers', [
'limit' => 50,
'updated_since' => '2026-03-01T00:00:00+01:00',
]);
$response->throw();
$data = $response->json('data');$client = new \GuzzleHttp\Client(['timeout' => 30]);
$response = $client->request('GET', 'https://nonox.app/api/v1/vouchers', [
'headers' => [
'Authorization' => 'Bearer '.getenv('NONOX_TOKEN'),
'Accept' => 'application/json',
],
'query' => [
'limit' => 50,
'updated_since' => '2026-03-01T00:00:00+01:00',
],
]);
$data = json_decode((string) $response->getBody(), true, flags: JSON_THROW_ON_ERROR)['data'];const url = new URL('https://nonox.app/api/v1/vouchers');
url.searchParams.set('limit', '50');
url.searchParams.set('updated_since', '2026-03-01T00:00:00+01:00');
const response = await fetch(url, {
headers: {
Authorization: `Bearer ${process.env.NONOX_TOKEN}`,
Accept: 'application/json',
},
});
if (!response.ok) {
const problem = await response.json();
throw new Error(`${problem.code}: ${problem.detail}`);
}
const { data } = await response.json();import os
import requests
response = requests.get(
"https://nonox.app/api/v1/vouchers",
headers={
"Authorization": f"Bearer {os.environ['NONOX_TOKEN']}",
"Accept": "application/json",
},
params={
"limit": 50,
"updated_since": "2026-03-01T00:00:00+01:00",
},
timeout=30,
)
response.raise_for_status()
data = response.json()["data"]När något går fel
Alla fel kommer som application/problem+json med en stabil code och en svensk förklaring i detail. Styr alltid på code. Saknar nyckeln en behörighet kommer 403 insufficient_scope med required_scopes. Alla koder finns i Fel.
Nästa steg
- Behörigheter: vilka scopes som öppnar vilka anrop.
- API-referensen: varje anrop med parametrar, scheman och exempel.
- Gränser för anrop: hur många anrop per minut som går.