Tabba.
FunktionerPriserKontakt
Log indKom i gang
Tabba.

Moderne økonomistyring for virksomheder.

Produkt

  • Funktioner
  • Priser
  • Integrationer
  • Ændringslog

Ressourcer

  • Blog
  • Hjælpecenter
  • Udviklere

Virksomhed

  • Karriere
  • Kontakt

Juridisk

  • Privatlivspolitik
  • Servicevilkår
  • Cookie-politik
  • Sikkerhed

Forbind

  • Twitter
  • GitHub
  • LinkedIn
  • Discord

© 2026 Tabba. Alle rettigheder forbeholdes.

PrivatlivspolitikServicevilkårCookie-politik
Back to developer docs

Guides

  • Getting started
  • Authentication
  • external_id and idempotency
  • Work registration
  • Issuance and auto-send
  • Webhooks
  • Pagination
  • Errors

Errors

The API uses HTTP-native status codes so resp.ok and standard handling work correctly. Failure bodies always follow one shape:

{
  "error": {
    "type": "validation_failed",
    "code": "VALIDATION_FAILED",
    "message": "Body failed schema validation.",
    "field_errors": {
      "name": ["Required"],
      "email": ["Invalid email address"]
    },
    "request_id": "req_01H…"
  }
}

Branch on code, not on message — code is stable; message is free-form and may improve over time.

Status code map

StatusFamilyTypical code
400Bad requestMalformed JSON
401AuthUNAUTHENTICATED
403ScopeINSUFFICIENT_SCOPE
404Not foundRESOURCE_NOT_FOUND / LINE_NOT_FOUND
409Business conflictsee below
422ValidationVALIDATION_FAILED (with field_errors)
429Rate limitRATE_LIMITED (with Retry-After header)
500InternalINTERNAL_ERROR

Typed 409 codes

Codes you can branch on to distinguish business-rule conflicts:

  • INVOICE_ALREADY_ISSUED — you tried to edit a frozen invoice; raise a credit note.
  • INVOICE_NOT_ISSUED — you tried to credit-note an unissued invoice.
  • SERIES_CANCELLED — a write against a cancelled series.
  • OCCURRENCE_NOT_FOUND — no current occurrence (past horizon, paused).
  • OCCURRENCE_SKIPPED — the occurrence was explicitly skipped.
  • DELETE_BLOCKED_BY_BOOKINGS — a customer delete blocked because Dinero has bookings against them.

request_id

Every response — success or failure — includes a request_id. Log it alongside your integration's own trace id. If you open a support ticket, the request_id lets us find your exact call in seconds.

Rate limiting

Every response carries three rate-limit headers:

X-RateLimit-Limit: 300
X-RateLimit-Remaining: 287
X-RateLimit-Reset: 1717000000

On 429, the response adds:

Retry-After: 12

Two buckets:

  • General — reads and non-Dinero writes. A generous default.
  • Dinero-writes — a separate, stricter bucket for endpoints that hit Dinero (issue, credit-note). This protects the expensive operations without throttling your reads.

Retry with exponential backoff on Retry-After. Do not retry on 400/401/403/404/422 — those will not succeed on retry with the same payload.

Versioning

The URL major (/v1) is additive-only. Within a major, we may:

  • Add new endpoints.
  • Add new optional fields on request bodies.
  • Add new fields on response bodies.
  • Add new event types to webhooks.
  • Add new error codes (branch defensively: an unknown code should fall through to a generic handler).

We will NOT, within /v1:

  • Remove endpoints.
  • Remove or rename fields.
  • Change the meaning of an existing code.
  • Tighten validation on an existing endpoint in a way that would reject payloads that used to succeed.

A breaking change ships as /v2. Both majors are supported in parallel during a deprecation window announced in the changelog.