API · 10 operations

Envelopes

Envelopes and the categories that group them, targets included.

get /v1/budgets/{budget_id}/categories

List categories in render order

scope budget:read · listCategories

Parameters

  • budget_id path · string · required

Returns · 200

{ categories[] }: id, name, sort_order. A category is a named set of envelopes and nothing more: it carries no total of its own, no period, and no behaviour.

Example

curl 'https://api.mintro.money/v1/budgets/default/categories' \ -H "Authorization: Bearer $MINTRO_KEY"

Errors · besides 401, 429, 500

  • 403

    forbidden: The key is valid but lacks the scope this call needs. Ask the human to mint a key with the scope named in the message.

post /v1/budgets/{budget_id}/categories

Create a category

scope budget:write · createCategory

Parameters

  • budget_id path · string · required

Body · JSON

  • name string · required · ≤ 200 chars

  • sort_order integer · ≥ 0 · ≤ 100000

Returns · 201

The category.

Example

curl -X POST 'https://api.mintro.money/v1/budgets/default/categories' \ -H "Authorization: Bearer $MINTRO_KEY" \ -H 'Content-Type: application/json' \ -d '{ "name": "<name>" }'

Errors · besides 401, 429, 500

  • 400

    validation_failed: The request body or query is malformed. The message names the offending field; fix it and retry.

  • 403

    forbidden: The key is valid but lacks the scope this call needs. Ask the human to mint a key with the scope named in the message.

  • 409

    idempotency_conflict: This Idempotency-Key was used for a different request, or the first request is still in flight. Retry the in-flight case after a second; use a fresh key for a genuinely different request.

patch /v1/budgets/{budget_id}/categories/{id}

Rename a category or change its position

scope budget:write · updateCategory

Parameters

  • budget_id path · string · required

  • id path · string · required

Body · JSON

  • name string · ≤ 200 chars

  • sort_order integer · ≥ 0 · ≤ 100000

Returns · 200

The updated category.

Example

curl -X PATCH 'https://api.mintro.money/v1/budgets/default/categories/<id>' \ -H "Authorization: Bearer $MINTRO_KEY" \ -H 'Content-Type: application/json' \ -d '{ "name": "<name>", "sort_order": 0 }'

Errors · besides 401, 429, 500

  • 400

    validation_failed: The request body or query is malformed. The message names the offending field; fix it and retry.

  • 403

    forbidden: The key is valid but lacks the scope this call needs. Ask the human to mint a key with the scope named in the message.

  • 404

    not_found: No such record on this budget. Re-read GET /v1/budgets/{id} (or the relevant list) for current ids rather than reusing a remembered one.

  • 409

    idempotency_conflict: This Idempotency-Key was used for a different request, or the first request is still in flight. Retry the in-flight case after a second; use a fresh key for a genuinely different request.

delete /v1/budgets/{budget_id}/categories/{id}

Delete a category; its envelopes survive, uncategorized

scope budget:write · deleteCategory

Parameters

  • budget_id path · string · required

  • id path · string · required

Returns · 204

Empty. Deleting a category never deletes envelopes; members simply become uncategorized (category_id: null), which is a normal resting state.

Example

curl -X DELETE 'https://api.mintro.money/v1/budgets/default/categories/<id>' \ -H "Authorization: Bearer $MINTRO_KEY"

Errors · besides 401, 429, 500

  • 403

    forbidden: The key is valid but lacks the scope this call needs. Ask the human to mint a key with the scope named in the message.

  • 404

    not_found: No such record on this budget. Re-read GET /v1/budgets/{id} (or the relevant list) for current ids rather than reusing a remembered one.

  • 409

    idempotency_conflict: This Idempotency-Key was used for a different request, or the first request is still in flight. Retry the in-flight case after a second; use a fresh key for a genuinely different request.

put /v1/budgets/{budget_id}/envelopes/order

Bulk placement: reorder categories and envelopes in one call

scope budget:write · reorderBudget

Parameters

  • budget_id path · string · required

Body · JSON

  • categories object[] · ≤ 200 items

  • categories[].id string · required · ≤ 64 chars

  • categories[].sort_order integer · required · ≥ 0 · ≤ 100000

  • envelopes object[] · ≤ 1000 items

  • envelopes[].id string · required · ≤ 64 chars

  • envelopes[].category_id string | null · ≤ 64 chars

  • envelopes[].sort_order integer · required · ≥ 0 · ≤ 100000

Returns · 200

