Billy MCP by usefulapi
Read Billy invoices, bills, contacts, products and postings; create contacts and draft invoices.
Sollte ich dies verwenden
Qualität und Sicherheit
Basierend auf einer automatisierten Analyse der Tool-Definitionen und der Einhaltung des Protokolls.
Kontextkosten
Dies ist die ungefähre Anzahl der Tokens, die jedes Mal verbraucht werden, wenn die Tools des Servers in den Kontext eines Modells geladen werden. Höhere Werte verringern die Aufmerksamkeit, die für andere Aufgaben verfügbar ist.
Installieren
Installation mit einem Klick
Fügen Sie dies Ihrer Datei `claude_desktop_config.json` hinzu:
{
"mcpServers": {
"billy": {
"url": "https://billy.usefulapi.io/mcp"
}
}
}Remote-Endpunkte
https://billy.usefulapi.io/mcpstreamable-httpWas es kann
Tool-Inventar
Tools (15)
🟢billy_get_organization
The Billy company the access token belongs to: id, name, address, registration (CVR) number, base currency, VAT settings, fiscal year, default payment terms, invoice numbering, default accounts. Good first call. GET /organization.
Eingabe-Schema
{
"type": "object",
"properties": {},
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢billy_list_contacts(search, page, page_size)
List customers and suppliers: name, type, address, CVR/registration number, EAN, payment terms, customer/supplier flags. The API has no documented search filter, so `search` is applied to the returned page only (case-insensitive on name, contact number and registration number); page on with next_page to look further. Paged. GET /contacts.
Eingabe-Schema
{
"type": "object",
"properties": {
"search": {
"description": "Keep only contacts on the returned page whose name, contactNo or registrationNo contains this text.",
"type": "string",
"minLength": 1,
"maxLength": 100
},
"page": {
"description": "Page number, 1-based (default 1). Use next_page from the previous reply.",
"type": "integer",
"minimum": 1,
"maximum": 100000
},
"page_size": {
"description": "Records per page, 1-200 (default 50).",
"type": "integer",
"minimum": 1,
"maximum": 200
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢billy_get_contact(id)
One contact by id, with its contact persons (names and e-mail addresses). GET /contacts/{id}.
Eingabe-Schema
{
"type": "object",
"properties": {
"id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{1,64}$",
"description": "The contact id (from billy_list_contacts)."
}
},
"required": [
"id"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢billy_list_invoices(state, contact_id, invoice_no, is_paid, min_entry_date, ...)
List sales invoices and credit notes (newest first by default): number, date, due date, state (draft/approved/voided), amount, tax, balance, isPaid, contactId, currency. Filter by state, customer, number, date, period, paid status or free text. Paged. GET /invoices.
Eingabe-Schema
{
"type": "object",
"properties": {
"state": {
"description": "Only invoices in this state.",
"type": "string",
"enum": [
"draft",
"approved",
"voided"
]
},
"contact_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{1,64}$",
"description": "Only invoices of this contact (from billy_list_contacts)."
},
"invoice_no": {
"description": "Exact invoice number.",
"type": "string",
"minLength": 1,
"maxLength": 50
},
"is_paid": {
"description": "true = only paid invoices, false = only unpaid.",
"type": "boolean"
},
"min_entry_date": {
"description": "Invoice date on or after (yyyy-mm-dd).",
"type": "string"
},
"max_entry_date": {
"description": "Invoice date on or before (yyyy-mm-dd).",
"type": "string"
},
"min_due_date": {
"description": "Due date on or after (yyyy-mm-dd).",
"type": "string"
},
"max_due_date": {
"description": "Due date on or before (yyyy-mm-dd); with is_paid=false this finds overdue invoices.",
"type": "string"
},
"entry_date_period": {
"type": "string",
"pattern": "^[A-Za-z0-9:.,-]{1,80}$",
"description": "Date period: all, year:2026, month:2026-03, quarter:2026-2, dates:2026-01-01...2026-01-31 ..."
},
"q": {
"description": "Free-text search over invoice number, order number, contact name, line description, amount.",
"type": "string",
"minLength": 1,
"maxLength": 100
},
"sort_property": {
"description": "Sort by (default entryDate).",
"type": "string",
"enum": [
"entryDate",
"dueDate",
"createdTime",
"invoiceNo",
"amount",
"balance",
"contact.name",
"approvedTime"
]
},
"sort_direction": {
"description": "Sort direction (default ASC).",
"type": "string",
"enum": [
"ASC",
"DESC"
]
},
"page": {
"description": "Page number, 1-based (default 1). Use next_page from the previous reply.",
"type": "integer",
"minimum": 1,
"maximum": 100000
},
"page_size": {
"description": "Records per page, 1-200 (default 50).",
"type": "integer",
"minimum": 1,
"maximum": 200
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢billy_get_invoice(id)
One invoice by id with its lines (product, description, quantity, unit price, amount, tax) and its payment associations. GET /invoices/{id}.
Eingabe-Schema
{
"type": "object",
"properties": {
"id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{1,64}$",
"description": "The invoice id (from billy_list_invoices)."
}
},
"required": [
"id"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢billy_list_bills(state, contact_id, is_paid, min_entry_date, max_entry_date, ...)
List bills (purchase invoices from suppliers): supplier, dates, state (draft/approved/voided), amount, balance, isPaid, supplier invoice number. Filter by state, supplier, dates or paid status. Paged. GET /bills.
Eingabe-Schema
{
"type": "object",
"properties": {
"state": {
"description": "Only bills in this state.",
"type": "string",
"enum": [
"draft",
"approved",
"voided"
]
},
"contact_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{1,64}$",
"description": "Only bills of this supplier contact."
},
"is_paid": {
"description": "true = only paid bills, false = only unpaid.",
"type": "boolean"
},
"min_entry_date": {
"description": "Bill date on or after (yyyy-mm-dd).",
"type": "string"
},
"max_entry_date": {
"description": "Bill date on or before (yyyy-mm-dd).",
"type": "string"
},
"min_due_date": {
"description": "Due date on or after (yyyy-mm-dd).",
"type": "string"
},
"max_due_date": {
"description": "Due date on or before (yyyy-mm-dd).",
"type": "string"
},
"suppliers_invoice_no": {
"description": "Exact supplier invoice number.",
"type": "string",
"minLength": 1,
"maxLength": 100
},
"q": {
"description": "Free-text search over supplier name, description, voucher number, amount, supplier invoice number.",
"type": "string",
"minLength": 1,
"maxLength": 100
},
"sort_property": {
"description": "Sort by (default entryDate).",
"type": "string",
"enum": [
"entryDate",
"dueDate",
"createdTime",
"amount",
"balance",
"contact.name",
"voucherNo",
"suppliersInvoiceNo"
]
},
"sort_direction": {
"description": "Sort direction (default ASC).",
"type": "string",
"enum": [
"ASC",
"DESC"
]
},
"page": {
"description": "Page number, 1-based (default 1). Use next_page from the previous reply.",
"type": "integer",
"minimum": 1,
"maximum": 100000
},
"page_size": {
"description": "Records per page, 1-200 (default 50).",
"type": "integer",
"minimum": 1,
"maximum": 200
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢billy_get_bill(id)
One supplier bill by id with its lines. GET /bills/{id}.
Eingabe-Schema
{
"type": "object",
"properties": {
"id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{1,64}$",
"description": "The bill id (from billy_list_bills)."
}
},
"required": [
"id"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢billy_list_products(search, page, page_size)
List products and services usable as invoice lines: name, product number, description, sales account, archived flag. The API has no documented search filter, so `search` is applied to the returned page only (name, productNo). Paged. GET /products.
Eingabe-Schema
{
"type": "object",
"properties": {
"search": {
"description": "Keep only products on the returned page whose name or productNo contains this text.",
"type": "string",
"minLength": 1,
"maxLength": 100
},
"page": {
"description": "Page number, 1-based (default 1). Use next_page from the previous reply.",
"type": "integer",
"minimum": 1,
"maximum": 100000
},
"page_size": {
"description": "Records per page, 1-200 (default 50).",
"type": "integer",
"minimum": 1,
"maximum": 200
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢billy_get_product(id)
One product by id with its unit prices per currency. GET /products/{id}.
Eingabe-Schema
{
"type": "object",
"properties": {
"id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{1,64}$",
"description": "The product id (from billy_list_products)."
}
},
"required": [
"id"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢billy_list_accounts(is_bank_account, page, page_size)
The chart of accounts: account number, name, group, nature, VAT rate, bank-account flag and bank details (IBAN, bank name) of bank accounts. With is_bank_account=true this lists the bank accounts whose ids billy_list_bank_lines needs. Paged. GET /accounts.
Eingabe-Schema
{
"type": "object",
"properties": {
"is_bank_account": {
"description": "true = only bank accounts.",
"type": "boolean"
},
"page": {
"description": "Page number, 1-based (default 1). Use next_page from the previous reply.",
"type": "integer",
"minimum": 1,
"maximum": 100000
},
"page_size": {
"description": "Records per page, 1-200 (default 50).",
"type": "integer",
"minimum": 1,
"maximum": 200
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢billy_list_tax_rates(page, page_size)
The company's VAT rates: name, rate (as a fraction, 0.25 = 25 percent), whether it applies to sales or purchases, active flag. Paged. GET /taxRates.
Eingabe-Schema
{
"type": "object",
"properties": {
"page": {
"description": "Page number, 1-based (default 1). Use next_page from the previous reply.",
"type": "integer",
"minimum": 1,
"maximum": 100000
},
"page_size": {
"description": "Records per page, 1-200 (default 50).",
"type": "integer",
"minimum": 1,
"maximum": 200
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢billy_list_bank_lines(account_id, is_reconciled, status, side, min_entry_date, ...)
List the bank-statement lines of ONE bank account (read only; nothing is matched or reconciled): date, description, amount, side (debit/credit), reconciled flag, receipt state. Get the account id from billy_list_accounts with is_bank_account=true. Paged. GET /bankLines.
Eingabe-Schema
{
"type": "object",
"properties": {
"account_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{1,64}$",
"description": "The bank account id (required)."
},
"is_reconciled": {
"description": "true = only reconciled lines, false = only unreconciled.",
"type": "boolean"
},
"status": {
"description": "Line status (the API defaults to booked).",
"type": "string",
"enum": [
"pending",
"booked"
]
},
"side": {
"description": "Only debit (money in) or credit (money out) lines.",
"type": "string",
"enum": [
"debit",
"credit"
]
},
"min_entry_date": {
"description": "Entry date on or after (yyyy-mm-dd).",
"type": "string"
},
"max_entry_date": {
"description": "Entry date on or before (yyyy-mm-dd).",
"type": "string"
},
"entry_date_period": {
"type": "string",
"pattern": "^[A-Za-z0-9:.,-]{1,80}$",
"description": "Date period: all, year:2026, month:2026-03, quarter:2026-2, dates:2026-01-01...2026-01-31 ..."
},
"min_amount": {
"description": "Amount at least.",
"type": "number",
"minimum": 0,
"maximum": 1000000000000
},
"max_amount": {
"description": "Amount at most.",
"type": "number",
"minimum": 0,
"maximum": 1000000000000
},
"receipt_state": {
"description": "Only lines with a missing or uploaded receipt.",
"type": "string",
"enum": [
"missing_receipt",
"receipt_uploaded"
]
},
"q": {
"description": "Free-text search over description or amount.",
"type": "string",
"minLength": 1,
"maxLength": 100
},
"sort_property": {
"description": "Sort by (default entryDate).",
"type": "string",
"enum": [
"entryDate",
"amount"
]
},
"sort_direction": {
"description": "Sort direction (default ASC).",
"type": "string",
"enum": [
"ASC",
"DESC"
]
},
"page": {
"description": "Page number, 1-based (default 1). Use next_page from the previous reply.",
"type": "integer",
"minimum": 1,
"maximum": 100000
},
"page_size": {
"description": "Records per page, 1-200 (default 50).",
"type": "integer",
"minimum": 1,
"maximum": 200
}
},
"required": [
"account_id"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢billy_list_postings(account_id, min_entry_date, max_entry_date, entry_date_period, is_voided, ...)
List ledger postings (the bookkeeping entries): date, text, account, amount, side (debit/credit), currency, voided flag. Filter by account, date or period. Read only. Paged. GET /postings.
Eingabe-Schema
{
"type": "object",
"properties": {
"account_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{1,64}$",
"description": "Only postings on this account (from billy_list_accounts)."
},
"min_entry_date": {
"description": "Entry date on or after (yyyy-mm-dd).",
"type": "string"
},
"max_entry_date": {
"description": "Entry date on or before (yyyy-mm-dd).",
"type": "string"
},
"entry_date_period": {
"type": "string",
"pattern": "^[A-Za-z0-9:.,-]{1,80}$",
"description": "Date period: all, year:2026, month:2026-03, quarter:2026-2, dates:2026-01-01...2026-01-31 ..."
},
"is_voided": {
"description": "true = only voided postings, false = only live ones.",
"type": "boolean"
},
"q": {
"description": "Free-text search over the posting text and the originator name.",
"type": "string",
"minLength": 1,
"maxLength": 100
},
"page": {
"description": "Page number, 1-based (default 1). Use next_page from the previous reply.",
"type": "integer",
"minimum": 1,
"maximum": 100000
},
"page_size": {
"description": "Records per page, 1-200 (default 50).",
"type": "integer",
"minimum": 1,
"maximum": 200
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🔴billy_create_contact(name, type, country_id, street, zipcode, ...)
WRITE: create ONE new contact (customer and/or supplier) in the company's Billy account. It does not check for duplicates (call billy_list_contacts first) and nothing is sent to the contact. Not idempotent: a repeat call creates a second contact. POST /contacts.
Eingabe-Schema
{
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 255,
"description": "Company or person name."
},
"type": {
"description": "company (default) or person.",
"type": "string",
"enum": [
"company",
"person"
]
},
"country_id": {
"description": "ISO country code (default DK).",
"type": "string",
"pattern": "^[A-Z]{2}$"
},
"street": {
"description": "Street and number.",
"type": "string",
"maxLength": 255
},
"zipcode": {
"description": "Postal code.",
"type": "string",
"maxLength": 20
},
"city": {
"description": "City.",
"type": "string",
"maxLength": 255
},
"phone": {
"description": "Phone number.",
"type": "string",
"maxLength": 50
},
"registration_no": {
"description": "CVR number (Denmark) or EU VAT number.",
"type": "string",
"maxLength": 50
},
"ean": {
"description": "EAN location number for e-invoicing (Denmark).",
"type": "string",
"maxLength": 20
},
"contact_no": {
"description": "Your own customer or supplier number.",
"type": "string",
"maxLength": 50
},
"email": {
"description": "Primary contact e-mail (stored as the primary contact person; nothing is sent).",
"type": "string",
"maxLength": 255,
"format": "email",
"pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
},
"is_customer": {
"description": "Customer flag (default true).",
"type": "boolean"
},
"is_supplier": {
"description": "Supplier flag (default false).",
"type": "boolean"
}
},
"required": [
"name"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🔴billy_create_draft_invoice(contact_id, entry_date, currency_id, tax_mode, contact_message, ...)
WRITE: create ONE invoice in the DRAFT state for an existing contact. The invoice is NOT approved, booked, numbered into the ledger or sent: the user reviews it in Billy and approves and sends it there. The invoice number is assigned by Billy. No payment is created. Not idempotent: a repeat call creates a second draft. POST /invoices with state=draft.
Eingabe-Schema
{
"type": "object",
"properties": {
"contact_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{1,64}$",
"description": "The customer's contact id (from billy_list_contacts or billy_create_contact)."
},
"entry_date": {
"description": "Invoice date yyyy-mm-dd (default today, UTC).",
"type": "string"
},
"currency_id": {
"description": "Invoice currency, e.g. DKK (default: the company's base currency).",
"type": "string",
"pattern": "^[A-Z]{3}$"
},
"tax_mode": {
"description": "Whether unit prices include (incl) or exclude (excl) VAT (default: the company's setting).",
"type": "string",
"enum": [
"incl",
"excl"
]
},
"contact_message": {
"description": "Message to the customer shown at the top of the invoice PDF.",
"type": "string",
"maxLength": 2000
},
"lines": {
"minItems": 1,
"maxItems": 100,
"type": "array",
"items": {
"type": "object",
"properties": {
"product_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{1,64}$",
"description": "The product id (from billy_list_products)."
},
"unit_price": {
"type": "number",
"minimum": -1000000000,
"maximum": 1000000000,
"description": "Price per unit in the invoice currency (VAT excluded unless tax_mode is incl)."
},
"quantity": {
"description": "Quantity (default 1).",
"type": "number",
"exclusiveMinimum": 0,
"maximum": 1000000000
},
"description": {
"description": "Text shown under the product name on the invoice.",
"type": "string",
"maxLength": 2000
}
},
"required": [
"product_id",
"unit_price"
]
},
"description": "1-100 invoice lines."
}
},
"required": [
"contact_id",
"lines"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
}Community
Nachweis