Skip to content

Spending you record yourself, posted the moment you send it.

One endpoint, with the fields it takes and the fields it gives back.

POST/expenses

Records and immediately posts a manual expense.

  • Leave entityId out only when this key can reach exactly one business. When it can reach several, a call that omits it is refused; call GET /businesses for the ids.
  • Send exactly one of vendorName or vendorId.
  • A vendorName that matches no existing vendor exactly creates a new one, so prefer vendorId when you have it. The match is case sensitive.
  • amountCents must be greater than zero.
  • The account you send is posted as it is. Nothing here is categorized by AI, and nothing lands in the review queue.

Needs the expenses:write permission. Only a Read and write key has it.

Body fields

entityId
Typestring
RequiredOptional
Details
  • a uuid
date
Typestring
RequiredRequired
Details
  • a date like 2026-09-20
amountCents
Typestring
RequiredRequired
Details
  • digits only, whole cents
vendorName
Typestring
RequiredOptional
Details
  • up to 200 characters
vendorId
Typestring
RequiredOptional
Details
  • a uuid
accountId
Typestring
RequiredRequired
Details
  • a uuid
memo
Typestring
RequiredOptional
Details
  • up to 2000 characters
Request
curl -X POST "https://www.numm.io/api/v1/expenses" \
  -H "Authorization: Bearer nmo_live_REPLACE_WITH_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 0190a1b2-c3d4-7e5f-8a9b-0c1d2e3fee00" \
  -d '{
  "entityId": "0190a1b2-c3d4-7e5f-8a9b-0c1d2e3f1002",
  "date": "2026-02-01",
  "amountCents": "1500",
  "vendorId": "0190a1b2-c3d4-7e5f-8a9b-0c1d2e3f1004",
  "accountId": "0190a1b2-c3d4-7e5f-8a9b-0c1d2e3f1003"
}'
Response 201
{
  "expenseId": "0190a1b2-c3d4-7e5f-9a9b-0c1d2e3f100a",
  "transactionId": "0190a1b2-c3d4-7e5f-9a9b-0c1d2e3f1006"
}

Response fields

expenseId
Typestring
PresentAlways
Details
  • a uuid
transactionId
Typestring or null
PresentAlways
Details
  • a uuid

This call takes an optional Idempotency-Key header. Repeat the same request with the same key within 24 hours and you get the first response back, with an idempotent-replayed: true header, and the work does not run twice. The same key with a different request is refused. See Idempotency and safe retries.

Errors

entity_not_allowed
Status403
MeaningYour key is limited to certain businesses, and this is not one of them.
not_found
Status404
MeaningThere is no such record, or none your key can reach.
period_locked
Status409
MeaningThe date falls inside a closed period, so nothing can post to it.
read_only_billing_state
Status402
MeaningYour subscription is past due, so your books are read only for now.
conflict
Status409
MeaningThe request clashed with something that already happened.

Every endpoint can also return:

invalid_key
Status401
MeaningYour key is missing, malformed, revoked, or expired.
insufficient_scope
Status403
MeaningYour key does not carry the scope this endpoint needs.
rate_limited
Status429
MeaningYou've made too many requests for this key. The retry-after header says how long to wait.
validation_failed
Status422
MeaningSomething in the path, the query, or the body did not pass validation.
internal_error
Status500
MeaningSomething went wrong on our side. Try again.
Expenses — Nummio API