NuminaDevelopers
Dashboard
Create journal entry

Create journal entry

POST
/v1/journal-entries

Creates a draft journal entry for the authenticated company. The entry is created with status 'open' and does not affect balances until it is booked, in the Numina UI or with POST /v1/journal-entries/{id}/book. VAT calculations (if vat_code provided) happen automatically during booking.

An account, VAT code or contact that does not exist returns 400 invalid_request.

Send an Idempotency-Key header (for example a UUID generated per request) to retry safely after a timeout or network error. A retry with the same key and the same body returns the original response with the header Idempotent-Replayed: true. Keys are scoped to the company and kept for 24 hours after a successful request. A failed request (4xx/5xx) frees the key, so a retry with that key runs again. Reusing a key with a different body returns 422; retrying while the first request is still processing returns 409.

Requires one ofjournal:writewrite:draftwrite:ledger

Headers

  • Idempotency-Keystring· max 255 chars
    Unique key for this request (max 255 characters). Retrying with the same key and body returns the original response instead of doing the work again.

Body

application/json

  • datestringRequired· YYYY-MM-DD
    Transaction date in YYYY-MM-DD format
  • textstringRequired· max 500 chars
    Transaction description
  • contact_idstring (uuid)
    Optional contact (customer/supplier) ID to associate with this transaction
  • linesarray of objectsRequired
    Journal entry line items (minimum 2 lines required for balanced entry)
    +Show 3 child attributes
    • account_numberintegerRequired
      Account number in chart of accounts
    • amountnumberRequired
      Signed amount in DKK: debit is positive, credit is negative. The lines must sum to exactly zero. With a vat_code, the amount includes VAT and the VAT is split out when the entry is booked.
    • vat_codestring
      VAT code (e.g., 'U25' for 25% sales VAT). Stored for later calculation during booking.
  • external_referencestring· max 255 chars
    Your own id for this entry (max 255 characters), unique per company for your app. A second entry with the same reference returns 409 with the existing entry's id. Available to apps registered as a Numina integration.

Errors

  • 400Invalid input or validation failed
  • 401Invalid or missing authentication
  • 403Missing scope, or the company is archived
  • 409An entry with this `external_reference` already exists (`id` is that entry), or a request with the same Idempotency-Key is still being processed
  • 422The Idempotency-Key was already used with a different request
  • 429Rate limit exceeded
  • 500Internal Server Error

Every error has the same shape. See Errors.

cURL
curl -X POST https://api.numina.app/v1/journal-entries \
  -H "Authorization: Bearer numi_YOUR_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "date": "2024-01-15",
    "text": "Cash sale",
    "contact_id": "550e8400-e29b-41d4-a716-446655440000",
    "lines": [
      {
        "account_number": 1010,
        "amount": -1250,
        "vat_code": "U25"
      },
      {
        "account_number": 6480,
        "amount": 1250
      }
    ],
    "external_reference": "payroll-run-2026-01"
  }'
JavaScript
const response = await fetch("https://api.numina.app/v1/journal-entries", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.NUMINA_API_KEY}`,
    "Idempotency-Key": crypto.randomUUID(),
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "date": "2024-01-15",
    "text": "Cash sale",
    "contact_id": "550e8400-e29b-41d4-a716-446655440000",
    "lines": [
      {
        "account_number": 1010,
        "amount": -1250,
        "vat_code": "U25"
      },
      {
        "account_number": 6480,
        "amount": 1250
      }
    ],
    "external_reference": "payroll-run-2026-01"
  }),
});

const data = await response.json();
Python
import uuid
import os

import requests

response = requests.post(
    "https://api.numina.app/v1/journal-entries",
    headers={
        "Authorization": f"Bearer {os.environ['NUMINA_API_KEY']}",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "date": "2024-01-15",
        "text": "Cash sale",
        "contact_id": "550e8400-e29b-41d4-a716-446655440000",
        "lines": [
            {
                "account_number": 1010,
                "amount": -1250,
                "vat_code": "U25"
            },
            {
                "account_number": 6480,
                "amount": 1250
            }
        ],
        "external_reference": "payroll-run-2026-01"
    },
)
data = response.json()
Response
201
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "date": "2026-01-15",
  "text": "Invoice payment from customer",
  "status": "open",
  "contact_id": "550e8400-e29b-41d4-a716-446655440000",
  "created_at": "2026-01-15T10:30:00Z",
  "external_reference": "payroll-run-2026-01",
  "lines": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "account_number": 3000,
      "account_id": "550e8400-e29b-41d4-a716-446655440001",
      "account_name": "Revenue",
      "amount": -1000,
      "text": "Invoice payment",
      "vat_code": "U25",
      "currency_code": "DKK",
      "currency_rate": 1
    }
  ]
}