{ categories, envelopes }: how many of each were placed. Idempotent: sending the same body twice lands in the same layout. Use this instead of N PATCHes; it is one database transaction and one rate-limit unit.

Example

curl -X PUT 'https://api.mintro.money/v1/budgets/default/envelopes/order' \ -H "Authorization: Bearer $MINTRO_KEY" \ -H 'Content-Type: application/json' \ -d '{ "categories": [ { "id": "<id>", "sort_order": 0 } ], "envelopes": [ { "id": "<id>", "sort_order": 0 } ] }'

Errors · besides 401, 429, 500

  • 400

    validation_failed: The request body or query is malformed. The message names the offending field; fix it and retry.

  • 403

    forbidden: The key is valid but lacks the scope this call needs. Ask the human to mint a key with the scope named in the message.

  • 404

    not_found: No such record on this budget. Re-read GET /v1/budgets/{id} (or the relevant list) for current ids rather than reusing a remembered one.

  • 409

    idempotency_conflict: This Idempotency-Key was used for a different request, or the first request is still in flight. Retry the in-flight case after a second; use a fresh key for a genuinely different request.

post /v1/budgets/{budget_id}/envelopes

Create an envelope

scope budget:write · createEnvelope

Parameters

  • budget_id path · string · required

Body · JSON

  • name string · required · ≤ 200 chars

  • currency string · matches ^[A-Z]{3}$ · ≥ 3 chars · ≤ 3 chars

  • category_id string | null · ≤ 64 chars

  • sort_order integer · ≥ 0 · ≤ 100000

  • target_cents integer | null · ≥ -9007199254740991

  • target_kind "monthly" | "weekly" | "by_date" | "balance" | "debt"

  • target_date string | null · YYYY-MM-DD

  • target_note string | null · ≤ 2000 chars

Returns · 201

The envelope, with cached_total_cents: 0.

Example

curl -X POST 'https://api.mintro.money/v1/budgets/default/envelopes' \ -H "Authorization: Bearer $MINTRO_KEY" \ -H 'Content-Type: application/json' \ -d '{ "name": "<name>" }'

Errors · besides 401, 429, 500

  • 400

    validation_failed: The request body or query is malformed. The message names the offending field; fix it and retry.

  • 403

    forbidden: The key is valid but lacks the scope this call needs. Ask the human to mint a key with the scope named in the message.

  • 409

    idempotency_conflict: This Idempotency-Key was used for a different request, or the first request is still in flight. Retry the in-flight case after a second; use a fresh key for a genuinely different request.

get /v1/budgets/{budget_id}/envelopes

List envelopes

scope budget:read · listEnvelopes

Parameters

  • budget_id path · string · required

  • cursor query · string

  • limit query · integer · ≥ 1 · ≤ 100

Returns · 200

{ envelopes[], next_cursor } with cached totals and targets.

Example

curl 'https://api.mintro.money/v1/budgets/default/envelopes' \ -H "Authorization: Bearer $MINTRO_KEY"

Errors · besides 401, 429, 500

  • 400

    validation_failed: The request body or query is malformed. The message names the offending field; fix it and retry.

  • 403

    forbidden: The key is valid but lacks the scope this call needs. Ask the human to mint a key with the scope named in the message.

get /v1/budgets/{budget_id}/envelopes/{id}

Envelope with recent entries

scope budget:read · getEnvelope

Parameters

  • budget_id path · string · required

  • id path · string · required

Returns · 200

