Skip to content

API reference

Payments

Incoming and outgoing payments, read-only.

List incoming payments

GET /payments listPayments

Money received for customer invoices, with the voucher that booked each. Read-only; a payment is registered on its invoice.

Scope

invoices:view

Parameters

  • limit integer query

    Page size, 1–200.

    Default: 50 · minimum 1 · maximum 200

  • cursor string query

    Opaque cursor from meta.next_cursor of the previous page.

    at most 2000 characters

  • updated_since string (date-time) query

    Only records whose updated_at is strictly later than this ISO 8601 time. Lists are ordered by updated_at, then id, so a sync stores the updated_at of the last record it has seen and passes it next time, walking all pages with `cursor`.

    Example: 2026-03-01T00:00:00+01:00

  • date_from string (date) query

    Paid on or after this date.

  • date_to string (date) query

    Paid on or before this date.

Responses

200 OK – A page of payments.

application/jsonobject

  • data array<InvoicePayment> required
    9 fields · each item
    • id integer
    • invoice_id string (uuid)
    • paid_on string (date)
    • amount_ore integer
    • currency string
    • account integer nullable

      Bank account the money came in on.

    • voucher_id string (uuid)
    • created_at string (date-time)
    • updated_at string (date-time)
  • meta ListMeta required
    3 fields
    • limit integer required
    • next_cursor string required nullable

      Opaque; pass as `cursor` for the next page. null on the last page.

    • has_more boolean required

Response headers: X-Request-Id, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset

401 Unauthorized – Missing, invalid, expired or revoked token or API key. Also returned when the person behind the credential has left the company (an OAuth grant is then revoked for good).

All error codes · application/problem+json

  • unauthenticatedNo valid credential

    Nyckeln eller token saknas, är ogiltig, har gått ut eller har återkallats.

Response headers: X-Request-Id, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset, WWW-Authenticate

403 Forbidden – The credential may not do this: a scope is missing, the granting person no longer has the permission, the address is not allowed, the company is archived (read-only) or no longer allows the app.

All error codes · application/problem+json

  • insufficient_scopeScope missing or permission lost

    Nyckeln eller appen saknar behörigheten vouchers:post, eller så har personen som gav den inte längre den behörigheten i företaget.

  • forbiddenThe action refuses (for example changing a posted voucher)

    Behörighet saknas för det här.

  • ip_not_allowedOutside the IP allowlist

    Företaget tillåter inte anrop från den här adressen.

  • company_archivedWrite to an archived company

    Företaget är arkiverat och kan bara läsas.

  • app_not_allowedThe company no longer allows the app

    Företaget tillåter inte längre den här appen.

Response headers: X-Request-Id, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset

404 Not Found – Not found. Also the answer for another company's ids (existence is never revealed) and for every call while NONOX Connect is turned off for the company.

All error codes · application/problem+json

  • not_foundUnknown id, other company's id, or module off

    Det du söker finns inte.

Response headers: X-Request-Id, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset

429 Too Many Requests – Rate limit exceeded (per credential, per company or per address). Wait Retry-After seconds.

All error codes · application/problem+json

  • rate_limitedOver the limit

    För många anrop. Försök igen om 23 sekunder.

Response headers: X-Request-Id, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset, Retry-After

Code samples

curl
curl "https://nonox.app/api/v1/payments?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/payments', [
        '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/payments', [
    '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/payments');
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/payments",
    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"]

Responses · 200

application/json
{
  "data": [
    {
      "id": 88,
      "invoice_id": "5c2e8a41-7b3d-4f19-a6c2-0e9d8b7a6f54",
      "paid_on": "2026-03-28",
      "amount_ore": 237500,
      "currency": "SEK",
      "account": 1930,
      "voucher_id": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
      "created_at": "2026-03-28T09:12:00+01:00",
      "updated_at": "2026-03-28T09:12:00+01:00"
    }
  ],
  "meta": {
    "limit": 50,
    "next_cursor": null,
    "has_more": false
  }
}

Error

