expense-inbox

Stable. Describes behaviour that is built and covered by tests in this repository.

API reference

GET /v1/expense-inbox #

The tenant's invoice inbox address

Invoices received by mail are forwarded to invoices+<token>@<inbound domain>. The attachments wait as items to review; the console reads them in the browser. Made on first use. address is empty until the deployment has an inbound mail domain.

Parameters

NameInTypeDescription
app_idquerystring · uuidThe inbox of one app instead of the whole tenant

Responses

StatusMeaningBody
200OKExpenseInbox
400Error envelopeError
Example response
{
  "token": "string",
  "app_id": "string",
  "address": "string"
}
curl
curl -X GET https://YOUR-API-ADDRESS/v1/expense-inbox \
  -H "Authorization: Bearer $PAYRUDDER_API_KEY"

POST /v1/expense-inbox/rotate #

Give the invoice inbox a new address

Mail sent to the old address is dropped.

Parameters

NameInTypeDescription
app_idquerystring · uuid

Responses

StatusMeaningBody
200OKExpenseInbox
400Error envelopeError
Example response
{
  "token": "string",
  "app_id": "string",
  "address": "string"
}
curl
curl -X POST https://YOUR-API-ADDRESS/v1/expense-inbox/rotate \
  -H "Authorization: Bearer $PAYRUDDER_API_KEY"

GET /v1/expense-inbox/items #

The attachments received by mail, newest first

Not paged: the newest page_size items; there is no page_token, so older items come into view once the newer ones are resolved.

Parameters

NameInTypeDescription
statusqueryto_review | accepted | dismissed
page_sizequeryinteger

Responses

StatusMeaningBody
200OKInboxItemPage
400Error envelopeError
Example response
{
  "items": [
    {
      "id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
      "app_id": "string",
      "from": "string",
      "subject": "string",
      "filename": "string",
      "content_type": "string",
      "size_bytes": "string",
      "status": "to_review",
      "expense_id": "string",
      "receive_time": "2026-11-03T10:15:00Z"
    }
  ]
}
curl
curl -X GET https://YOUR-API-ADDRESS/v1/expense-inbox/items \
  -H "Authorization: Bearer $PAYRUDDER_API_KEY"

GET /v1/expense-inbox/items/{id}/file #

The bytes of a received attachment

Parameters

NameInTypeDescription
id requiredpathstring · uuid

Responses

StatusMeaningBody
200The file as it came (PDF, PNG or JPEG)
404Error envelopeError
curl
curl -X GET https://YOUR-API-ADDRESS/v1/expense-inbox/items/<id>/file \
  -H "Authorization: Bearer $PAYRUDDER_API_KEY"

POST /v1/expense-inbox/items/{id}/resolve #

Mark a received attachment accepted or dismissed

An item is resolved once. Accepting records the expense that was made from it.

Parameters

NameInTypeDescription
id requiredpathstring · uuid

Request body

FieldTypeDescription
status requiredaccepted | dismissed
expense_idstring · uuid
Example
{
  "status": "accepted"
}

Responses

StatusMeaningBody
200OKInboxItem
400Error envelopeError
404Error envelopeError
Example response
{
  "id": "0192f0b4-6f6e-7c3a-9a3e-6a1f2b3c4d5e",
  "app_id": "string",
  "from": "string",
  "subject": "string",
  "filename": "string",
  "content_type": "string",
  "size_bytes": "string",
  "status": "to_review",
  "expense_id": "string",
  "receive_time": "2026-11-03T10:15:00Z"
}
curl
curl -X POST https://YOUR-API-ADDRESS/v1/expense-inbox/items/<id>/resolve \
  -H "Authorization: Bearer $PAYRUDDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"status":"accepted"}'

Models

Error

FieldTypeDescription
error requiredobject

ExpenseInbox

FieldTypeDescription
token requiredstring
app_id requiredstring
address requiredstringinvoices+<token>@<inbound domain>; empty when no inbound domain is configured

InboxItem

FieldTypeDescription
id requiredstring · uuid
app_id requiredstring
from requiredstring
subject requiredstring
filename requiredstring
content_type requiredstring
size_bytes requiredstring · int64
status requiredto_review | accepted | dismissed
expense_id requiredstring
receive_time requiredstring · date-time

InboxItemPage

FieldTypeDescription
items requiredarray of InboxItem

ResolveInboxItemRequest

FieldTypeDescription
status requiredaccepted | dismissed
expense_idstring · uuid