Hoppa till innehållet

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:create och vouchers: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:

Shell
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
curl "https://nonox.app/api/v1/company" \
  -H "Authorization: Bearer $NONOX_TOKEN" \
  -H "Accept: application/json"
PHP (Laravel)
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');
PHP (Guzzle)
$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'];
JavaScript
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();
Python
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
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
    }
  ]
}'
PHP (Laravel)
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');
PHP (Guzzle)
$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'];
JavaScript
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();
Python
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
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)"
PHP (Laravel)
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');
PHP (Guzzle)
$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'];
JavaScript
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();
Python
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
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"
PHP (Laravel)
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');
PHP (Guzzle)
$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'];
JavaScript
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();
Python
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