Billy MCP by usefulapi
Read Billy invoices, bills, contacts, products and postings; create contacts and draft invoices.
我該用這個嗎
品質與安全性
根據工具定義與協定合規性的自動化分析。
上下文成本
這是每次將伺服器的工具載入模型上下文時所消耗的約略 token 數量。數量越高,可用於其他工作的注意力就越少。
安裝
一鍵安裝
將以下內容加入你的 `claude_desktop_config.json` 檔案:
{
"mcpServers": {
"billy": {
"url": "https://billy.usefulapi.io/mcp"
}
}
}遠端端點
https://billy.usefulapi.io/mcpstreamable-http它能做什麼
工具清單
工具(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.
輸入結構描述
{
"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.
輸入結構描述
{
"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}.
輸入結構描述
{
"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.
輸入結構描述
{
"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}.
輸入結構描述
{
"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.
輸入結構描述
{
"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}.
輸入結構描述
{
"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.
輸入結構描述
{
"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}.
輸入結構描述
{
"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.
輸入結構描述
{
"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.
輸入結構描述
{
"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.
輸入結構描述
{
"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.
輸入結構描述
{
"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.
輸入結構描述
{
"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.
輸入結構描述
{
"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"
}社群
證據