4011 example
No valid credential
{
  "type": "urn:nonox:problem:unauthenticated",
  "title": "Unauthorized",
  "status": 401,
  "code": "unauthenticated",
  "detail": "Nyckeln eller token saknas, är ogiltig, har gått ut eller har återkallats.",
  "instance": "urn:nonox:request:7f3c2a9e-4b1d-4c8e-9a51-2d6f0e8b3c17"
}
4035 examples
Scope missing or permission lost
{
  "type": "urn:nonox:problem:insufficient_scope",
  "title": "Forbidden",
  "status": 403,
  "code": "insufficient_scope",
  "detail": "Nyckeln eller appen saknar behörigheten vouchers:post, eller så har personen som gav den inte längre den behörigheten i företaget.",
  "instance": "urn:nonox:request:7f3c2a9e-4b1d-4c8e-9a51-2d6f0e8b3c17",
  "required_scopes": [
    "vouchers:post"
  ]
}
The action refuses (for example changing a posted voucher)
{
  "type": "urn:nonox:problem:forbidden",
  "title": "Forbidden",
  "status": 403,
  "code": "forbidden",
  "detail": "Behörighet saknas för det här.",
  "instance": "urn:nonox:request:7f3c2a9e-4b1d-4c8e-9a51-2d6f0e8b3c17"
}
Outside the IP allowlist
{
  "type": "urn:nonox:problem:ip_not_allowed",
  "title": "Forbidden",
  "status": 403,
  "code": "ip_not_allowed",
  "detail": "Företaget tillåter inte anrop från den här adressen.",
  "instance": "urn:nonox:request:7f3c2a9e-4b1d-4c8e-9a51-2d6f0e8b3c17"
}
Write to an archived company
{
  "type": "urn:nonox:problem:company_archived",
  "title": "Forbidden",
  "status": 403,
  "code": "company_archived",
  "detail": "Företaget är arkiverat och kan bara läsas.",
  "instance": "urn:nonox:request:7f3c2a9e-4b1d-4c8e-9a51-2d6f0e8b3c17"
}
The company no longer allows the app
{
  "type": "urn:nonox:problem:app_not_allowed",
  "title": "Forbidden",
  "status": 403,
  "code": "app_not_allowed",
  "detail": "Företaget tillåter inte längre den här appen.",
  "instance": "urn:nonox:request:7f3c2a9e-4b1d-4c8e-9a51-2d6f0e8b3c17"
}
4041 example
Unknown id, other company's id, or module off
{
  "type": "urn:nonox:problem:not_found",
  "title": "Not Found",
  "status": 404,
  "code": "not_found",
  "detail": "Det du söker finns inte.",
  "instance": "urn:nonox:request:7f3c2a9e-4b1d-4c8e-9a51-2d6f0e8b3c17"
}
4291 example
Over the limit
{
  "type": "urn:nonox:problem:rate_limited",
  "title": "Too Many Requests",
  "status": 429,
  "code": "rate_limited",
  "detail": "För många anrop. Försök igen om 23 sekunder.",
  "instance": "urn:nonox:request:7f3c2a9e-4b1d-4c8e-9a51-2d6f0e8b3c17"
}

List supplier payments

GET /supplier-payments listSupplierPayments

Money paid for supplier invoices, with the voucher that booked each. Read-only.

Scope

supplier-invoices:create or supplier-invoices:approve or payments:create

Parameters

  • limit integer query

    Page size, 1–200.

    Default: 50 · minimum 1 · maximum 200

  • cursor string query

    Opaque cursor from meta.next_cursor of the previous page.

    at most 2000 characters

  • updated_since string (date-time) query

    Only records whose updated_at is strictly later than this ISO 8601 time. Lists are ordered by updated_at, then id, so a sync stores the updated_at of the last record it has seen and passes it next time, walking all pages with `cursor`.

    Example: 2026-03-01T00:00:00+01:00

  • date_from string (date) query

    Paid on or after this date.

  • date_to string (date) query

    Paid on or before this date.

Responses

200 OK – A page of payments.

application/jsonobject

  • data array<SupplierPayment> required
    11 fields · each item
    • id integer
    • supplier_invoice_id string (uuid)
    • paid_on string (date)
    • amount_ore integer

      Kronor the bank took, öre (negative for money back on a credit note).

    • currency string
    • foreign_amount_minor integer nullable

      Hundredths of the invoice's currency, for an invoice in another currency.

    • exchange_difference_ore integer
    • account integer nullable
    • voucher_id string (uuid)
    • created_at string (date-time)
    • updated_at string (date-time)
  • meta ListMeta required
    3 fields
    • limit integer required
    • next_cursor string required nullable

      Opaque; pass as `cursor` for the next page. null on the last page.

    • has_more boolean required

Response headers: X-Request-Id, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset

401 Unauthorized – Missing, invalid, expired or revoked token or API key. Also returned when the person behind the credential has left the company (an OAuth grant is then revoked for good).

All error codes · application/problem+json

  • unauthenticatedNo valid credential

    Nyckeln eller token saknas, är ogiltig, har gått ut eller har återkallats.

Response headers: X-Request-Id, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset, WWW-Authenticate

403 Forbidden – The credential may not do this: a scope is missing, the granting person no longer has the permission, the address is not allowed, the company is archived (read-only) or no longer allows the app.

All error codes · application/problem+json

  • insufficient_scopeScope missing or permission lost

    Nyckeln eller appen saknar behörigheten vouchers:post, eller så har personen som gav den inte längre den behörigheten i företaget.

  • forbiddenThe action refuses (for example changing a posted voucher)

    Behörighet saknas för det här.

  • ip_not_allowedOutside the IP allowlist

    Företaget tillåter inte anrop från den här adressen.

  • company_archivedWrite to an archived company

    Företaget är arkiverat och kan bara läsas.

  • app_not_allowedThe company no longer allows the app

    Företaget tillåter inte längre den här appen.

