Builder's guide · Appendix A

A complete request, end to end

Posting a manual journal: create the draft, then post it.

# 1. Create a draft (no balance changes yet)
curl -X POST https://books.internal.example/v1/ledger/manual-journals \
  -H 'X-Source-System: console' \
  -H "Authorization: Bearer $AK_WRITER_KEY" \
  -H 'Idempotency-Key: 5d7f6a0e-2c1b-4c39-9a9e-3e0b6f1f9a11' \
  -H 'Content-Type: application/json' \
  -d '{ "company_id": "…", "entry_type": "adjusting",
        "posting_date": "2026-11-06", "description": "Accrue November rent",
        "prepared_by": "Sam Ortiz",
        "lines": [ { "gl_account_id": "…rent expense…", "debit_amount": "900.00" },
                   { "gl_account_id": "…accrued liabilities…", "credit_amount": "900.00" } ] }'

# 2. Post it, after the person confirms (a new key: this is a new action)
curl -X POST https://books.internal.example/v1/ledger/manual-journals/<id>/post \
  -H 'X-Source-System: console' \
  -H "Authorization: Bearer $AK_WRITER_KEY" \
  -H 'Idempotency-Key: 9a2e1c44-7b0d-4f6e-8a51-c1d2e3f4a5b6'

# 3. Record in the console's audit table:
#    person, route, X-Request-Id, journal id, journal entry id

The fields follow ManualJournalCreate in api/openapi.yaml at version 0.1.0. No journal_number is sent because the company has a number series (section 7). Generate your client from the OpenAPI file rather than copying this example.

The authentication checks, in order

StepCheckFailure
1X-Source-System present400 SOURCE_SYSTEM_MISSING
2Bearer credential present401 AUTHENTICATION_REQUIRED
3Key well-formed and genuine401 CREDENTIAL_INVALID
4The writer code exists403 SOURCE_SYSTEM_UNKNOWN
5The header names the key's own writer403 SOURCE_SYSTEM_CREDENTIAL_MISMATCH
6The writer is active403 SOURCE_SYSTEM_INACTIVE
7Key not revoked or expired401 CREDENTIAL_INVALID
8The role allows the route403 OPERATION_NOT_PERMITTED
9The company is in scope403 COMPANY_NOT_IN_SCOPE