Skip to content

Receipts and bills waiting for someone to confirm the category, and the call that confirms one.

2 endpoints, each with the fields it takes and the fields it gives back.

GET/review-queue

Returns pending AI-categorized expenses awaiting human review.

  • Leave entityId out to read the queue across every business in your account at once. A key limited to particular businesses is the exception: unless it is limited to exactly one, it has to name the one it wants.
  • This list is limited rather than paged: hasMore says whether more is waiting behind the limit you asked for.
  • limit counts highConfidence and needsReview together. highConfidence holds the items the AI scored high enough to accept in a batch; everything else is in needsReview. Each item carries the confidence the split used, which is null when the AI never scored it.

Needs the review:read permission. A Read only key has it.

Query parameters

entityId
Typestring
RequiredOptional
Details
  • a uuid
limit
Typeinteger
RequiredOptional
Details
  • 1 to 100, default 50
Request
curl "https://www.numm.io/api/v1/review-queue?entityId=0190a1b2-c3d4-7e5f-8a9b-0c1d2e3f1002" \
  -H "Authorization: Bearer nmo_live_REPLACE_WITH_YOUR_KEY"
Response 200
{
  "hasMore": false,
  "highConfidence": [],
  "needsReview": [
    {
      "id": "0190a1b2-c3d4-7e5f-9a9b-0c1d2e3f1008",
      "date": "2026-02-05",
      "amount": {
        "cents": "500",
        "formatted": "$5.00",
        "currency": "USD"
      },
      "vendor": "Office Depot",
      "description": null,
      "proposedAccountId": "0190a1b2-c3d4-7e5f-8a9b-0c1d2e3f1003",
      "proposedAccount": "Office Expense",
      "confidence": null,
      "rationale": null
    }
  ]
}

Response fields

highConfidence
Typearray of object
PresentAlways
highConfidence[].id
Typestring
PresentAlways
Details
  • a uuid
highConfidence[].date
Typestring
PresentAlways
Details
  • a date like 2026-09-20
highConfidence[].amount
Typemoney
PresentAlways
Details
  • an object: cents (whole cents as a digit string, in the currency beside it), formatted (a display string, not something to parse), currency (a three-letter code)
highConfidence[].vendor
Typestring or null
PresentAlways
highConfidence[].description
Typestring or null
PresentAlways
highConfidence[].proposedAccountId
Typestring or null
PresentAlways
Details
  • a uuid
highConfidence[].proposedAccount
Typestring or null
PresentAlways
highConfidence[].confidence
Typenumber or null
PresentAlways
highConfidence[].rationale
Typestring or null
PresentAlways
needsReview
Typearray of object
PresentAlways
needsReview[].id
Typestring
PresentAlways
Details
  • a uuid
needsReview[].date
Typestring
PresentAlways
Details
  • a date like 2026-09-20
needsReview[].amount
Typemoney
PresentAlways
Details
  • an object: cents (whole cents as a digit string, in the currency beside it), formatted (a display string, not something to parse), currency (a three-letter code)
needsReview[].vendor
Typestring or null
PresentAlways
needsReview[].description
Typestring or null
PresentAlways
needsReview[].proposedAccountId
Typestring or null
PresentAlways
Details
  • a uuid
needsReview[].proposedAccount
Typestring or null
PresentAlways
needsReview[].confidence
Typenumber or null
PresentAlways
needsReview[].rationale
Typestring or null
PresentAlways
hasMore
Typeboolean
PresentAlways

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.

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.

POST/review-queue/{id}/accept

Posts a pending review-queue expense, under the proposed account or one you name.

  • With no accountId, the category the AI proposed is used.
  • If the item has no proposed category, you have to send one.

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

Path parameters

id
Typestring
RequiredRequired
Details
  • a uuid

Body fields

accountId
Typestring
RequiredOptional
Details
  • a uuid
Request
curl -X POST "https://www.numm.io/api/v1/review-queue/0190a1b2-c3d4-7e5f-9a9b-0c1d2e3f1008/accept" \
  -H "Authorization: Bearer nmo_live_REPLACE_WITH_YOUR_KEY" \
  -H "Idempotency-Key: 0190a1b2-c3d4-7e5f-8a9b-0c1d2e3fee00"
Response 200
{
  "ok": true
}

Response fields

ok
Typeboolean
PresentAlways
Details
  • always true

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

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.
Review queue — Nummio API