The envelope plus its most recent entries, and scheduled_bills: how many active bills with an account are filed to it. The cashflow line walks those on their own day, so projecting the envelope never counts them twice. forecast_options { last_month_cents, average_3_cents, target_cents } is what each basis would add a month, worked out by the same rules the cashflow line uses and after the envelope's scheduled bills, so each option's amount is shown before you choose (for target, next month's amount; target_cents is null when there is no monthly or weekly target, so target would project nothing). The amounts are not a snapshot: they are worked out on every read, so last month is always the latest full month and the average the last three full months; they move on the 1st, and target_cents follows the envelope's target. Null for a closed or card payment envelope. spending { last_month_cents, average_3_cents, bills_due_this_month, bills_due_this_month_cents } is what the envelope spent with its bills in (the latest full month, and the three full months before this one averaged, rounded up), and how many scheduled bill payments are still due from today to this month's last day and what they take. Sort or filter envelopes by these; null for a closed or card payment envelope.

Example

curl 'https://api.mintro.money/v1/budgets/default/envelopes/<id>' \ -H "Authorization: Bearer $MINTRO_KEY"

Errors · besides 401, 429, 500

  • 403

    forbidden: The key is valid but lacks the scope this call needs. Ask the human to mint a key with the scope named in the message.

  • 404

    not_found: No such record on this budget. Re-read GET /v1/budgets/{id} (or the relevant list) for current ids rather than reusing a remembered one.

patch /v1/budgets/{budget_id}/envelopes/{id}

Rename, close (force for entries, settle for money available), set or clear target, choose what the cashflow line projects

scope budget:write · updateEnvelope

Parameters

  • budget_id path · string · required

  • id path · string · required

Body · JSON

  • name string · ≤ 200 chars

  • status "open" | "closed"

  • force boolean

  • settle boolean

  • category_id string | null · ≤ 64 chars

  • sort_order integer · ≥ 0 · ≤ 100000

  • target_cents integer | null · ≥ -9007199254740991

  • target_kind "monthly" | "weekly" | "by_date" | "balance" | "debt"

  • target_date string | null · YYYY-MM-DD

  • target_note string | null · ≤ 2000 chars

  • forecast_basis "last_month" | "average_3" | "target" | null

Returns · 200

The updated envelope. forecast_basis decides whether GET /v1/cashflow projects this envelope's spending: last_month, average_3 (three full months), target (its monthly target), or null (not projected, the default). Scheduled bills are never counted twice: a projection adds only the envelope's spending that is not already a scheduled bill. GET this envelope (or GET /v1/budgets/{id}) for forecast_options: what each basis would add, before you choose.

Example

curl -X PATCH 'https://api.mintro.money/v1/budgets/default/envelopes/<id>' \ -H "Authorization: Bearer $MINTRO_KEY" \ -H 'Content-Type: application/json' \ -d '{ "name": "<name>", "status": "open" }'

Errors · besides 401, 429, 500

  • 400

    validation_failed: The request body or query is malformed. The message names the offending field; fix it and retry.

  • 403

    forbidden: The key is valid but lacks the scope this call needs. Ask the human to mint a key with the scope named in the message.

  • 404

    not_found: No such record on this budget. Re-read GET /v1/budgets/{id} (or the relevant list) for current ids rather than reusing a remembered one.

  • 409

    idempotency_conflict: This Idempotency-Key was used for a different request, or the first request is still in flight. Retry the in-flight case after a second; use a fresh key for a genuinely different request.

    envelope_not_empty: The envelope has a non-zero cached total. Move or undo its entries first, or PATCH with force: true to close it and keep them.

    envelope_has_money: The envelope still has money available this month (or is overspent). A closed envelope is out of sight, so it may not hold any: move it or cover it first, or PATCH with settle: true to return it to ready to assign (or cover the overspend from it) as it closes.

delete /v1/budgets/{budget_id}/envelopes/{id}

Delete a closed envelope; what it held goes back where it came from

scope budget:write · deleteEnvelope

Parameters

  • budget_id path · string · required

  • id path · string · required

Returns · 200

{ envelope_id, entries_removed, inflows_ready_to_assign, outflows_to_file, unassigned_cents }. Only a closed envelope can be deleted (409 envelope_open otherwise): close is the reversible step, this is the one past it. Its entries are removed through the one entry write path; a transaction left with no entries is unfiled: an inflow lands as income for its month and is ready to assign again, an outflow returns to the inbox to be filed elsewhere. Money the ledger had given the envelope returns to ready to assign as one unassign row (unassigned_cents). A split keeps its other entries and stays filed. Use it to retire an import-era "Income" pot without leaving its history in every report.

Example

curl -X DELETE 'https://api.mintro.money/v1/budgets/default/envelopes/<id>' \ -H "Authorization: Bearer $MINTRO_KEY"

Errors · besides 401, 429, 500

  • 403

    forbidden: The key is valid but lacks the scope this call needs. Ask the human to mint a key with the scope named in the message.

  • 404

    not_found: No such record on this budget. Re-read GET /v1/budgets/{id} (or the relevant list) for current ids rather than reusing a remembered one.

  • 409

    idempotency_conflict: This Idempotency-Key was used for a different request, or the first request is still in flight. Retry the in-flight case after a second; use a fresh key for a genuinely different request.

    envelope_open: Only a closed envelope can be deleted. PATCH it with status: closed first (force: true if it has entries), then DELETE.