Response headers: X-Request-Id, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset

404 Not Found – Not found. Also the answer for another company's ids (existence is never revealed) and for every call while NONOX Connect is turned off for the company.

All error codes · application/problem+json

  • not_foundUnknown id, other company's id, or module off

    Det du söker finns inte.

Response headers: X-Request-Id, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset

429 Too Many Requests – Rate limit exceeded (per credential, per company or per address). Wait Retry-After seconds.

All error codes · application/problem+json

  • rate_limitedOver the limit

    För många anrop. Försök igen om 23 sekunder.

Response headers: X-Request-Id, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset, Retry-After

Code samples

curl
curl "https://nonox.app/api/v1/supplier-payments?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/supplier-payments', [
        '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/supplier-payments', [
    '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/supplier-payments');
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/supplier-payments",
    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"]

Responses · 200

application/json
{
  "data": [
    {
      "id": 41,
      "supplier_invoice_id": "8d1f4b2a-3c5e-4a7b-9d0e-6f1a2b3c4d5e",
      "paid_on": "2026-03-31",
      "amount_ore": 125000,
      "currency": "SEK",
      "foreign_amount_minor": null,
      "exchange_difference_ore": 0,
      "account": 1930,
      "voucher_id": "2b3c4d5e-6f7a-4b8c-9d0e-1f2a3b4c5d6e",
      "created_at": "2026-03-31T08:00:00+02:00",
      "updated_at": "2026-03-31T08:00:00+02:00"
    }
  ],
  "meta": {
    "limit": 50,
    "next_cursor": null,
    "has_more": false
  }
}

Error

4011 example
No valid credential
{
  "type": "urn:nonox:problem:unauthenticated",
  "title": "Unauthorized",
  "status": 401,
  "code": "unauthenticated",
  "detail": "Nyckeln eller token saknas, är ogiltig, har gått ut eller har återkallats.",
  "instance": "urn:nonox:request:7f3c2a9e-4b1d-4c8e-9a51-2d6f0e8b3c17"
}
4035 examples
Scope missing or permission lost
{
  "type": "urn:nonox:problem:insufficient_scope",
  "title": "Forbidden",
  "status": 403,
  "code": "insufficient_scope",
  "detail": "Nyckeln eller appen saknar behörigheten vouchers:post, eller så har personen som gav den inte längre den behörigheten i företaget.",
  "instance": "urn:nonox:request:7f3c2a9e-4b1d-4c8e-9a51-2d6f0e8b3c17",
  "required_scopes": [
    "vouchers:post"
  ]
}
The action refuses (for example changing a posted voucher)
{
  "type": "urn:nonox:problem:forbidden",
  "title": "Forbidden",
  "status": 403,
  "code": "forbidden",
  "detail": "Behörighet saknas för det här.",
  "instance": "urn:nonox:request:7f3c2a9e-4b1d-4c8e-9a51-2d6f0e8b3c17"
}
Outside the IP allowlist
{
  "type": "urn:nonox:problem:ip_not_allowed",
  "title": "Forbidden",
  "status": 403,
  "code": "ip_not_allowed",
  "detail": "Företaget tillåter inte anrop från den här adressen.",
  "instance": "urn:nonox:request:7f3c2a9e-4b1d-4c8e-9a51-2d6f0e8b3c17"
}
Write to an archived company
{
  "type": "urn:nonox:problem:company_archived",
  "title": "Forbidden",
  "status": 403,
  "code": "company_archived",
  "detail": "Företaget är arkiverat och kan bara läsas.",
  "instance": "urn:nonox:request:7f3c2a9e-4b1d-4c8e-9a51-2d6f0e8b3c17"
}
The company no longer allows the app
{
  "type": "urn:nonox:problem:app_not_allowed",
  "title": "Forbidden",
  "status": 403,
  "code": "app_not_allowed",
  "detail": "Företaget tillåter inte längre den här appen.",
  "instance": "urn:nonox:request:7f3c2a9e-4b1d-4c8e-9a51-2d6f0e8b3c17"
}
4041 example
Unknown id, other company's id, or module off
{
  "type": "urn:nonox:problem:not_found",
  "title": "Not Found",
  "status": 404,
  "code": "not_found",
  "detail": "Det du söker finns inte.",
  "instance": "urn:nonox:request:7f3c2a9e-4b1d-4c8e-9a51-2d6f0e8b3c17"
}
4291 example
Over the limit
{
  "type": "urn:nonox:problem:rate_limited",
  "title": "Too Many Requests",
  "status": 429,
  "code": "rate_limited",
  "detail": "För många anrop. Försök igen om 23 sekunder.",
  "instance": "urn:nonox:request:7f3c2a9e-4b1d-4c8e-9a51-2d6f0e8b3c17"
}