Every API here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for apis
7 MCP tools reach this
find_apisBrowse and filter every API in the catalog.
get_api_artifactsOne API's artifacts, grouped by type.
get_openapiThe primary OpenAPI for this API.
find_similar_apisAPIs that look like this one.
apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
resolveTurn a domain, URL or GitHub org into the provider it belongs to.
find_cohortsEvery scored population of providers in the catalog.
All 92 tools →
Call it yourself
curl for this page
This API
curl "https://apis.io/api/v1/apis/asap-cool:asap-cool-expenses-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we
store it to create your key and to recognise you if you sign in with another
provider. See our Privacy Policy and
Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: ASAP Platform Expenses API
description: 'Public HTTP API for ASAP Platform (api.asap.cool).
All `/v1` responses are wrapped in a standard envelope. Success responses are `{ "data": , "meta": { "request_id", "next_cursor"?, "has_more"? } }` — the schema documented for each operation describes the inner `data` value. Errors are `{ "error": { "code", "message", "field"?, "request_id" } }`. Every response also carries an `X-Request-Id` header matching `meta.request_id` / `error.request_id`.'
license:
name: BUSL-1.1
version: 0.0.0
servers:
- url: https://api.asap.cool
description: Production
tags:
- name: Expenses
description: 'Purchases: what the org paid, with VAT per rate. A draft counts for nothing until confirmed.'
paths:
/v1/expenses:
get:
tags:
- Expenses
summary: GET /v1/expenses
operationId: listExpenses
parameters:
- name: status
in: query
description: Only this status.
required: false
schema:
oneOf:
- type: 'null'
- $ref: '#/components/schemas/StatusView'
- name: from
in: query
description: Incurred on or after this day, `YYYY-MM-DD`.
required: false
schema:
type:
- string
- 'null'
- name: to
in: query
description: Incurred on or before this day, `YYYY-MM-DD`.
required: false
schema:
type:
- string
- 'null'
- name: category
in: query
description: Only this category.
required: false
schema:
oneOf:
- type: 'null'
- $ref: '#/components/schemas/CategoryView'
responses:
'200':
description: Expenses matching the filters, most recent first.
content:
application/json:
schema:
$ref: '#/components/schemas/ExpenseListView'
'401':
description: No active org.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'403':
description: Missing invoice:read scope.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'422':
description: A date filter is not YYYY-MM-DD.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
security:
- api_key:
- invoice:read
- session: []
post:
tags:
- Expenses
summary: POST /v1/expenses
operationId: createExpense
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/CreateExpenseRequest'
required: true
responses:
'201':
description: Draft stored; it counts for nothing until confirmed.
content:
application/json:
schema:
$ref: '#/components/schemas/ExpenseView'
'401':
description: No active org.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'403':
description: Missing invoice:write scope.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'422':
description: A field is malformed, or `file_not_found` (not a file of this org).
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
security:
- api_key:
- invoice:write
- session: []
/v1/expenses/from-inbound/{inbound_id}:
post:
tags:
- Expenses
summary: POST /v1/expenses/from-inbound/{inbound_id}
operationId: createExpenseFromInbound
parameters:
- name: inbound_id
in: path
description: Received e-invoice identifier.
required: true
schema:
type: string
format: uuid
responses:
'201':
description: Draft prefilled from the e-invoice's parsed figures, with one VAT line whose rate is inferred. No AI is involved and no credit is used. It stays a draft for the user to check.
content:
application/json:
schema:
$ref: '#/components/schemas/ExpenseView'
'401':
description: No active org.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'403':
description: Missing invoice:write scope.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'404':
description: Received invoice not found, or cross-org.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'409':
description: '`expense_exists`: an expense already points at this e-invoice.'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'422':
description: '`inbound_not_parsed`: the e-invoice''s figures could not be read.'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
security:
- api_key:
- invoice:write
- session: []
/v1/expenses/receipts:
post:
tags:
- Expenses
summary: POST /v1/expenses/receipts
operationId: uploadExpenseReceipt
requestBody:
description: 'multipart/form-data with a `file` part: a PDF, JPEG or PNG receipt.'
content:
multipart/form-data:
schema:
type: string
required: true
responses:
'200':
description: This receipt is already an expense; it is returned as is and no credit is used.
content:
application/json:
schema:
$ref: '#/components/schemas/ExpenseView'
'201':
description: 'Receipt stored and read. A PDF that embeds its Factur-X data is read from it (`extraction_status` `none`, no AI credit, works with AI off). Otherwise the draft carries what the model read (`read`), or nothing (`failed`) when the read did not work: fill it by hand with the receipt beside the form. One AI credit is used either way.'
content:
application/json:
schema:
$ref: '#/components/schemas/ExpenseView'
'401':
description: No active org.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'402':
description: Monthly AI credits exhausted (`plan_limit_reached`); nothing was stored. `POST /v1/expenses` takes the figures by hand and needs no credit.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'403':
description: Missing invoice:write scope.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'413':
description: Body exceeds the upload limit.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'422':
description: '`upload_rejected` (empty, too large, not accepted) or `receipt_type_unsupported` (not a PDF, JPEG or PNG).'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'429':
description: Storage quota exhausted (`storage_quota_exceeded`).
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'503':
description: Receipt reading is not configured (`ai_unavailable`); nothing was stored.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
security:
- api_key:
- invoice:write
- session: []
/v1/expenses/register:
get:
tags:
- Expenses
summary: GET /v1/expenses/register
operationId: getExpenseRegister
parameters:
- name: from
in: query
description: First day of the period, `YYYY-MM-DD` (required).
required: false
schema:
type:
- string
- 'null'
- name: to
in: query
description: Last day of the period, `YYYY-MM-DD`, inclusive (required).
required: false
schema:
type:
- string
- 'null'
responses:
'200':
description: Totals of the confirmed expenses of the period; deductible VAT is null in franchise en base.
content:
application/json:
schema:
$ref: '#/components/schemas/RegisterView'
'401':
description: No active org.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'403':
description: Missing invoice:read scope.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'422':
description: '`from` or `to` missing or not YYYY-MM-DD, `to` before `from`, or `register_too_large`.'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
security:
- api_key:
- invoice:read
- session: []
/v1/expenses/register.csv:
get:
tags:
- Expenses
summary: GET /v1/expenses/register.csv
operationId: exportExpenseRegister
parameters:
- name: from
in: query
description: First day of the period, `YYYY-MM-DD` (required).
required: false
schema:
type:
- string
- 'null'
- name: to
in: query
description: Last day of the period, `YYYY-MM-DD`, inclusive (required).
required: false
schema:
type:
- string
- 'null'
responses:
'200':
description: 'CSV attachment: one row per VAT line of a confirmed expense.'
content:
text/csv:
schema:
type: string
'401':
description: No active org.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'403':
description: Missing invoice:read scope.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'422':
description: '`from` or `to` missing or not YYYY-MM-DD, `to` before `from`, or `register_too_large`.'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
security:
- api_key:
- invoice:read
- session: []
/v1/expenses/{id}:
get:
tags:
- Expenses
summary: GET /v1/expenses/{id}
operationId: getExpense
parameters:
- name: id
in: path
description: Expense identifier.
required: true
schema:
type: string
format: uuid
responses:
'200':
description: The expense.
content:
application/json:
schema:
$ref: '#/components/schemas/ExpenseView'
'401':
description: No active org.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'403':
description: Missing invoice:read scope.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'404':
description: Not found, or cross-org.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
security:
- api_key:
- invoice:read
- session: []
delete:
tags:
- Expenses
summary: DELETE /v1/expenses/{id}
operationId: deleteExpense
parameters:
- name: id
in: path
description: Expense identifier.
required: true
schema:
type: string
format: uuid
responses:
'204':
description: Deleted. The receipt stays in the file library.
'401':
description: No active org.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'403':
description: Missing invoice:write scope.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'404':
description: Not found, or cross-org.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
security:
- api_key:
- invoice:write
- session: []
patch:
tags:
- Expenses
summary: PATCH /v1/expenses/{id}
operationId: updateExpense
parameters:
- name: id
in: path
description: Expense identifier.
required: true
schema:
type: string
format: uuid
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateExpenseRequest'
required: true
responses:
'200':
description: The updated expense. A confirmed expense stays confirmed, so the edit must still pass the confirmation checks.
content:
application/json:
schema:
$ref: '#/components/schemas/ExpenseView'
'401':
description: No active org.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'403':
description: Missing invoice:write scope.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'404':
description: Not found, or cross-org.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'422':
description: A field is malformed or, on a confirmed expense, the result is inconsistent.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
security:
- api_key:
- invoice:write
- session: []
/v1/expenses/{id}/confirm:
post:
tags:
- Expenses
summary: POST /v1/expenses/{id}/confirm
operationId: confirmExpense
parameters:
- name: id
in: path
description: Expense identifier.
required: true
schema:
type: string
format: uuid
responses:
'200':
description: The expense is confirmed (also when it already was).
content:
application/json:
schema:
$ref: '#/components/schemas/ExpenseView'
'401':
description: No active org.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'403':
description: Missing invoice:write scope.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'404':
description: Not found, or cross-org.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'422':
description: The expense is incomplete or inconsistent; the error names the field.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
security:
- api_key:
- invoice:write
- session: []
/v1/expenses/{id}/receipt:
get:
tags:
- Expenses
summary: GET /v1/expenses/{id}/receipt
operationId: downloadExpenseReceipt
parameters:
- name: id
in: path
description: Expense identifier.
required: true
schema:
type: string
format: uuid
responses:
'307':
description: 'Redirect to the stored receipt: the library file (`/v1/files/{id}/content`) or, for an expense recorded from a received e-invoice, its PDF (`/v1/invoices/inbound/{id}/pdf`). Those routes check their own scope and the org.'
'401':
description: No active org.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'403':
description: Missing invoice:read scope.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
'404':
description: Expense not found, cross-org, or it has no receipt (`receipt_not_found`).
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBody'
security:
- api_key:
- invoice:read
- session: []
components:
schemas:
VatLineView:
type: object
description: One VAT rate of an expense.
required:
- rate
- base_cents
- vat_cents
- deductible_cents
properties:
base_cents:
type: integer
format: int64
description: Amount before VAT, in cents.
deductible_cents:
type: integer
format: int64
description: Recoverable part of the VAT, in cents.
rate:
type: string
description: Rate in percent (`"20"`, `"5.5"`).
vat_cents:
type: integer
format: int64
description: VAT amount, in cents.
CreateExpenseRequest:
type: object
description: Body of `POST /v1/expenses`.
properties:
category:
oneOf:
- type: 'null'
- $ref: '#/components/schemas/CategoryView'
description: Advisory category; defaults to `other`.
currency:
type:
- string
- 'null'
description: ISO currency code; defaults to `eur`.
file_id:
type:
- string
- 'null'
format: uuid
description: A file of the library to attach as the receipt.
incurred_on:
type:
- string
- 'null'
description: Day the expense was incurred, `YYYY-MM-DD`.
reference:
type:
- string
- 'null'
description: The supplier's invoice or ticket number.
supplier_name:
type:
- string
- 'null'
description: Who was paid.
total_ttc:
type:
- integer
- 'null'
format: int64
description: Total paid, in cents.
vat_lines:
type: array
items:
$ref: '#/components/schemas/VatLineInput'
description: VAT per rate (10 lines at most).
ExpenseView:
type: object
description: An expense.
required:
- id
- status
- category
- currency
- total_ht
- total_vat
- vat_deductible
- vat_lines
- extraction_status
- created_at
- updated_at
properties:
category:
$ref: '#/components/schemas/CategoryView'
description: Advisory category.
confirmed_at:
type:
- string
- 'null'
description: RFC 3339 UTC, set once confirmed.
created_at:
type: string
description: RFC 3339 UTC.
currency:
type: string
description: Lower-case ISO currency code; only `eur` can be confirmed.
extraction_status:
type: string
description: '`none`, `read` (prefilled by AI) or `failed` (the read failed; fill it by hand).'
file_id:
type:
- string
- 'null'
format: uuid
description: Receipt in the file library.
id:
type: string
format: uuid
description: Expense identifier.
inbound_invoice_id:
type:
- string
- 'null'
format: uuid
description: Received e-invoice this expense was recorded from.
incurred_on:
type:
- string
- 'null'
description: Day the expense was incurred, `YYYY-MM-DD`.
reference:
type:
- string
- 'null'
description: The supplier's invoice or ticket number.
status:
$ref: '#/components/schemas/StatusView'
description: '`draft` or `confirmed`.'
supplier_name:
type:
- string
- 'null'
description: Who was paid.
total_ht:
type: integer
format: int64
description: Sum of the lines' bases, in cents.
total_ttc:
type:
- integer
- 'null'
format: int64
description: Total paid, in cents.
total_vat:
type: integer
format: int64
description: Sum of the lines' VAT, in cents.
updated_at:
type: string
description: RFC 3339 UTC.
vat_deductible:
type: integer
format: int64
description: Sum of the lines' recoverable VAT, in cents.
vat_lines:
type: array
items:
$ref: '#/components/schemas/VatLineView'
description: VAT per rate.
StatusView:
type: string
description: Expense lifecycle.
enum:
- draft
- confirmed
RegisterCategoryView:
type: object
description: Sums for one category.
required:
- category
- amounts
properties:
amounts:
$ref: '#/components/schemas/RegisterAmounts'
description: Its sums.
category:
$ref: '#/components/schemas/CategoryView'
description: The category.
RegisterAmounts:
type: object
description: Sums, in cents.
required:
- ht
- vat
- ttc
properties:
ht:
type: integer
format: int64
description: Before VAT.
ttc:
type: integer
format: int64
description: Total paid.
vat:
type: integer
format: int64
description: VAT paid.
vat_deductible:
type:
- integer
- 'null'
format: int64
description: Recoverable VAT; `null` when the org is in franchise en base.
RegisterRateView:
type: object
description: Sums for one VAT rate.
required:
- rate
- amounts
properties:
amounts:
$ref: '#/components/schemas/RegisterAmounts'
description: Its sums.
rate:
type: string
description: Rate in percent (`"20"`, `"5.5"`).
RegisterView:
type: object
description: The purchases register of a period.
required:
- from
- to
- expense_count
- total
- by_category
- by_rate
properties:
by_category:
type: array
items:
$ref: '#/components/schemas/RegisterCategoryView'
description: Per category, categories without expenses left out.
by_rate:
type: array
items:
$ref: '#/components/schemas/RegisterRateView'
description: Per VAT rate, highest first.
expense_count:
type: integer
format: int64
description: Confirmed expenses in the period.
from:
type: string
description: First day, `YYYY-MM-DD`.
to:
type: string
description: Last day, `YYYY-MM-DD`.
total:
$ref: '#/components/schemas/RegisterAmounts'
description: Everything.
vat_regime:
type:
- string
- 'null'
description: The org's VAT regime (`subject`, `franchise_base`, `real`) when known.
ErrorBody:
type: object
description: 'Generic error body returned by API handlers when they fail. `code` is a
stable machine-readable token; `message` is human-friendly and meant for
surfacing to end users.'
required:
- code
- message
properties:
code:
type: string
description: Stable machine token (e.g. `invalid_credentials`).
field:
type:
- string
- 'null'
description: Offending request field for validation errors, when known.
message:
type: string
description: Human-readable message.
ExpenseListView:
type: object
description: Response of `GET /v1/expenses`.
required:
- expenses
properties:
expenses:
type: array
items:
$ref: '#/components/schemas/ExpenseView'
description: Matching expenses, most recent first (200 at most).
CategoryView:
type: string
description: Advisory expense category.
enum:
- software
- hardware
- telecom
- travel
- meals
- fees
- insurance
- marketing
- rent
- training
- other
VatLineInput:
type: object
description: One VAT rate of an expense, as sent by the client.
required:
- rate
- base_cents
- vat_cents
properties:
base_cents:
type: integer
format: int64
description: Amount before VAT, in cents.
deductible_cents:
type:
- integer
- 'null'
format: int64
description: Recoverable part of the VAT, in cents; defaults to the whole VAT.
rate:
type: string
description: Rate in percent as a decimal token (`"20"`, `"5.5"`).
vat_cents:
type: integer
format: int64
description: VAT amount, in cents.
UpdateExpenseRequest:
type: object
description: 'Body of `PATCH /v1/expenses/{id}`. A missing field is left as it is; a blank
text clears it; `vat_lines`, when present, replaces all the lines.'
properties:
category:
oneOf:
- type: 'null'
- $ref: '#/components/schemas/CategoryView'
description: Advisory category.
currency:
type:
- string
- 'null'
description: ISO currency code.
incurred_on:
type:
- string
- 'null'
description: Day the expense was incurred, `YYYY-MM-DD`.
reference:
type:
- string
- 'null'
description: The supplier's invoice or ticket number.
supplier_name:
type:
- string
- 'null'
description: Who was paid.
total_ttc:
type:
- integer
- 'null'
format: int64
description: Total paid, in cents.
vat_lines:
type:
- array
- 'null'
items:
$ref: '#/components/schemas/VatLineInput'
description: New VAT lines, replacing the current ones.
securitySchemes:
api_key:
type: http
scheme: bearer
session:
type: apiKey
in: cookie
name: asap_session