Skip to main content
Glama
ohneben's Wafeq MCP

ohneben's Wafeq MCP

ohneben's Wafeq MCP

Buy Me A Coffee


License & checks

CI License: MIT

MCP registries

MCP Registry Listed on mcpservers.org Wafeq-MCP MCP server

Run your Wafeq books in plain language from AI assistants like Claude, Cursor, and any other MCP client.

This Model Context Protocol server exposes the Wafeq Public API β€” all 251 endpoints, generated straight from the OpenAPI spec into MCP tools, plus two hand-written ones. Every tool carries a safety category (🟒 read-only / 🟑 write / 🟠 state change / πŸ”΄ irreversible or destructive) so your assistant knows what an action does before it calls it β€” including the difference between saving an invoice and filing it with a tax authority, which no CRUD-shaped wrapper can tell you. It runs over stdio (Claude Desktop and other local launchers) or Streamable HTTP (hosted in Docker), and ships with retries, client-side rate limiting, request timeouts, idempotency keys, multipart upload and binary PDF handling so it holds up against a live book.

Why you'll want this

Some MCP servers just forward an API. This one is built to be safe to hand to an LLM and easy to run against real accounting data:

What you get

Why it matters

All 251 endpoints, spec-driven

Full coverage of invoices, bills, quotes, credit and debit notes, payments, banking, journals, payroll, projects, inventory and reports β€” nothing hand-picked or left behind.

Nine safety categories, not four 🟒 / 🟑 / 🟠 / πŸ”΄

A dozen of Wafeq's POSTs are not creates. Previews write nothing; ending an amortization early posts to the ledger with no undo; reporting an invoice to a tax authority leaves your organization permanently. Each gets its own banner instead of being lumped in with "create".

Server instructions sent on connect

The client is told how to read the safety banners and the handful of Wafeq conventions β€” date format, decimal separator, whole-period report ranges β€” up front, instead of discovering them by getting a call wrong first.

Machine-readable MCP annotations (readOnlyHint, destructiveHint)

Hosts that honor annotations (Claude included) can auto-trust the 98 read-only tools and demand confirmation before any of the 44 that delete or cannot be undone.

Correct report parameters, per report

Each of the four reports gets its own schema: balance sheet takes date + period_count; profit-and-loss and cash flow take date_after + date_before; trial balance takes from_date + to_date. Wafeq silently ignores misspelled query parameters, so a wrong name looks like a working call.

Whole-period validation before sending

Profit-and-loss and cash flow reject ranges that don't align to whole months or years. The server checks locally and replies with the nearest valid range instead of spending a round trip on an HTTP 400.

Automatic idempotency keys

Every one of the 146 write endpoints that supports X-Wafeq-Idempotency-Key gets a UUID v4 automatically, reused across retries β€” so a network hiccup can never duplicate an invoice. Supply your own to make a deliberate re-run safe too.

File uploads that actually work

POST /files/ is multipart-only and POST /files/raw/ needs a Content-Disposition header. Both are handled; you pass base64 content and a filename.

Binary PDFs handled as bytes

The nine PDF endpoints are base64-encoded into a small envelope with size and content type, instead of being read as text and corrupted.

Automatic retries with backoff

Transient 429 / 5xx responses are retried with jittered exponential backoff, honoring Retry-After β€” with the same idempotency key, exactly as Wafeq's integration guide requires.

Built-in rate limiting

Self-throttles so a burst of tool calls doesn't trip a 429. Wafeq publishes no numeric limit, so the default is deliberately conservative and configurable.

Tenant verified at startup

A Wafeq API key is organization-scoped. The server calls GET /organization/ before serving and publishes the result on /health, so a mis-set key shows up as a name you can check rather than as writes against the wrong company's books.

Two transports: stdio and Streamable HTTP

Use it locally in Claude Desktop, or run one always-on server that any number of MCP clients reach over HTTP.

Docker + docker-compose, health check, auto-restart

docker compose up and it stays up, bound to localhost only.

Optional bearer-token auth on the HTTP endpoint

Put the server behind a shared secret the moment it's reachable beyond localhost.

Your secrets never reach the model

Credentials live in the server's environment and are injected on every request. The passthrough tool cannot override Authorization or point the credential at another host.

Drop-in spec updates

Wafeq ships a newer spec? Replace one file and rebuild β€” new endpoints become new tools automatically, no code changes.

How it compares

Capability

This project

Generic OpenAPI→MCP wrapper*

All 251 Wafeq endpoints as tools

βœ…

βœ…

Per-tool safety category + banner

βœ…

❌

Tax-authority filing flagged as irreversible, not "create"

βœ…

❌

readOnlyHint / destructiveHint MCP annotations

βœ…

βž–

Read-only fields stripped from create/update bodies

βœ…

❌

Duplicated enum prose compacted out of schemas

βœ…

❌

Correct, per-report date parameters

βœ…

βœ…

Whole-period range validated before sending

βœ…

❌

Automatic X-Wafeq-Idempotency-Key, stable across retries

βœ…

❌

Multipart + raw-binary file upload

βœ…

βž–

Binary PDF responses base64-encoded, not mangled

βœ…

βž–

Transaction dates recovered for journal line items

βœ…

❌

Automatic retries on 429 / 5xx (honors Retry-After)

βœ…

❌

Client-side rate limiting

βœ…

❌

Organization identity verified at startup

βœ…

❌

stdio transport

βœ…

βœ…

Streamable-HTTP transport

βœ…

βž–

Docker + docker-compose, health check, auto-restart

βœ…

❌

Optional bearer-token auth on the endpoint

βœ…

❌

License

MIT

varies

*Generic OpenAPIβ†’MCP wrappers turn any spec into MCP tools. They can reach the same endpoints, but treat every operation identically β€” and against Wafeq's spec specifically they inherit the read-only-required-field problem described in MIGRATION.md. "βž–" = varies by tool / not guaranteed.

Related MCP server: MCP Holded

What you can do

Once it's connected, ask your assistant things like:

  • "What was our profit and loss for the first half of this year?"

  • "Show me every unpaid invoice older than 30 days, with the customer name."

  • "Create a draft invoice for Acme Ltd for 3 days of consulting at €800/day."

  • "Download invoice INV-2026-014 as a PDF."

  • "Which account did the €7,000 transfer in January post to?"

  • "Attach this receipt to expense EXP-118."

  • "Reconcile the bank statement lines for March against the ledger."

  • "Convert quote QUO-31 to an invoice and record the payment."

How it works

Claude / Cursor / any MCP client  ──MCP──►  this server  ──HTTPS──►  Wafeq API (your organization)

At startup the server parses the bundled OpenAPI spec into MCP tools β€” resolving $refs, guarding against recursive schemas, and stripping server-assigned (readOnly) fields out of request bodies β€” tags each tool with its safety category, verifies which Wafeq organization the credentials belong to, and then injects your credential on every outgoing request. Your key stays in the server's environment; the model never sees or handles it.

Requirements

  • A Wafeq organization with API access β€” either a private API key (Wafeq β†’ Settings β†’ Developer β†’ API keys) or an OAuth2 access token. See Get your API credentials.

  • Docker (Docker Desktop on macOS/Windows) for the quick start below β€” or Node.js β‰₯ 20 to run from source.

Quick start (Docker)

1. Add your credentials. Copy the example config and fill it in:

cp .env.example .env

Then edit .env and set WAFEQ_API_KEY. Unless HOST is a loopback address the server also requires MCP_AUTH_TOKEN and refuses to start without one, so set it to a long random string: MCP_AUTH_TOKEN=$(openssl rand -hex 32).

2. Start the server:

docker compose up -d --build

docker-compose.yml binds to 127.0.0.1:8765 only, so the server is reachable from your machine but not from the network.

3. Confirm it's running β€” and that it's pointed at the right books:

curl -s http://localhost:8765/health
{
  "status": "ok",
  "server": "wafeq-mcp",
  "version": "2.0.0",
  "tools": 253,
  "organization": {
    "status": "ok",
    "id": "org_...",
    "name": "Your Company FZCO",
    "base_currency": "EUR",
    "country": "AE"
  },
  "auth_required": false
}

Check the name field. That is the organization your key writes to. If it isn't the company you expected, stop and fix the key before doing anything else. /health answers 503 and "status": "degraded" when the credentials can't be verified.

4. Point your MCP client at it: http://localhost:8765/mcp (Streamable HTTP).

Remote endpoints are added to Claude as a custom connector (Settings β†’ Connectors), or bridged locally with mcp-remote. For the bridge, add this under mcpServers in your client config and restart the app completely:

{
  "mcpServers": {
    "wafeq": {
      "command": "npx",
      "args": [
        "mcp-remote",
        "http://localhost:8765/mcp",
        "--header", "Authorization: Bearer YOUR_MCP_AUTH_TOKEN"
      ]
    }
  }
}

(Drop the --header line only if the server runs without a token, which it allows on a loopback bind alone.)

Prefer a ready-made image?

Every release publishes a ready-to-run image to the GitHub Container Registry, so you can skip the local build entirely:

docker run -d --name wafeq-mcp -p 127.0.0.1:8765:8765 --env-file .env \
  ghcr.io/ohneben/wafeq-mcp:latest

Pin a version (:2.0.0) rather than latest if you want releases to be something you opt into.

Install from the MCP Registry

The server is published to the MCP Registry as io.github.ohneben/wafeq-mcp, so registry-aware clients can install it by name. The registry entry launches the image over stdio β€” see Run the container over stdio for the equivalent hand-written config.

curl -s "https://registry.modelcontextprotocol.io/v0.1/servers/io.github.ohneben%2Fwafeq-mcp/versions/latest"

Get your API credentials

Private API key (most people): in Wafeq, go to Settings β†’ Developer β†’ API keys and create a key. It is scoped to one organization. Put it in .env as WAFEQ_API_KEY; the server sends it as Authorization: Api-Key <key>.

OAuth2 app: if you have an access token from a Wafeq OAuth2 app, put it in .env as WAFEQ_ACCESS_TOKEN instead. The server switches to Authorization: Bearer <token> automatically. Set WAFEQ_AUTH_SCHEME only if you need to force one scheme while both variables are present.

Configuration

All configuration is environment variables. Everything except the credential has a working default.

Variable

Default

What it does

WAFEQ_API_KEY

β€”

Private organization API key. Sent as Api-Key <key>. One credential is required.

WAFEQ_ACCESS_TOKEN

β€”

OAuth2 access token. Sent as Bearer <token>. Takes precedence over WAFEQ_API_KEY.

WAFEQ_AUTH_SCHEME

auto

Force api-key or bearer. Normally leave unset.

WAFEQ_API_BASE_URL

https://api.wafeq.com/v1

Wafeq API base URL.

WAFEQ_OPENAPI_PATH

bundled spec

Use a different OpenAPI document (JSON or YAML).

MCP_TRANSPORT

stdio

stdio or http. Docker sets http.

PORT

8765

HTTP listen port.

HOST

0.0.0.0

HTTP bind address.

MCP_HTTP_PATH

/mcp

Path the MCP endpoint is served on.

MCP_AUTH_TOKEN

β€”

Bearer token required on /mcp. Required unless HOST is a loopback address, otherwise the server refuses to start. Renamed from MCP_SHARED_TOKEN in 2.1.0.

MCP_ALLOWED_HOSTS

β€”

Comma-separated hostnames the Host header may carry. Empty lets the server derive it: the loopback names on a loopback bind, no check behind a reverse proxy.

MCP_ALLOW_INSECURE

0

Start without a token on a non-loopback bind. Only for a port that genuinely is not reachable by anyone else.

MCP_BODY_LIMIT

25mb

Largest accepted request body.

MCP_SESSION_TTL

1800

Seconds an idle session is kept before it is swept.

MCP_MAX_SESSIONS

256

Concurrent sessions before the least recently used one is evicted.

WAFEQ_TOOL_GROUPS

β€”

Comma-separated resource groups to expose, e.g. invoices,bills,reports. Empty = all 251. Run npm run list-tools for the list.

WAFEQ_MAX_REQUESTS

20

Client-side rate limit: requests per window. 0 disables throttling.

WAFEQ_RATE_WINDOW_MS

10000

Rate-limit window in milliseconds.

WAFEQ_MAX_RETRIES

3

Retries on 429 / 5xx / network errors.

WAFEQ_TIMEOUT_MS

30000

Per-attempt request timeout.

WAFEQ_ALLOW_LOCAL_FILE_UPLOAD

false

Allow upload tools to read this machine's filesystem via file_path. See Security.

WAFEQ_MAX_UPLOAD_BYTES

26214400

Maximum decoded upload size (25 MiB).

Too many tools?

251 tools is a lot. The full catalogue is about 0.5 MB of JSON (~133k tokens) on tools/list, and some hosts get slower or less accurate with that many. Two things help.

The schemas are already compacted. Wafeq's spec renders every enum's values into its description as well as into enum β€” the currency list alone is ~4 KB, inlined at 203 places. The generator collapses those single-member allOf wrappers and drops the duplicated bullet lists, which takes ~29% off the payload without removing a single allowed value.

Narrow the catalogue if you still want it smaller β€” no code changes needed:

WAFEQ_TOOL_GROUPS=invoices,bills,contacts,payments,reports,accounts,items,tax-rates

The two hand-written tools are always available, so nothing becomes unreachable β€” anything you filter out can still be called through wafeq_request.

Tool safety categories

Every tool's description opens with a banner, and every tool carries the matching MCP annotations. Counts are for the bundled spec (251 generated + 2 hand-written = 253).

Banner

Tools

readOnlyHint

destructiveHint

What it covers

🟒 READ-ONLY

85

βœ…

❌

Every GET, plus the account-ledger convenience tool.

🟒 READ-ONLY · returns a PDF

9

βœ…

❌

The PDF downloads: invoice, simplified invoice, credit note, debit note, bill, quote, purchase order, payment, payslip. Returned base64-encoded.

🟒 READ-ONLY · preview / simulation

4

βœ…

❌

Amortization and revenue-recognition previews. POST, but documented as writing nothing.

🟑 WRITE · creates data

39

❌

❌

Collection creates, both file uploads, and the two conversions (quote→invoice, purchase order→bill). Not idempotent by nature — hence the automatic idempotency key.

🟑 WRITE · updates data

70

❌

❌

Every PUT and PATCH.

🟠 STATE CHANGE · moves a document in or out of the ledger

2

❌

❌

Mark expense posted / draft. Reversible β€” each undoes the other.

πŸ”΄ IRREVERSIBLE Β· files the document with an external tax authority

3

❌

βœ…

Report invoice / credit note / simplified invoice to the tax authority. Leaves your organization and cannot be recalled.

πŸ”΄ IRREVERSIBLE Β· posts the remaining balance to the ledger

2

❌

βœ…

End amortization / revenue recognition early. No API undo β€” run the matching preview first.

πŸ”΄ DESTRUCTIVE Β· deletes

39

❌

βœ…

Every DELETE, plus the wafeq_request passthrough (its effect can't be known in advance).

253

98

44

The three πŸ”΄ groups all set destructiveHint: true, so a host that honors annotations stops and asks before any of them β€” not just before deletions. Filing an invoice with a tax authority is at least as consequential as deleting one, and unlike a deletion it reaches outside your organization.

Print the live catalogue any time, without credentials:

npm run list-tools

Tool

Endpoint

wafeq_account_ledger

hand-written

wafeq_accounts_list

GET /accounts/

wafeq_accounts_retrieve

GET /accounts/{id}/

wafeq_amortizations_list

GET /amortizations/

wafeq_amortizations_retrieve

GET /amortizations/{id}/

wafeq_bank_accounts_ledger_transactions_list

GET /bank-accounts/{bank_account_id}/ledger-transactions/

wafeq_bank_accounts_ledger_transactions_retrieve

GET /bank-accounts/{bank_account_id}/ledger-transactions/{id}/

wafeq_bank_accounts_list

GET /bank-accounts/

wafeq_bank_accounts_retrieve

GET /bank-accounts/{id}/

wafeq_bank_accounts_statement_transactions_list

GET /bank-accounts/{bank_account_id}/statement-transactions/

wafeq_bank_accounts_statement_transactions_retrieve

GET /bank-accounts/{bank_account_id}/statement-transactions/{id}/

wafeq_beneficiaries_list

GET /beneficiaries/

wafeq_beneficiaries_retrieve

GET /beneficiaries/{id}/

wafeq_bills_line_items_list

GET /bills/{bill_id}/line-items/

wafeq_bills_line_items_retrieve

GET /bills/{bill_id}/line-items/{id}/

wafeq_bills_list

GET /bills/

wafeq_bills_retrieve

GET /bills/{id}/

wafeq_branches_list

GET /branches/

wafeq_branches_retrieve

GET /branches/{id}/

wafeq_contacts_list

GET /contacts/

wafeq_contacts_retrieve

GET /contacts/{id}/

wafeq_cost_centers_list

GET /cost-centers/

wafeq_cost_centers_retrieve

GET /cost-centers/{id}/

wafeq_credit_notes_line_items_list

GET /credit-notes/{credit_note_id}/line-items/

wafeq_credit_notes_line_items_retrieve

GET /credit-notes/{credit_note_id}/line-items/{id}/

wafeq_credit_notes_list

GET /credit-notes/

wafeq_credit_notes_retrieve

GET /credit-notes/{id}/

wafeq_custom_fields_list

GET /custom-fields/

wafeq_custom_fields_retrieve

GET /custom-fields/{id}/

wafeq_debit_notes_line_items_list

GET /debit-notes/{debit_note_id}/line-items/

wafeq_debit_notes_line_items_retrieve

GET /debit-notes/{debit_note_id}/line-items/{id}/

wafeq_debit_notes_list

GET /debit-notes/

wafeq_debit_notes_retrieve

GET /debit-notes/{id}/

wafeq_employees_list

GET /employees/

wafeq_employees_retrieve

GET /employees/{id}/

wafeq_expenses_list

GET /expenses/

wafeq_expenses_retrieve

GET /expenses/{id}/

wafeq_files_list

GET /files/

wafeq_files_retrieve

GET /files/{id}/

wafeq_invoices_line_items_list

GET /invoices/{invoice_id}/line-items/

wafeq_invoices_line_items_retrieve

GET /invoices/{invoice_id}/line-items/{id}/

wafeq_invoices_list

GET /invoices/

wafeq_invoices_retrieve

GET /invoices/{id}/

wafeq_item_units_of_measure_list

GET /item-units-of-measure/

wafeq_item_units_of_measure_retrieve

GET /item-units-of-measure/{id}/

wafeq_items_list

GET /items/

wafeq_items_retrieve

GET /items/{id}/

wafeq_journal_line_items_list

GET /journal-line-items/

wafeq_journal_line_items_retrieve

GET /journal-line-items/{id}/

wafeq_manual_journals_list

GET /manual-journals/

wafeq_manual_journals_retrieve

GET /manual-journals/{id}/

wafeq_organization_retrieve

GET /organization/

wafeq_payment_requests_list

GET /payment_requests/

wafeq_payment_requests_retrieve

GET /payment_requests/{id}/

wafeq_payments_list

GET /payments/

wafeq_payments_retrieve

GET /payments/{id}/

wafeq_payslips_list

GET /payslips/

wafeq_payslips_pay_items_list

GET /payslips/{payslip_id}/pay-items/

wafeq_payslips_pay_items_retrieve

GET /payslips/{payslip_id}/pay-items/{id}/

wafeq_payslips_retrieve

GET /payslips/{id}/

wafeq_projects_list

GET /projects/

wafeq_projects_retrieve

GET /projects/{id}/

wafeq_purchase_orders_line_items_list

GET /purchase-orders/{purchase_order_id}/line-items/

wafeq_purchase_orders_line_items_retrieve

GET /purchase-orders/{purchase_order_id}/line-items/{id}/

wafeq_purchase_orders_list

GET /purchase-orders/

wafeq_purchase_orders_retrieve

GET /purchase-orders/{id}/

wafeq_quotes_line_items_list

GET /quotes/{quote_id}/line-items/

wafeq_quotes_line_items_retrieve

GET /quotes/{quote_id}/line-items/{id}/

wafeq_quotes_list

GET /quotes/

wafeq_quotes_retrieve

GET /quotes/{id}/

wafeq_reports_balance_sheet_list

GET /reports/balance-sheet/

wafeq_reports_cash_flow_list

GET /reports/cash-flow/

wafeq_reports_profit_and_loss_list

GET /reports/profit-and-loss/

wafeq_reports_trial_balance_list

GET /reports/trial-balance/

wafeq_revenue_recognitions_list

GET /revenue-recognitions/

wafeq_revenue_recognitions_retrieve

GET /revenue-recognitions/{id}/

wafeq_simplified_invoices_line_items_list

GET /simplified-invoices/{invoice_id}/line-items/

wafeq_simplified_invoices_line_items_retrieve

GET /simplified-invoices/{invoice_id}/line-items/{id}/

wafeq_simplified_invoices_list

GET /simplified-invoices/

wafeq_simplified_invoices_retrieve

GET /simplified-invoices/{id}/

wafeq_tax_rates_list

GET /tax-rates/

wafeq_units_of_measure_list

GET /units-of-measure/

wafeq_units_of_measure_retrieve

GET /units-of-measure/{id}/

wafeq_warehouses_list

GET /warehouses/

wafeq_warehouses_retrieve

GET /warehouses/{id}/

Tool

Endpoint

wafeq_bills_download_retrieve

GET /bills/{id}/download/

wafeq_credit_notes_download_retrieve

GET /credit-notes/{id}/download/

wafeq_debit_notes_download_retrieve

GET /debit-notes/{id}/download/

wafeq_invoices_download_retrieve

GET /invoices/{id}/download/

wafeq_payments_download_retrieve

GET /payments/{id}/download/

wafeq_payslips_download_retrieve

GET /payslips/{id}/download/

wafeq_purchase_orders_download_retrieve

GET /purchase-orders/{id}/download/

wafeq_quotes_download_retrieve

GET /quotes/{id}/download/

wafeq_simplified_invoices_download_retrieve

GET /simplified-invoices/{id}/download/

Tool

Endpoint

wafeq_amortizations_preview_create

POST /amortizations/preview/

wafeq_amortizations_preview_end_early_create

POST /amortizations/{id}/preview-end-early/

wafeq_revenue_recognitions_preview_create

POST /revenue-recognitions/preview/

wafeq_revenue_recognitions_preview_end_early_create

POST /revenue-recognitions/{id}/preview-end-early/

Tool

Endpoint

wafeq_accounts_create

POST /accounts/

wafeq_bank_accounts_create

POST /bank-accounts/

wafeq_bank_accounts_ledger_transactions_create

POST /bank-accounts/{bank_account_id}/ledger-transactions/

wafeq_bank_accounts_statement_transactions_create

POST /bank-accounts/{bank_account_id}/statement-transactions/

wafeq_beneficiaries_create

POST /beneficiaries/

wafeq_bills_create

POST /bills/

wafeq_bills_line_items_create

POST /bills/{bill_id}/line-items/

wafeq_branches_create

POST /branches/

wafeq_contacts_create

POST /contacts/

wafeq_cost_centers_create

POST /cost-centers/

wafeq_credit_notes_create

POST /credit-notes/

wafeq_credit_notes_line_items_create

POST /credit-notes/{credit_note_id}/line-items/

wafeq_custom_fields_create

POST /custom-fields/

wafeq_debit_notes_create

POST /debit-notes/

wafeq_debit_notes_line_items_create

POST /debit-notes/{debit_note_id}/line-items/

wafeq_employees_create

POST /employees/

wafeq_expenses_create

POST /expenses/

wafeq_invoices_create

POST /invoices/

wafeq_invoices_line_items_create

POST /invoices/{invoice_id}/line-items/

wafeq_item_units_of_measure_create

POST /item-units-of-measure/

wafeq_items_create

POST /items/

wafeq_manual_journals_create

POST /manual-journals/

wafeq_payment_requests_create

POST /payment_requests/

wafeq_payments_create

POST /payments/

wafeq_payslips_create

POST /payslips/

wafeq_payslips_pay_items_create

POST /payslips/{payslip_id}/pay-items/

wafeq_projects_create

POST /projects/

wafeq_purchase_orders_bill_create

POST /purchase-orders/{id}/bill/

wafeq_purchase_orders_create

POST /purchase-orders/

wafeq_purchase_orders_line_items_create

POST /purchase-orders/{purchase_order_id}/line-items/

wafeq_quotes_create

POST /quotes/

wafeq_quotes_invoice_create

POST /quotes/{id}/invoice/

wafeq_quotes_line_items_create

POST /quotes/{quote_id}/line-items/

wafeq_simplified_invoices_create

POST /simplified-invoices/

wafeq_simplified_invoices_line_items_create

POST /simplified-invoices/{invoice_id}/line-items/

wafeq_units_of_measure_create

POST /units-of-measure/

wafeq_upload_file

POST /files/

wafeq_upload_file_raw

POST /files/raw/

wafeq_warehouses_create

POST /warehouses/

Tool

Endpoint

wafeq_accounts_partial_update

PATCH /accounts/{id}/

wafeq_accounts_update

PUT /accounts/{id}/

wafeq_bank_accounts_ledger_transactions_partial_update

PATCH /bank-accounts/{bank_account_id}/ledger-transactions/{id}/

wafeq_bank_accounts_ledger_transactions_update

PUT /bank-accounts/{bank_account_id}/ledger-transactions/{id}/

wafeq_bank_accounts_partial_update

PATCH /bank-accounts/{id}/

wafeq_bank_accounts_statement_transactions_partial_update

PATCH /bank-accounts/{bank_account_id}/statement-transactions/{id}/

wafeq_bank_accounts_statement_transactions_update

PUT /bank-accounts/{bank_account_id}/statement-transactions/{id}/

wafeq_bank_accounts_update

PUT /bank-accounts/{id}/

wafeq_beneficiaries_partial_update

PATCH /beneficiaries/{id}/

wafeq_beneficiaries_update

PUT /beneficiaries/{id}/

wafeq_bills_line_items_partial_update

PATCH /bills/{bill_id}/line-items/{id}/

wafeq_bills_line_items_update

PUT /bills/{bill_id}/line-items/{id}/

wafeq_bills_partial_update

PATCH /bills/{id}/

wafeq_bills_update

PUT /bills/{id}/

wafeq_branches_partial_update

PATCH /branches/{id}/

wafeq_branches_update

PUT /branches/{id}/

wafeq_contacts_partial_update

PATCH /contacts/{id}/

wafeq_contacts_update

PUT /contacts/{id}/

wafeq_cost_centers_partial_update

PATCH /cost-centers/{id}/

wafeq_cost_centers_update

PUT /cost-centers/{id}/

wafeq_credit_notes_line_items_partial_update

PATCH /credit-notes/{credit_note_id}/line-items/{id}/

wafeq_credit_notes_line_items_update

PUT /credit-notes/{credit_note_id}/line-items/{id}/

wafeq_credit_notes_partial_update

PATCH /credit-notes/{id}/

wafeq_credit_notes_update

PUT /credit-notes/{id}/

wafeq_custom_fields_partial_update

PATCH /custom-fields/{id}/

wafeq_custom_fields_update

PUT /custom-fields/{id}/

wafeq_debit_notes_line_items_partial_update

PATCH /debit-notes/{debit_note_id}/line-items/{id}/

wafeq_debit_notes_line_items_update

PUT /debit-notes/{debit_note_id}/line-items/{id}/

wafeq_debit_notes_partial_update

PATCH /debit-notes/{id}/

wafeq_debit_notes_update

PUT /debit-notes/{id}/

wafeq_employees_partial_update

PATCH /employees/{id}/

wafeq_employees_update

PUT /employees/{id}/

wafeq_expenses_partial_update

PATCH /expenses/{id}/

wafeq_expenses_update

PUT /expenses/{id}/

wafeq_invoices_line_items_partial_update

PATCH /invoices/{invoice_id}/line-items/{id}/

wafeq_invoices_line_items_update

PUT /invoices/{invoice_id}/line-items/{id}/

wafeq_invoices_partial_update

PATCH /invoices/{id}/

wafeq_invoices_update

PUT /invoices/{id}/

wafeq_item_units_of_measure_partial_update

PATCH /item-units-of-measure/{id}/

wafeq_item_units_of_measure_update

PUT /item-units-of-measure/{id}/

wafeq_items_partial_update

PATCH /items/{id}/

wafeq_items_update

PUT /items/{id}/

wafeq_manual_journals_partial_update

PATCH /manual-journals/{id}/

wafeq_manual_journals_update

PUT /manual-journals/{id}/

wafeq_payment_requests_partial_update

PATCH /payment_requests/{id}/

wafeq_payment_requests_update

PUT /payment_requests/{id}/

wafeq_payments_partial_update

PATCH /payments/{id}/

wafeq_payments_update

PUT /payments/{id}/

wafeq_payslips_partial_update

PATCH /payslips/{id}/

wafeq_payslips_pay_items_partial_update

PATCH /payslips/{payslip_id}/pay-items/{id}/

wafeq_payslips_pay_items_update

PUT /payslips/{payslip_id}/pay-items/{id}/

wafeq_payslips_update

PUT /payslips/{id}/

wafeq_projects_partial_update

PATCH /projects/{id}/

wafeq_projects_update

PUT /projects/{id}/

wafeq_purchase_orders_line_items_partial_update

PATCH /purchase-orders/{purchase_order_id}/line-items/{id}/

wafeq_purchase_orders_line_items_update

PUT /purchase-orders/{purchase_order_id}/line-items/{id}/

wafeq_purchase_orders_partial_update

PATCH /purchase-orders/{id}/

wafeq_purchase_orders_update

PUT /purchase-orders/{id}/

wafeq_quotes_line_items_partial_update

PATCH /quotes/{quote_id}/line-items/{id}/

wafeq_quotes_line_items_update

PUT /quotes/{quote_id}/line-items/{id}/

wafeq_quotes_partial_update

PATCH /quotes/{id}/

wafeq_quotes_update

PUT /quotes/{id}/

wafeq_simplified_invoices_line_items_partial_update

PATCH /simplified-invoices/{invoice_id}/line-items/{id}/

wafeq_simplified_invoices_line_items_update

PUT /simplified-invoices/{invoice_id}/line-items/{id}/

wafeq_simplified_invoices_partial_update

PATCH /simplified-invoices/{id}/

wafeq_simplified_invoices_update

PUT /simplified-invoices/{id}/

wafeq_units_of_measure_partial_update

PATCH /units-of-measure/{id}/

wafeq_units_of_measure_update

PUT /units-of-measure/{id}/

wafeq_warehouses_partial_update

PATCH /warehouses/{id}/

wafeq_warehouses_update

PUT /warehouses/{id}/

Tool

Endpoint

wafeq_expenses_mark_as_draft_create

POST /expenses/{id}/mark-as-draft/

wafeq_expenses_mark_as_posted_create

POST /expenses/{id}/mark-as-posted/

Tool

Endpoint

wafeq_credit_notes_tax_authority_report_create

POST /credit-notes/{id}/tax-authority/report/

wafeq_invoices_tax_authority_report_create

POST /invoices/{id}/tax-authority/report/

wafeq_simplified_invoices_tax_authority_report_create

POST /simplified-invoices/{id}/tax-authority/report/

Tool

Endpoint

wafeq_amortizations_end_early_create

POST /amortizations/{id}/end-early/

wafeq_revenue_recognitions_end_early_create

POST /revenue-recognitions/{id}/end-early/

Tool

Endpoint

wafeq_accounts_destroy

DELETE /accounts/{id}/

wafeq_amortizations_destroy

DELETE /amortizations/{id}/

wafeq_bank_accounts_destroy

DELETE /bank-accounts/{id}/

wafeq_bank_accounts_ledger_transactions_destroy

DELETE /bank-accounts/{bank_account_id}/ledger-transactions/{id}/

wafeq_bank_accounts_statement_transactions_destroy

DELETE /bank-accounts/{bank_account_id}/statement-transactions/{id}/

wafeq_beneficiaries_destroy

DELETE /beneficiaries/{id}/

wafeq_bills_destroy

DELETE /bills/{id}/

wafeq_bills_line_items_destroy

DELETE /bills/{bill_id}/line-items/{id}/

wafeq_branches_destroy

DELETE /branches/{id}/

wafeq_contacts_destroy

DELETE /contacts/{id}/

wafeq_cost_centers_destroy

DELETE /cost-centers/{id}/

wafeq_credit_notes_destroy

DELETE /credit-notes/{id}/

wafeq_credit_notes_line_items_destroy

DELETE /credit-notes/{credit_note_id}/line-items/{id}/

wafeq_custom_fields_destroy

DELETE /custom-fields/{id}/

wafeq_debit_notes_destroy

DELETE /debit-notes/{id}/

wafeq_debit_notes_line_items_destroy

DELETE /debit-notes/{debit_note_id}/line-items/{id}/

wafeq_employees_destroy

DELETE /employees/{id}/

wafeq_expenses_destroy

DELETE /expenses/{id}/

wafeq_files_destroy

DELETE /files/{id}/

wafeq_invoices_destroy

DELETE /invoices/{id}/

wafeq_invoices_line_items_destroy

DELETE /invoices/{invoice_id}/line-items/{id}/

wafeq_item_units_of_measure_destroy

DELETE /item-units-of-measure/{id}/

wafeq_items_destroy

DELETE /items/{id}/

wafeq_manual_journals_destroy

DELETE /manual-journals/{id}/

wafeq_payment_requests_destroy

DELETE /payment_requests/{id}/

wafeq_payments_destroy

DELETE /payments/{id}/

wafeq_payslips_destroy

DELETE /payslips/{id}/

wafeq_payslips_pay_items_destroy

DELETE /payslips/{payslip_id}/pay-items/{id}/

wafeq_projects_destroy

DELETE /projects/{id}/

wafeq_purchase_orders_destroy

DELETE /purchase-orders/{id}/

wafeq_purchase_orders_line_items_destroy

DELETE /purchase-orders/{purchase_order_id}/line-items/{id}/

wafeq_quotes_destroy

DELETE /quotes/{id}/

wafeq_quotes_line_items_destroy

DELETE /quotes/{quote_id}/line-items/{id}/

wafeq_request

hand-written

wafeq_revenue_recognitions_destroy

DELETE /revenue-recognitions/{id}/

wafeq_simplified_invoices_destroy

DELETE /simplified-invoices/{id}/

wafeq_simplified_invoices_line_items_destroy

DELETE /simplified-invoices/{invoice_id}/line-items/{id}/

wafeq_units_of_measure_destroy

DELETE /units-of-measure/{id}/

wafeq_warehouses_destroy

DELETE /warehouses/{id}/

Coverage

Area

Tools

🟒 Read

🟑 Write

πŸ”΄ Irreversible

πŸ”΄ Delete

Sales & receivables

69

25

31

3

10

Purchasing & payables

54

19

27

0

8

Banking

18

6

9

0

3

Ledger & reporting

31

19

6

2

4

Payroll

19

7

9

0

3

Master data & dimensions

54

18

27

0

9

Files & organization

6

3

2

0

1

Escape hatch & convenience

2

1

0

0

1

Total

253

98

111

5

39

"Write" includes the two 🟠 state-change tools. Areas map to Wafeq resources as follows β€” Sales: invoices, simplified invoices, quotes, credit notes, payments, payment requests Β· Purchasing: bills, purchase orders, debit notes, expenses, beneficiaries Β· Banking: bank accounts with their ledger and statement transactions Β· Ledger & reporting: accounts, manual journals, journal line items, the four reports, tax rates, amortizations, revenue recognitions Β· Payroll: payslips, employees Β· Master data: contacts, items, units of measure, warehouses, projects, cost centers, branches, custom fields.

Two hand-written tools

Everything above is generated. Two tools are written by hand:

  • wafeq_account_ledger (🟒) β€” journal line items with their real transaction date. Wafeq's /journal-line-items/ rows carry created_ts (when the row reached Wafeq), which is regularly a different month from the transaction, and no date field at all. This tool recovers the date using the endpoint's own date_after/date_before filters, which do operate on the transaction date. It probes a month at a time and only splits into day queries where rows exist, so quiet periods cost one request each; the result reports requests_made.

  • wafeq_request (πŸ”΄) β€” the escape hatch: any method, any path, plus query, body and headers. It is the fallback for anything the bundled spec misses, not the primary interface. Categorized destructive because its effect can't be known in advance.

Run from source (stdio, no Docker)

npm ci
npm run build

Then register it with your MCP client. For Claude Desktop, add to claude_desktop_config.json:

{
  "mcpServers": {
    "wafeq": {
      "command": "node",
      "args": ["/absolute/path/to/Wafeq MCP/dist/index.js"],
      "env": {
        "MCP_TRANSPORT": "stdio",
        "WAFEQ_API_KEY": "your-key-here"
      }
    }
  }
}

For Claude Code:

claude mcp add wafeq --env WAFEQ_API_KEY=your-key-here -- node /absolute/path/to/dist/index.js

Run the container over stdio

You can also let your client launch the published image directly, with no HTTP server and no local build:

{
  "mcpServers": {
    "wafeq": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-e", "MCP_TRANSPORT=stdio",
        "-e", "WAFEQ_API_KEY",
        "ghcr.io/ohneben/wafeq-mcp:latest"
      ],
      "env": {
        "WAFEQ_API_KEY": "your-key-here"
      }
    }
  }
}

MCP_TRANSPORT=stdio is required here: the image defaults to the HTTP transport.

Useful scripts:

Command

What it does

npm run build

Compile TypeScript to dist/.

npm test

Run the Vitest suite.

npm run list-tools

Print the categorized catalogue. Needs no credentials.

npm run start:stdio

Run over stdio.

npm run start:http

Run the Streamable HTTP server.

Keeping the spec current

Tools are generated from spec/wafeq-public-api.json at startup β€” there is no code generation step and no hand-written tool list. Drop in a newer OpenAPI document (JSON or YAML), rebuild, and new endpoints become new tools. See spec/README.md for where the bundled copy came from and what to re-check after an update.

Observed-behaviour corrections live in src/overrides.ts, keyed by operationId and dated, so an entry whose operation disappears simply stops applying.

Notes & conventions

  • Dates are YYYY-MM-DD. Amounts use a dot as the decimal separator.

  • Paging: list tools take limit and offset, and report the total count.

  • Reports take report-specific date parameters β€” balance sheet date + period_count; profit-and-loss and cash flow date_after + date_before; trial balance from_date + to_date. Wafeq silently ignores a misspelled query parameter, so a wrong name looks like a working call; the per-report schemas exist to make that impossible.

  • Whole periods: profit-and-loss and cash-flow ranges must cover whole months or years. The server checks locally and replies with the nearest valid range rather than spending a round trip on an HTTP 400.

  • File uploads (wafeq_files_*): pass base64 content plus a filename. POST /files/ is multipart-only and POST /files/raw/ needs a Content-Disposition header β€” both are handled for you.

  • PDF downloads come back base64-encoded in a small envelope carrying the size and content type, not as mangled text.

  • Idempotency: every write endpoint that supports X-Wafeq-Idempotency-Key gets a UUID v4 automatically, reused across retries. Pass your own to make a deliberate re-run safe.

  • Retries: transient 429 / 5xx responses are retried with jittered exponential backoff, honoring Retry-After, under the same idempotency key.

  • Rate limiting: Wafeq publishes no numeric limit, so the client-side default (WAFEQ_MAX_REQUESTS=20 per WAFEQ_RATE_WINDOW_MS=10000) is deliberately conservative. Raise it if you know your allowance.

  • One organization per credential. A Wafeq API key is organization-scoped; every tool call acts on that organization, and /health names it.

CI & releases

Every push and pull request is built and tested on Node 20 and 22, and the tool catalogue is generated with no credentials present β€” which is what catches a duplicate or schema-illegal tool name before it ships. CI also fails if .env ever becomes tracked.

A release is a vX.Y.Z tag and nothing else. No version number is maintained by hand. Pushing the tag runs the whole chain:

  1. The version is derived once, from the tag.

  2. The image is built and pushed to ghcr.io/ohneben/wafeq-mcp β€” tagged with the version, MAJOR.MINOR, the short SHA, and latest on main.

  3. The entry is published to the MCP Registry with server.json pinned to that exact image tag. Ownership is proved by the io.modelcontextprotocol.server.name label on the image, which must match server.json's name β€” a test enforces that it does.

  4. The released number is written back into package.json and server.json on main, and the tag is moved onto that commit. So the repository always states the last published version, and the server reports it over MCP and on /health without a code edit.

npm version 2.0.1 --no-git-tag-version   # optional; CI stamps it either way
git tag v2.0.1 && git push origin v2.0.1

workflow_dispatch re-publishes a given version without cutting a new tag. Pushes to main build a -dev.g<sha> image and stop there β€” they never touch the registry.

Security

  • Credentials stay server-side. They are read from the environment and injected per request. The model sees tool inputs and API responses, never the key. The passthrough tool cannot override the Authorization header, and refuses to send the credential to any host other than the configured API base.

  • Never commit .env. It is git-ignored, and CI fails if it ever becomes tracked. .env.example holds placeholders only.

  • Bind to localhost, or set a token. docker-compose.yml publishes on 127.0.0.1 only. Bound any further, the server refuses to start without MCP_AUTH_TOKEN; it is compared in constant time. A Host header check runs on top of that, so a web page cannot reach a loopback server by DNS rebinding.

  • Local file uploads are off by default. WAFEQ_ALLOW_LOCAL_FILE_UPLOAD=false means the server will not read files from its own filesystem. Turning it on lets anything that can call the server ask it to read a local path β€” leave it off unless you need it and trust every client. Base64 uploads work either way.

  • Check the organization on /health before the first write. An API key is scoped to one organization, and a wrong key fails by writing to the wrong company rather than by erroring.

  • The πŸ”΄ tools mean it. Deletions are permanent, ending a schedule early has no API undo, and a tax-authority filing cannot be recalled. Keep host confirmations on for anything carrying destructiveHint.

See SECURITY.md to report a vulnerability.

Credits & license

MIT β€” see LICENSE.md. Built on the Model Context Protocol TypeScript SDK. Not affiliated with or endorsed by Wafeq.

Available Tools

253 tools
wafeq_account_ledgerA
Read-onlyIdempotent

🟒 READ-ONLY · Journal Line Items · convenience tool

List journal line items WITH their real transaction date attached as date.

Use this instead of the raw journal-line-items tool whenever the date matters β€” for tracing an account's history, reconciling a period, or explaining a balance. The raw endpoint returns created_ts (when the row reached Wafeq), which is regularly a different month from the transaction and must not be reported as the transaction date.

Both dates are required and the window must be 92 days or fewer for dates to be resolved; a wider range still returns rows, but without date. Costs one request per month plus one per day in months that contain rows, so quiet periods are cheap. The result reports requests_made.

Inputs: date_after (required), date_before (required), branch, account, +8 more.

wafeq_accounts_createA

🟑 WRITE · creates data · Accounts · POST /accounts/

Create account

Endpoint for creating a new account.

Not idempotent β€” calling twice creates two records. Pass idempotency_key (or let the server generate one) to make a retry safe.

Inputs: body (required), idempotency_key.

wafeq_accounts_destroyB
DestructiveIdempotent

πŸ”΄ DESTRUCTIVE Β· deletes Β· Accounts Β· DELETE /accounts/{id}/

Delete account

Endpoint for deleting an existing account.

Permanently removes the record.

Inputs: id (required), idempotency_key.

wafeq_accounts_listC
Read-onlyIdempotent

🟒 READ-ONLY · Accounts · GET /accounts/

List accounts

Endpoint for retrieving a list of accounts.

Inputs: page, is_system, page_size, external_id, +6 more.

wafeq_accounts_partial_updateA
Idempotent

🟑 WRITE · updates data · Accounts · PATCH /accounts/{id}/

Partial update account

Endpoint for partially updating an existing account.

Inputs: id (required), body, idempotency_key.

wafeq_accounts_retrieveB
Read-onlyIdempotent

🟒 READ-ONLY · Accounts · GET /accounts/{id}/

Retrieve account

Endpoint for retrieving a single account.

Inputs: id (required).

wafeq_accounts_updateB
Idempotent

🟑 WRITE · updates data · Accounts · PUT /accounts/{id}/

Update account

Endpoint for updating an existing account.

Inputs: id (required), body (required), idempotency_key.

wafeq_amortizations_destroyA
DestructiveIdempotent

πŸ”΄ DESTRUCTIVE Β· deletes Β· Amortizations Β· DELETE /amortizations/{id}/

Delete amortization

Endpoint for deleting an existing amortization.

Permanently removes the record.

Inputs: id (required), idempotency_key.

wafeq_amortizations_end_early_createA
Destructive

πŸ”΄ IRREVERSIBLE Β· posts the remaining balance to the ledger Β· Amortizations Β· POST /amortizations/{id}/end-early/

End amortization early

Endpoint for terminating an amortization early, recognizing the remaining balance against the provided account.

Terminates a schedule early and recognizes its whole remaining balance immediately. There is no API undo. Run the matching preview_... tool first to see exactly what would be posted.

Inputs: id (required), body (required).

wafeq_amortizations_listB
Read-onlyIdempotent

🟒 READ-ONLY · Amortizations · GET /amortizations/

List amortizations

Endpoint for retrieving a list of amortizations.

Inputs: page, duration, page_size, status__in, +5 more.

wafeq_amortizations_preview_createA
Read-onlyIdempotent

🟒 READ-ONLY · preview / simulation · Amortizations · POST /amortizations/preview/

Preview amortization schedule

Endpoint for previewing the amortization events that would be generated for the given schedule, without creating an amortization.

This is a POST, but Wafeq documents it as a simulation: it returns the events that WOULD be generated and writes nothing to the ledger.

Inputs: body (required), duration, status__in, end_date_after, +4 more.

wafeq_amortizations_preview_end_early_createA
Read-onlyIdempotent

🟒 READ-ONLY · preview / simulation · Amortizations · POST /amortizations/{id}/preview-end-early/

Preview early termination

Endpoint for previewing the remaining balance and the posted events that would be reversed by terminating the amortization early at the given date.

This is a POST, but Wafeq documents it as a simulation: it returns the events that WOULD be generated and writes nothing to the ledger.

Inputs: id (required), body (required).

wafeq_amortizations_retrieveB
Read-onlyIdempotent

🟒 READ-ONLY · Amortizations · GET /amortizations/{id}/

Retrieve amortization

Endpoint for retrieving a single amortization.

Inputs: id (required).

wafeq_bank_accounts_createA

🟑 WRITE · creates data · Bank Accounts · POST /bank-accounts/

Create bank account

Endpoint for creating a new bank account.

Not idempotent β€” calling twice creates two records. Pass idempotency_key (or let the server generate one) to make a retry safe.

Inputs: body (required), idempotency_key.

wafeq_bank_accounts_destroyB
DestructiveIdempotent

πŸ”΄ DESTRUCTIVE Β· deletes Β· Bank Accounts Β· DELETE /bank-accounts/{id}/

Delete bank account

Endpoint for deleting an existing bank account.

Permanently removes the record.

Inputs: id (required), idempotency_key.

wafeq_bank_accounts_ledger_transactions_createA

🟑 WRITE · creates data · Bank Ledger Transactions · POST /bank-accounts/{bank_account_id}/ledger-transactions/

Create bank ledger transaction

Endpoint for creating a new bank ledger transaction.

Not idempotent β€” calling twice creates two records. Pass idempotency_key (or let the server generate one) to make a retry safe.

Inputs: body (required), bank_account_id (required), idempotency_key.

wafeq_bank_accounts_ledger_transactions_destroyA
DestructiveIdempotent

πŸ”΄ DESTRUCTIVE Β· deletes Β· Bank Ledger Transactions Β· DELETE /bank-accounts/{bank_account_id}/ledger-transactions/{id}/

Delete bank ledger transaction

Endpoint for deleting an existing bank ledger transaction.

Permanently removes the record.

Inputs: id (required), bank_account_id (required), idempotency_key.

wafeq_bank_accounts_ledger_transactions_listC
Read-onlyIdempotent

🟒 READ-ONLY · Bank Ledger Transactions · GET /bank-accounts/{bank_account_id}/ledger-transactions/

List bank ledger transactions

Endpoint for retrieving a list of bank ledger transactions.

Inputs: bank_account_id (required), page, page_size.

wafeq_bank_accounts_ledger_transactions_partial_updateC
Idempotent

🟑 WRITE · updates data · Bank Ledger Transactions · PATCH /bank-accounts/{bank_account_id}/ledger-transactions/{id}/

Partial update bank ledger transaction

Endpoint for partially updating an existing bank ledger transaction.

Inputs: id (required), bank_account_id (required), body, idempotency_key.

wafeq_bank_accounts_ledger_transactions_retrieveC
Read-onlyIdempotent

🟒 READ-ONLY · Bank Ledger Transactions · GET /bank-accounts/{bank_account_id}/ledger-transactions/{id}/

Retrieve bank ledger transaction

Endpoint for retrieving a single bank ledger transaction.

Inputs: id (required), bank_account_id (required).

wafeq_bank_accounts_ledger_transactions_updateB
Idempotent

🟑 WRITE · updates data · Bank Ledger Transactions · PUT /bank-accounts/{bank_account_id}/ledger-transactions/{id}/

Update bank ledger transaction

Endpoint for updating an existing bank ledger transaction.

Inputs: id (required), body (required), bank_account_id (required), idempotency_key.

wafeq_bank_accounts_listB
Read-onlyIdempotent

🟒 READ-ONLY · Bank Accounts · GET /bank-accounts/

List bank accounts

Endpoint for retrieving a list of bank accounts.

Inputs: page, currency, page_size, classification, +5 more.

wafeq_bank_accounts_partial_updateB
Idempotent

🟑 WRITE · updates data · Bank Accounts · PATCH /bank-accounts/{id}/

Partial update bank account

Endpoint for partially updating an existing bank account.

Inputs: id (required), body, idempotency_key.

wafeq_bank_accounts_retrieveB
Read-onlyIdempotent

🟒 READ-ONLY · Bank Accounts · GET /bank-accounts/{id}/

Retrieve bank account

Endpoint for retrieving a single bank account.

Inputs: id (required).

wafeq_bank_accounts_statement_transactions_createA

🟑 WRITE · creates data · Bank Statement Transactions · POST /bank-accounts/{bank_account_id}/statement-transactions/

Create bank statement transaction

Endpoint for creating a new bank statement transaction.

Not idempotent β€” calling twice creates two records. Pass idempotency_key (or let the server generate one) to make a retry safe.

Inputs: body (required), bank_account_id (required), idempotency_key.

wafeq_bank_accounts_statement_transactions_destroyA
DestructiveIdempotent

πŸ”΄ DESTRUCTIVE Β· deletes Β· Bank Statement Transactions Β· DELETE /bank-accounts/{bank_account_id}/statement-transactions/{id}/

Delete bank statement transaction

Endpoint for deleting an existing bank statement transaction.

Permanently removes the record.

Inputs: id (required), bank_account_id (required), idempotency_key.

wafeq_bank_accounts_statement_transactions_listC
Read-onlyIdempotent

🟒 READ-ONLY · Bank Statement Transactions · GET /bank-accounts/{bank_account_id}/statement-transactions/

List bank statement transactions

Endpoint for retrieving a list of bank statement transactions.

Inputs: bank_account_id (required), page, page_size.

wafeq_bank_accounts_statement_transactions_partial_updateB
Idempotent

🟑 WRITE · updates data · Bank Statement Transactions · PATCH /bank-accounts/{bank_account_id}/statement-transactions/{id}/

Partial update bank statement transaction

Endpoint for partially updating an existing bank statement transaction.

Inputs: id (required), bank_account_id (required), body, idempotency_key.

wafeq_bank_accounts_statement_transactions_retrieveA
Read-onlyIdempotent

🟒 READ-ONLY · Bank Statement Transactions · GET /bank-accounts/{bank_account_id}/statement-transactions/{id}/

Retrieve bank statement transaction

Endpoint for retrieving a single bank statement transaction.

Inputs: id (required), bank_account_id (required).

wafeq_bank_accounts_statement_transactions_updateC
Idempotent

🟑 WRITE · updates data · Bank Statement Transactions · PUT /bank-accounts/{bank_account_id}/statement-transactions/{id}/

Update bank statement transaction

Endpoint for updating an existing bank statement transaction.

Inputs: id (required), body (required), bank_account_id (required), idempotency_key.

wafeq_bank_accounts_updateB
Idempotent

🟑 WRITE · updates data · Bank Accounts · PUT /bank-accounts/{id}/

Update bank account

Endpoint for updating an existing bank account.

Inputs: id (required), body (required), idempotency_key.

wafeq_beneficiaries_createA

🟑 WRITE · creates data · Beneficiaries · POST /beneficiaries/

Create beneficiary

Endpoint for creating a new beneficiary.

Not idempotent β€” calling twice creates two records. Pass idempotency_key (or let the server generate one) to make a retry safe.

Inputs: body (required), idempotency_key.

wafeq_beneficiaries_destroyB
DestructiveIdempotent

πŸ”΄ DESTRUCTIVE Β· deletes Β· Beneficiaries Β· DELETE /beneficiaries/{id}/

Delete beneficiary

Endpoint for deleting an existing beneficiary.

Permanently removes the record.

Inputs: id (required), idempotency_key.

wafeq_beneficiaries_listC
Read-onlyIdempotent

🟒 READ-ONLY · Beneficiaries · GET /beneficiaries/

List beneficiaries

Endpoint for retrieving a list of beneficiaries.

Inputs: page, contact, country, keyword, +7 more.

wafeq_beneficiaries_partial_updateA
Idempotent

🟑 WRITE · updates data · Beneficiaries · PATCH /beneficiaries/{id}/

Partial update beneficiary

Endpoint for partially updating an existing beneficiary.

Inputs: id (required), body, idempotency_key.

wafeq_beneficiaries_retrieveB
Read-onlyIdempotent

🟒 READ-ONLY · Beneficiaries · GET /beneficiaries/{id}/

Retrieve beneficiary

Endpoint for retrieving a single beneficiary.

Inputs: id (required).

wafeq_beneficiaries_updateC
Idempotent

🟑 WRITE · updates data · Beneficiaries · PUT /beneficiaries/{id}/

Update beneficiary

Endpoint for updating an existing beneficiary.

Inputs: id (required), body (required), idempotency_key.

wafeq_bills_createA

🟑 WRITE · creates data · Bills · POST /bills/

Create bill

Endpoint for creating a new bill.

Not idempotent β€” calling twice creates two records. Pass idempotency_key (or let the server generate one) to make a retry safe.

Inputs: body (required), idempotency_key.

wafeq_bills_destroyB
DestructiveIdempotent

πŸ”΄ DESTRUCTIVE Β· deletes Β· Bills Β· DELETE /bills/{id}/

Delete bill

Endpoint for deleting an existing bill.

Permanently removes the record.

Inputs: id (required), idempotency_key.

wafeq_bills_download_retrieveA
Read-onlyIdempotent

🟒 READ-ONLY · returns a PDF · Bills · GET /bills/{id}/download/

Download bill PDF

Endpoint for downloading a PDF of the bill.

Returns the document as base64-encoded PDF bytes plus its size and content type. Nothing is modified.

Inputs: id (required).

wafeq_bills_line_items_createA

🟑 WRITE · creates data · Bill Line Items · POST /bills/{bill_id}/line-items/

Create bill line item

Endpoint for creating a new bill line item.

Not idempotent β€” calling twice creates two records. Pass idempotency_key (or let the server generate one) to make a retry safe.

Inputs: body (required), bill_id (required), idempotency_key.

wafeq_bills_line_items_destroyA
DestructiveIdempotent

πŸ”΄ DESTRUCTIVE Β· deletes Β· Bill Line Items Β· DELETE /bills/{bill_id}/line-items/{id}/

Delete bill line item

Endpoint for deleting an existing bill line item.

Permanently removes the record.

Inputs: id (required), bill_id (required), idempotency_key.

wafeq_bills_line_items_listC
Read-onlyIdempotent

🟒 READ-ONLY · Bill Line Items · GET /bills/{bill_id}/line-items/

List bill line items

Endpoint for retrieving a list of bill line items.

Inputs: bill_id (required), page, page_size.

wafeq_bills_line_items_partial_updateC
Idempotent

🟑 WRITE · updates data · Bill Line Items · PATCH /bills/{bill_id}/line-items/{id}/

Partial update bill line item

Endpoint for partially updating an existing bill line item.

Inputs: id (required), bill_id (required), body, idempotency_key.

wafeq_bills_line_items_retrieveB
Read-onlyIdempotent

🟒 READ-ONLY · Bill Line Items · GET /bills/{bill_id}/line-items/{id}/

Retrieve bill line item

Endpoint for retrieving a single bill line item.

Inputs: id (required), bill_id (required).

wafeq_bills_line_items_updateC
Idempotent

🟑 WRITE · updates data · Bill Line Items · PUT /bills/{bill_id}/line-items/{id}/

Update bill line item

Endpoint for updating an existing bill line item.

Inputs: id (required), body (required), bill_id (required), idempotency_key.

wafeq_bills_listC
Read-onlyIdempotent

🟒 READ-ONLY · Bills · GET /bills/

List bills

Endpoint for retrieving a list of bills.

Inputs: page, branch, status, contact, +10 more.

wafeq_bills_partial_updateC
Idempotent

🟑 WRITE · updates data · Bills · PATCH /bills/{id}/

Partial update bill

Endpoint for partially updating an existing bill.

Inputs: id (required), body, idempotency_key.

wafeq_bills_retrieveB
Read-onlyIdempotent

🟒 READ-ONLY · Bills · GET /bills/{id}/

Retrieve bill

Endpoint for retrieving a single bill.

Inputs: id (required).

wafeq_bills_updateC
Idempotent

🟑 WRITE · updates data · Bills · PUT /bills/{id}/

Update bill

Endpoint for updating an existing bill.

Inputs: id (required), body (required), idempotency_key.

wafeq_branches_createA

🟑 WRITE · creates data · Branches · POST /branches/

Create branch

Endpoint for creating a new branch.

Not idempotent β€” calling twice creates two records. Pass idempotency_key (or let the server generate one) to make a retry safe.

Inputs: body (required), idempotency_key.

wafeq_branches_destroyB
DestructiveIdempotent

πŸ”΄ DESTRUCTIVE Β· deletes Β· Branches Β· DELETE /branches/{id}/

Delete branch

Endpoint for deleting an existing branch.

Permanently removes the record.

Inputs: id (required), idempotency_key.

wafeq_branches_listB
Read-onlyIdempotent

🟒 READ-ONLY · Branches · GET /branches/

List branches

Endpoint for retrieving a list of branches.

Inputs: page, page_size.

wafeq_branches_partial_updateA
Idempotent

🟑 WRITE · updates data · Branches · PATCH /branches/{id}/

Partial update branch

Endpoint for partially updating an existing branch.

Inputs: id (required), body, idempotency_key.

wafeq_branches_retrieveA
Read-onlyIdempotent

🟒 READ-ONLY · Branches · GET /branches/{id}/

Retrieve branch

Endpoint for retrieving a single branch.

Inputs: id (required).

wafeq_branches_updateC
Idempotent

🟑 WRITE · updates data · Branches · PUT /branches/{id}/

Update branch

Endpoint for updating an existing branch.

Inputs: id (required), body (required), idempotency_key.

wafeq_contacts_createA

🟑 WRITE · creates data · Contacts · POST /contacts/

Create contact

Endpoint for creating a new contact.

Not idempotent β€” calling twice creates two records. Pass idempotency_key (or let the server generate one) to make a retry safe.

Inputs: body (required), idempotency_key.

wafeq_contacts_destroyA
DestructiveIdempotent

πŸ”΄ DESTRUCTIVE Β· deletes Β· Contacts Β· DELETE /contacts/{id}/

Delete contact

Endpoint for deleting an existing contact.

Permanently removes the record.

Inputs: id (required), idempotency_key.

wafeq_contacts_listC
Read-onlyIdempotent

🟒 READ-ONLY · Contacts · GET /contacts/

List contacts

Endpoint for retrieving a list of contacts.

Inputs: page, country, keyword, page_size, +6 more.

wafeq_contacts_partial_updateC
Idempotent

🟑 WRITE · updates data · Contacts · PATCH /contacts/{id}/

Partial update contact

Endpoint for partially updating an existing contact.

Inputs: id (required), body, idempotency_key.

wafeq_contacts_retrieveC
Read-onlyIdempotent

🟒 READ-ONLY · Contacts · GET /contacts/{id}/

Retrieve contact

Endpoint for retrieving a single contact.

Inputs: id (required).

wafeq_contacts_updateC
Idempotent

🟑 WRITE · updates data · Contacts · PUT /contacts/{id}/

Update contact

Endpoint for updating an existing contact.

Inputs: id (required), body (required), idempotency_key.

wafeq_cost_centers_createA

🟑 WRITE · creates data · Cost Centers · POST /cost-centers/

Create cost center

Endpoint for creating a new cost center.

Not idempotent β€” calling twice creates two records. Pass idempotency_key (or let the server generate one) to make a retry safe.

Inputs: body (required), idempotency_key.

wafeq_cost_centers_destroyA
DestructiveIdempotent

πŸ”΄ DESTRUCTIVE Β· deletes Β· Cost Centers Β· DELETE /cost-centers/{id}/

Delete cost center

Endpoint for deleting an existing cost center.

Permanently removes the record.

Inputs: id (required), idempotency_key.

wafeq_cost_centers_listC
Read-onlyIdempotent

🟒 READ-ONLY · Cost Centers · GET /cost-centers/

List cost centers

Endpoint for retrieving a list of cost centers.

Inputs: page, page_size.

wafeq_cost_centers_partial_updateB
Idempotent

🟑 WRITE · updates data · Cost Centers · PATCH /cost-centers/{id}/

Partial update cost center

Endpoint for partially updating an existing cost center.

Inputs: id (required), body, idempotency_key.

wafeq_cost_centers_retrieveB
Read-onlyIdempotent

🟒 READ-ONLY · Cost Centers · GET /cost-centers/{id}/

Retrieve cost center

Endpoint for retrieving a single cost center.

Inputs: id (required).

wafeq_cost_centers_updateC
Idempotent

🟑 WRITE · updates data · Cost Centers · PUT /cost-centers/{id}/

Update cost center

Endpoint for updating an existing cost center.

Inputs: id (required), body (required), idempotency_key.

wafeq_credit_notes_createA

🟑 WRITE · creates data · Credit Notes · POST /credit-notes/

Create credit note

Endpoint for creating a new credit note.

Not idempotent β€” calling twice creates two records. Pass idempotency_key (or let the server generate one) to make a retry safe.

Inputs: body (required), idempotency_key.

wafeq_credit_notes_destroyB
DestructiveIdempotent

πŸ”΄ DESTRUCTIVE Β· deletes Β· Credit Notes Β· DELETE /credit-notes/{id}/

Delete credit note

Endpoint for deleting an existing credit note.

Permanently removes the record.

Inputs: id (required), idempotency_key.

wafeq_credit_notes_download_retrieveA
Read-onlyIdempotent

🟒 READ-ONLY · returns a PDF · Credit Notes · GET /credit-notes/{id}/download/

Download credit note PDF

Endpoint for downloading a PDF of the credit note.

Returns the document as base64-encoded PDF bytes plus its size and content type. Nothing is modified.

Inputs: id (required).

wafeq_credit_notes_line_items_createA

🟑 WRITE · creates data · Credit Note Line Items · POST /credit-notes/{credit_note_id}/line-items/

Create credit note line item

Endpoint for creating a new credit note line item.

Not idempotent β€” calling twice creates two records. Pass idempotency_key (or let the server generate one) to make a retry safe.

Inputs: body (required), credit_note_id (required), idempotency_key.

wafeq_credit_notes_line_items_destroyA
DestructiveIdempotent

πŸ”΄ DESTRUCTIVE Β· deletes Β· Credit Note Line Items Β· DELETE /credit-notes/{credit_note_id}/line-items/{id}/

Delete credit note line item

Endpoint for deleting an existing credit note line item.

Permanently removes the record.

Inputs: id (required), credit_note_id (required), idempotency_key.

wafeq_credit_notes_line_items_listC
Read-onlyIdempotent

🟒 READ-ONLY · Credit Note Line Items · GET /credit-notes/{credit_note_id}/line-items/

List credit note line items

Endpoint for retrieving a list of credit note line items.

Inputs: credit_note_id (required), page, page_size.

wafeq_credit_notes_line_items_partial_updateB
Idempotent

🟑 WRITE · updates data · Credit Note Line Items · PATCH /credit-notes/{credit_note_id}/line-items/{id}/

Partial update credit note line item

Endpoint for partially updating an existing credit note line item.

Inputs: id (required), credit_note_id (required), body, idempotency_key.

wafeq_credit_notes_line_items_retrieveA
Read-onlyIdempotent

🟒 READ-ONLY · Credit Note Line Items · GET /credit-notes/{credit_note_id}/line-items/{id}/

Retrieve credit note line item

Endpoint for retrieving a single credit note line item.

Inputs: id (required), credit_note_id (required).

wafeq_credit_notes_line_items_updateB
Idempotent

🟑 WRITE · updates data · Credit Note Line Items · PUT /credit-notes/{credit_note_id}/line-items/{id}/

Update credit note line item

Endpoint for updating an existing credit note line item.

Inputs: id (required), body (required), credit_note_id (required), idempotency_key.

wafeq_credit_notes_listB
Read-onlyIdempotent

🟒 READ-ONLY · Credit Notes · GET /credit-notes/

List credit notes

Endpoint for retrieving a list of credit notes.

Inputs: page, branch, status, contact, +8 more.

wafeq_credit_notes_partial_updateC
Idempotent

🟑 WRITE · updates data · Credit Notes · PATCH /credit-notes/{id}/

Partial update credit note

Endpoint for partially updating an existing credit note.

Inputs: id (required), body, idempotency_key.

wafeq_credit_notes_retrieveB
Read-onlyIdempotent

🟒 READ-ONLY · Credit Notes · GET /credit-notes/{id}/

Retrieve credit note

Endpoint for retrieving a single credit note.

Inputs: id (required).

wafeq_credit_notes_tax_authority_report_createA
Destructive

πŸ”΄ IRREVERSIBLE Β· files the document with an external tax authority Β· Credit Notes Β· POST /credit-notes/{id}/tax-authority/report/

Report credit note to tax authority

Report the credit note to the tax authority for processing and validation.

Submits the document outside your organization for clearance/reporting. It CANNOT be recalled or undone through this API. Confirm with the user before calling, and check the document's contents first.

Inputs: id (required), idempotency_key.

wafeq_credit_notes_updateC
Idempotent

🟑 WRITE · updates data · Credit Notes · PUT /credit-notes/{id}/

Update credit note

Endpoint for updating an existing credit note.

Inputs: id (required), body (required), idempotency_key.

wafeq_custom_fields_createA

🟑 WRITE · creates data · Custom Fields · POST /custom-fields/

Create custom field

Endpoint for creating a new custom field.

Not idempotent β€” calling twice creates two records. Pass idempotency_key (or let the server generate one) to make a retry safe.

Inputs: body (required), idempotency_key.

wafeq_custom_fields_destroyA
DestructiveIdempotent

πŸ”΄ DESTRUCTIVE Β· deletes Β· Custom Fields Β· DELETE /custom-fields/{id}/

Delete custom field

Endpoint for deleting an existing custom field. The custom field must not be in use on any documents.

Permanently removes the record.

Inputs: id (required), idempotency_key.

wafeq_custom_fields_listB
Read-onlyIdempotent

🟒 READ-ONLY · Custom Fields · GET /custom-fields/

List custom fields

Endpoint for retrieving a list of custom fields.

Inputs: page, page_size.

wafeq_custom_fields_partial_updateB
Idempotent

🟑 WRITE · updates data · Custom Fields · PATCH /custom-fields/{id}/

Partial update custom field

Endpoint for partially updating an existing custom field.

Inputs: id (required), body, idempotency_key.

wafeq_custom_fields_retrieveA
Read-onlyIdempotent

🟒 READ-ONLY · Custom Fields · GET /custom-fields/{id}/

Retrieve custom field

Endpoint for retrieving a single custom field.

Inputs: id (required).

wafeq_custom_fields_updateC
Idempotent

🟑 WRITE · updates data · Custom Fields · PUT /custom-fields/{id}/

Update custom field

Endpoint for updating an existing custom field.

Inputs: id (required), body (required), idempotency_key.

wafeq_debit_notes_createA

🟑 WRITE · creates data · Debit Notes · POST /debit-notes/

Create debit note

Endpoint for creating a new debit note.

Not idempotent β€” calling twice creates two records. Pass idempotency_key (or let the server generate one) to make a retry safe.

Inputs: body (required), idempotency_key.

wafeq_debit_notes_destroyA
DestructiveIdempotent

πŸ”΄ DESTRUCTIVE Β· deletes Β· Debit Notes Β· DELETE /debit-notes/{id}/

Delete debit note

Endpoint for deleting an existing debit note.

Permanently removes the record.

Inputs: id (required), idempotency_key.

wafeq_debit_notes_download_retrieveA
Read-onlyIdempotent

🟒 READ-ONLY · returns a PDF · Debit Notes · GET /debit-notes/{id}/download/

Download debit note PDF

Endpoint for downloading a PDF of the debit note.

Returns the document as base64-encoded PDF bytes plus its size and content type. Nothing is modified.

Inputs: id (required).

wafeq_debit_notes_line_items_createA

🟑 WRITE · creates data · Debit Note Line Items · POST /debit-notes/{debit_note_id}/line-items/

Create debit note line item

Endpoint for creating a new debit note line item.

Not idempotent β€” calling twice creates two records. Pass idempotency_key (or let the server generate one) to make a retry safe.

Inputs: body (required), debit_note_id (required), idempotency_key.

wafeq_debit_notes_line_items_destroyA
DestructiveIdempotent

πŸ”΄ DESTRUCTIVE Β· deletes Β· Debit Note Line Items Β· DELETE /debit-notes/{debit_note_id}/line-items/{id}/

Delete debit note line item

Endpoint for deleting an existing debit note line item.

Permanently removes the record.

Inputs: id (required), debit_note_id (required), idempotency_key.

wafeq_debit_notes_line_items_listB
Read-onlyIdempotent

🟒 READ-ONLY · Debit Note Line Items · GET /debit-notes/{debit_note_id}/line-items/

List debit note line items

Endpoint for retrieving a list of debit note line items.

Inputs: debit_note_id (required), page, page_size.

wafeq_debit_notes_line_items_partial_updateB
Idempotent

🟑 WRITE · updates data · Debit Note Line Items · PATCH /debit-notes/{debit_note_id}/line-items/{id}/

Partial update debit note line item

Endpoint for partially updating an existing debit note line item.

Inputs: id (required), debit_note_id (required), body, idempotency_key.

wafeq_debit_notes_line_items_retrieveA
Read-onlyIdempotent

🟒 READ-ONLY · Debit Note Line Items · GET /debit-notes/{debit_note_id}/line-items/{id}/

Retrieve debit note line item

Endpoint for retrieving a single debit note line item.

Inputs: id (required), debit_note_id (required).

wafeq_debit_notes_line_items_updateB
Idempotent

🟑 WRITE · updates data · Debit Note Line Items · PUT /debit-notes/{debit_note_id}/line-items/{id}/

Update debit note line item

Endpoint for updating an existing debit note line item.

Inputs: id (required), body (required), debit_note_id (required), idempotency_key.

wafeq_debit_notes_listC
Read-onlyIdempotent

🟒 READ-ONLY · Debit Notes · GET /debit-notes/

List debit notes

Endpoint for retrieving a list of debit notes.

Inputs: page, branch, status, contact, +8 more.

wafeq_debit_notes_partial_updateA
Idempotent

🟑 WRITE · updates data · Debit Notes · PATCH /debit-notes/{id}/

Partial update debit note

Endpoint for partially updating an existing debit note.

Inputs: id (required), body, idempotency_key.

wafeq_debit_notes_retrieveA
Read-onlyIdempotent

🟒 READ-ONLY · Debit Notes · GET /debit-notes/{id}/

Retrieve debit note

Endpoint for retrieving a single debit note.

Inputs: id (required).

wafeq_debit_notes_updateC
Idempotent

🟑 WRITE · updates data · Debit Notes · PUT /debit-notes/{id}/

Update debit note

Endpoint for updating an existing debit note.

Inputs: id (required), body (required), idempotency_key.

wafeq_employees_createA

🟑 WRITE · creates data · Employees · POST /employees/

Create employee

Endpoint for creating a new employee.

Not idempotent β€” calling twice creates two records. Pass idempotency_key (or let the server generate one) to make a retry safe.

Inputs: body (required), idempotency_key.

wafeq_employees_destroyA
DestructiveIdempotent

πŸ”΄ DESTRUCTIVE Β· deletes Β· Employees Β· DELETE /employees/{id}/

Delete employee

Endpoint for deleting an existing employee.

Permanently removes the record.

Inputs: id (required), idempotency_key.

wafeq_employees_listB
Read-onlyIdempotent

🟒 READ-ONLY · Employees · GET /employees/

List employees

Endpoint for retrieving a list of employees.

Inputs: page, country, page_size, created_ts_after, +3 more.

wafeq_employees_partial_updateC
Idempotent

🟑 WRITE · updates data · Employees · PATCH /employees/{id}/

Partial update employee

Endpoint for partially updating an existing employee.

Inputs: id (required), body, idempotency_key.

wafeq_employees_retrieveA
Read-onlyIdempotent

🟒 READ-ONLY · Employees · GET /employees/{id}/

Retrieve employee

Endpoint for retrieving a single employee.

Inputs: id (required).

wafeq_employees_updateC
Idempotent

🟑 WRITE · updates data · Employees · PUT /employees/{id}/

Update employee

Endpoint for updating an existing employee.

Inputs: id (required), body (required), idempotency_key.

wafeq_expenses_createB

🟑 WRITE · creates data · Expenses · POST /expenses/

Create expense

Endpoint for creating a new expense.

Not idempotent β€” calling twice creates two records. Pass idempotency_key (or let the server generate one) to make a retry safe.

Inputs: body (required), idempotency_key.

wafeq_expenses_destroyB
DestructiveIdempotent

πŸ”΄ DESTRUCTIVE Β· deletes Β· Expenses Β· DELETE /expenses/{id}/

Delete expense

Endpoint for deleting an existing expense.

Permanently removes the record.

Inputs: id (required), idempotency_key.

wafeq_expenses_listB
Read-onlyIdempotent

🟒 READ-ONLY · Expenses · GET /expenses/

List expenses

Endpoint for retrieving a list of expenses.

Inputs: date, page, branch, status, +11 more.

wafeq_expenses_mark_as_draft_createA
Idempotent

🟠 STATE CHANGE · moves a document in or out of the ledger · Expenses · POST /expenses/{id}/mark-as-draft/

Mark expense as draft

Moves a posted expense back to draft (removes its journal from the ledger).

Changes posted/draft status, which adds or removes the document's journal from the ledger. Reversible: the opposite tool undoes it.

Removes the expense's journal from the ledger and returns it to draft. Undo with mark expense as posted.

Inputs: id (required).

wafeq_expenses_mark_as_posted_createA
Idempotent

🟠 STATE CHANGE · moves a document in or out of the ledger · Expenses · POST /expenses/{id}/mark-as-posted/

Mark expense as posted

Posts a draft expense to the ledger (generates its journal).

Changes posted/draft status, which adds or removes the document's journal from the ledger. Reversible: the opposite tool undoes it.

Generates the expense's journal and posts it to the ledger. Undo with mark expense as draft.

Inputs: id (required).

wafeq_expenses_partial_updateC
Idempotent

🟑 WRITE · updates data · Expenses · PATCH /expenses/{id}/

Partial update expense

Endpoint for partially updating an existing expense.

Inputs: id (required), body, idempotency_key.

wafeq_expenses_retrieveA
Read-onlyIdempotent

🟒 READ-ONLY · Expenses · GET /expenses/{id}/

Retrieve expense

Endpoint for retrieving a single expense.

Inputs: id (required).

wafeq_expenses_updateC
Idempotent

🟑 WRITE · updates data · Expenses · PUT /expenses/{id}/

Update expense

Endpoint for updating an existing expense.

Inputs: id (required), body (required), idempotency_key.

wafeq_files_destroyB
DestructiveIdempotent

πŸ”΄ DESTRUCTIVE Β· deletes Β· Files Β· DELETE /files/{id}/

Delete file

Endpoint for deleting an existing file.

Permanently removes the record.

Inputs: id (required), idempotency_key.

wafeq_files_listC
Read-onlyIdempotent

🟒 READ-ONLY · Files · GET /files/

List files

Endpoint for retrieving a list of files.

Inputs: page, mime_type, page_size, file_size_max, +6 more.

wafeq_files_retrieveB
Read-onlyIdempotent

🟒 READ-ONLY · Files · GET /files/{id}/

Retrieve file

Endpoint for retrieving a single file.

Inputs: id (required).

wafeq_invoices_createA

🟑 WRITE · creates data · Invoices · POST /invoices/

Create invoice

Endpoint for creating a new invoice.

Not idempotent β€” calling twice creates two records. Pass idempotency_key (or let the server generate one) to make a retry safe.

Inputs: body (required), idempotency_key.

wafeq_invoices_destroyB
DestructiveIdempotent

πŸ”΄ DESTRUCTIVE Β· deletes Β· Invoices Β· DELETE /invoices/{id}/

Delete invoice

Endpoint for deleting an existing invoice.

Permanently removes the record.

Inputs: id (required), idempotency_key.

wafeq_invoices_download_retrieveA
Read-onlyIdempotent

🟒 READ-ONLY · returns a PDF · Invoices · GET /invoices/{id}/download/

Download invoice PDF

Endpoint for downloading a PDF of the invoice.

Returns the document as base64-encoded PDF bytes plus its size and content type. Nothing is modified.

Inputs: id (required).

wafeq_invoices_line_items_createA

🟑 WRITE · creates data · Invoice Line Items · POST /invoices/{invoice_id}/line-items/

Create invoice line item

Endpoint for creating a new invoice line item.

Not idempotent β€” calling twice creates two records. Pass idempotency_key (or let the server generate one) to make a retry safe.

Inputs: body (required), invoice_id (required), idempotency_key.

wafeq_invoices_line_items_destroyB
DestructiveIdempotent

πŸ”΄ DESTRUCTIVE Β· deletes Β· Invoice Line Items Β· DELETE /invoices/{invoice_id}/line-items/{id}/

Delete invoice line item

Endpoint for deleting an existing invoice line item.

Permanently removes the record.

Inputs: id (required), invoice_id (required), idempotency_key.

wafeq_invoices_line_items_listB
Read-onlyIdempotent

🟒 READ-ONLY · Invoice Line Items · GET /invoices/{invoice_id}/line-items/

List invoice line items

Endpoint for retrieving a list of invoice line items.

Inputs: invoice_id (required), page, page_size.

wafeq_invoices_line_items_partial_updateC
Idempotent

🟑 WRITE · updates data · Invoice Line Items · PATCH /invoices/{invoice_id}/line-items/{id}/

Partial update invoice line item

Endpoint for partially updating an existing invoice line item.

Inputs: id (required), invoice_id (required), body, idempotency_key.

wafeq_invoices_line_items_retrieveB
Read-onlyIdempotent

🟒 READ-ONLY · Invoice Line Items · GET /invoices/{invoice_id}/line-items/{id}/

Retrieve invoice line item

Endpoint for retrieving a single invoice line item.

Inputs: id (required), invoice_id (required).

wafeq_invoices_line_items_updateC
Idempotent

🟑 WRITE · updates data · Invoice Line Items · PUT /invoices/{invoice_id}/line-items/{id}/

Update invoice line item

Endpoint for updating an existing invoice line item.

Inputs: id (required), body (required), invoice_id (required), idempotency_key.

wafeq_invoices_listB
Read-onlyIdempotent

🟒 READ-ONLY · Invoices · GET /invoices/

List invoices

Endpoint for retrieving a list of invoices.

Inputs: page, branch, status, contact, +8 more.

wafeq_invoices_partial_updateC
Idempotent

🟑 WRITE · updates data · Invoices · PATCH /invoices/{id}/

Partial update invoice

Endpoint for partially updating an existing invoice.

Inputs: id (required), body, idempotency_key.

wafeq_invoices_retrieveB
Read-onlyIdempotent

🟒 READ-ONLY · Invoices · GET /invoices/{id}/

Retrieve invoice

Endpoint for retrieving a single invoice.

Inputs: id (required).

wafeq_invoices_tax_authority_report_createA
Destructive

πŸ”΄ IRREVERSIBLE Β· files the document with an external tax authority Β· Invoices Β· POST /invoices/{id}/tax-authority/report/

Report invoice to tax authority

Report the invoice to the tax authority for processing and validation.

Submits the document outside your organization for clearance/reporting. It CANNOT be recalled or undone through this API. Confirm with the user before calling, and check the document's contents first.

Inputs: id (required), idempotency_key.

wafeq_invoices_updateC
Idempotent

🟑 WRITE · updates data · Invoices · PUT /invoices/{id}/

Update invoice

Endpoint for updating an existing invoice.

Inputs: id (required), body (required), idempotency_key.

wafeq_items_createA

🟑 WRITE · creates data · Items · POST /items/

Create item

Endpoint for creating a new item.

Not idempotent β€” calling twice creates two records. Pass idempotency_key (or let the server generate one) to make a retry safe.

Inputs: body (required), idempotency_key.

wafeq_items_destroyA
DestructiveIdempotent

πŸ”΄ DESTRUCTIVE Β· deletes Β· Items Β· DELETE /items/{id}/

Delete item

Endpoint for deleting an existing item.

Permanently removes the record.

Inputs: id (required), idempotency_key.

wafeq_items_listB
Read-onlyIdempotent

🟒 READ-ONLY · Items · GET /items/

List items

Endpoint for retrieving a list of items.

Inputs: page, page_size, external_id, created_ts_after, +3 more.

wafeq_items_partial_updateA
Idempotent

🟑 WRITE · updates data · Items · PATCH /items/{id}/

Partial update item

Endpoint for partially updating an existing item.

Inputs: id (required), body, idempotency_key.

wafeq_items_retrieveB
Read-onlyIdempotent

🟒 READ-ONLY · Items · GET /items/{id}/

Retrieve item

Endpoint for retrieving a single item.

Inputs: id (required).

wafeq_items_updateC
Idempotent

🟑 WRITE · updates data · Items · PUT /items/{id}/

Update item

Endpoint for updating an existing item.

Inputs: id (required), body (required), idempotency_key.

wafeq_item_units_of_measure_createA

🟑 WRITE · creates data · Item Unit Of Measures · POST /item-units-of-measure/

Create item unit of measure

Endpoint for creating a new item unit of measure.

Not idempotent β€” calling twice creates two records. Pass idempotency_key (or let the server generate one) to make a retry safe.

Inputs: body (required), idempotency_key.

wafeq_item_units_of_measure_destroyA
DestructiveIdempotent

πŸ”΄ DESTRUCTIVE Β· deletes Β· Item Unit Of Measures Β· DELETE /item-units-of-measure/{id}/

Delete item unit of measure

Endpoint for deleting an existing item unit of measure.

Permanently removes the record.

Inputs: id (required), idempotency_key.

wafeq_item_units_of_measure_listB
Read-onlyIdempotent

🟒 READ-ONLY · Item Unit Of Measures · GET /item-units-of-measure/

List item unit of measures

Endpoint for retrieving a list of item unit of measures.

Inputs: page, page_size.

wafeq_item_units_of_measure_partial_updateB
Idempotent

🟑 WRITE · updates data · Item Unit Of Measures · PATCH /item-units-of-measure/{id}/

Partial update item unit of measure

Endpoint for partially updating an existing item unit of measure.

Inputs: id (required), body, idempotency_key.

wafeq_item_units_of_measure_retrieveB
Read-onlyIdempotent

🟒 READ-ONLY · Item Unit Of Measures · GET /item-units-of-measure/{id}/

Retrieve item unit of measure

Endpoint for retrieving a single item unit of measure.

Inputs: id (required).

wafeq_item_units_of_measure_updateC
Idempotent

🟑 WRITE · updates data · Item Unit Of Measures · PUT /item-units-of-measure/{id}/

Update item unit of measure

Endpoint for updating an existing item unit of measure.

Inputs: id (required), body (required), idempotency_key.

wafeq_journal_line_items_listA
Read-onlyIdempotent

🟒 READ-ONLY · Journal Line Items · GET /journal-line-items/

List journal line items

Endpoint for retrieving a list of journal line items.

NO DATE FIELD: rows carry created_ts (when the row was written to Wafeq) and modified_ts, but NOT the transaction date. created_ts is frequently a different month from the transaction β€” do not report it as the transaction date. To work by transaction date, filter with date_after/date_before, which DO operate on the real transaction date. For rows that come back already carrying their date, use the wafeq_account_ledger tool instead. Note this endpoint is cursor-paginated (cursor + page_size), unlike the rest of the API, which uses page.

Inputs: branch, cursor, account, contact, +12 more.

wafeq_journal_line_items_retrieveA
Read-onlyIdempotent

🟒 READ-ONLY · Journal Line Items · GET /journal-line-items/{id}/

Retrieve journal line item

Endpoint for retrieving a single journal line item.

NO DATE FIELD: the row carries created_ts (when it was written to Wafeq), which is not the transaction date. The transaction date lives on the parent journal referenced by the journal field.

Inputs: id (required).

wafeq_manual_journals_createA

🟑 WRITE · creates data · Manual Journals · POST /manual-journals/

Create manual journal

Endpoint for creating a new manual journal.

Not idempotent β€” calling twice creates two records. Pass idempotency_key (or let the server generate one) to make a retry safe.

Inputs: body (required), idempotency_key.

wafeq_manual_journals_destroyA
DestructiveIdempotent

πŸ”΄ DESTRUCTIVE Β· deletes Β· Manual Journals Β· DELETE /manual-journals/{id}/

Delete manual journal

Endpoint for deleting an existing manual journal.

Permanently removes the record.

Inputs: id (required), idempotency_key.

wafeq_manual_journals_listC
Read-onlyIdempotent

🟒 READ-ONLY · Manual Journals · GET /manual-journals/

List manual journals

Endpoint for retrieving a list of manual journals.

Inputs: page, page_size, reference, date_after, +6 more.

wafeq_manual_journals_partial_updateB
Idempotent

🟑 WRITE · updates data · Manual Journals · PATCH /manual-journals/{id}/

Partial update manual journal

Endpoint for partially updating an existing manual journal.

Inputs: id (required), body, idempotency_key.

wafeq_manual_journals_retrieveA
Read-onlyIdempotent

🟒 READ-ONLY · Manual Journals · GET /manual-journals/{id}/

Retrieve manual journal

Endpoint for retrieving a single manual journal.

Inputs: id (required).

wafeq_manual_journals_updateC
Idempotent

🟑 WRITE · updates data · Manual Journals · PUT /manual-journals/{id}/

Update manual journal

Endpoint for updating an existing manual journal.

Inputs: id (required), body (required), idempotency_key.

wafeq_organization_retrieveA
Read-onlyIdempotent

🟒 READ-ONLY · Organizations · GET /organization/

Retrieve organization

Endpoint for retrieving a single organization.

Inputs: no named parameters.

wafeq_payment_requests_createA

🟑 WRITE · creates data · Payment Requests · POST /payment_requests/

Create payment request

Endpoint for creating a new payment request.

Not idempotent β€” calling twice creates two records. Pass idempotency_key (or let the server generate one) to make a retry safe.

Inputs: body (required), idempotency_key.

wafeq_payment_requests_destroyA
DestructiveIdempotent

πŸ”΄ DESTRUCTIVE Β· deletes Β· Payment Requests Β· DELETE /payment_requests/{id}/

Delete payment request

Endpoint for deleting an existing payment request.

Permanently removes the record.

Inputs: id (required), idempotency_key.

wafeq_payment_requests_listB
Read-onlyIdempotent

🟒 READ-ONLY · Payment Requests · GET /payment_requests/

List payment requests

Endpoint for retrieving a list of payment requests.

Inputs: page, status, currency, page_size, +8 more.

wafeq_payment_requests_partial_updateA
Idempotent

🟑 WRITE · updates data · Payment Requests · PATCH /payment_requests/{id}/

Partial update payment request

Endpoint for partially updating an existing payment request.

Inputs: id (required), body, idempotency_key.

wafeq_payment_requests_retrieveB
Read-onlyIdempotent

🟒 READ-ONLY · Payment Requests · GET /payment_requests/{id}/

Retrieve payment request

Endpoint for retrieving a single payment request.

Inputs: id (required).

wafeq_payment_requests_updateC
Idempotent

🟑 WRITE · updates data · Payment Requests · PUT /payment_requests/{id}/

Update payment request

Endpoint for updating an existing payment request.

Inputs: id (required), body (required), idempotency_key.

wafeq_payments_createA

🟑 WRITE · creates data · Payments · POST /payments/

Create payment

Endpoint for creating a new payment.

Not idempotent β€” calling twice creates two records. Pass idempotency_key (or let the server generate one) to make a retry safe.

Inputs: body (required), idempotency_key.

wafeq_payments_destroyC
DestructiveIdempotent

πŸ”΄ DESTRUCTIVE Β· deletes Β· Payments Β· DELETE /payments/{id}/

Delete payment

Endpoint for deleting an existing payment.

Permanently removes the record.

Inputs: id (required), idempotency_key.

wafeq_payments_download_retrieveA
Read-onlyIdempotent

🟒 READ-ONLY · returns a PDF · Payments · GET /payments/{id}/download/

Download payment PDF

Endpoint for downloading a PDF of the payment.

Returns the document as base64-encoded PDF bytes plus its size and content type. Nothing is modified.

Inputs: id (required).

wafeq_payments_listC
Read-onlyIdempotent

🟒 READ-ONLY · Payments · GET /payments/

List payments

Endpoint for retrieving a list of payments.

Inputs: date, page, contact, project, +9 more.

wafeq_payments_partial_updateC
Idempotent

🟑 WRITE · updates data · Payments · PATCH /payments/{id}/

Partial update payment

Endpoint for partially updating an existing payment.

Inputs: id (required), body, idempotency_key.

wafeq_payments_retrieveC
Read-onlyIdempotent

🟒 READ-ONLY · Payments · GET /payments/{id}/

Retrieve payment

Endpoint for retrieving a single payment.

Inputs: id (required).

wafeq_payments_updateC
Idempotent

🟑 WRITE · updates data · Payments · PUT /payments/{id}/

Update payment

Endpoint for updating an existing payment.

Inputs: id (required), body (required), idempotency_key.

wafeq_payslips_createA

🟑 WRITE · creates data · Payslips · POST /payslips/

Create payslip

Endpoint for creating a new payslip.

Not idempotent β€” calling twice creates two records. Pass idempotency_key (or let the server generate one) to make a retry safe.

Inputs: body (required), idempotency_key.

wafeq_payslips_destroyB
DestructiveIdempotent

πŸ”΄ DESTRUCTIVE Β· deletes Β· Payslips Β· DELETE /payslips/{id}/

Delete payslip

Endpoint for deleting an existing payslip.

Permanently removes the record.

Inputs: id (required), idempotency_key.

wafeq_payslips_download_retrieveA
Read-onlyIdempotent

🟒 READ-ONLY · returns a PDF · Payslips · GET /payslips/{id}/download/

Download payslip PDF

Endpoint for downloading a PDF of the payslip.

Returns the document as base64-encoded PDF bytes plus its size and content type. Nothing is modified.

Inputs: id (required).

wafeq_payslips_listB
Read-onlyIdempotent

🟒 READ-ONLY · Payslips · GET /payslips/

List payslips

Endpoint for retrieving a list of payslips.

Inputs: page, branch, project, employee, +7 more.

wafeq_payslips_partial_updateA
Idempotent

🟑 WRITE · updates data · Payslips · PATCH /payslips/{id}/

Partial update payslip

Endpoint for partially updating an existing payslip.

Inputs: id (required), body, idempotency_key.

wafeq_payslips_pay_items_createB

🟑 WRITE · creates data · Pay Items · POST /payslips/{payslip_id}/pay-items/

Create pay item

Endpoint for creating a new pay item.

Not idempotent β€” calling twice creates two records. Pass idempotency_key (or let the server generate one) to make a retry safe.

Inputs: body (required), payslip_id (required), idempotency_key.

wafeq_payslips_pay_items_destroyA
DestructiveIdempotent

πŸ”΄ DESTRUCTIVE Β· deletes Β· Pay Items Β· DELETE /payslips/{payslip_id}/pay-items/{id}/

Delete pay item

Endpoint for deleting an existing pay item.

Permanently removes the record.

Inputs: id (required), payslip_id (required), idempotency_key.

wafeq_payslips_pay_items_listC
Read-onlyIdempotent

🟒 READ-ONLY · Pay Items · GET /payslips/{payslip_id}/pay-items/

List pay items

Endpoint for retrieving a list of pay items.

Inputs: payslip_id (required), page, page_size.

wafeq_payslips_pay_items_partial_updateB
Idempotent

🟑 WRITE · updates data · Pay Items · PATCH /payslips/{payslip_id}/pay-items/{id}/

Partial update pay item

Endpoint for partially updating an existing pay item.

Inputs: id (required), payslip_id (required), body, idempotency_key.

wafeq_payslips_pay_items_retrieveB
Read-onlyIdempotent

🟒 READ-ONLY · Pay Items · GET /payslips/{payslip_id}/pay-items/{id}/

Retrieve pay item

Endpoint for retrieving a single pay item.

Inputs: id (required), payslip_id (required).

wafeq_payslips_pay_items_updateB
Idempotent

🟑 WRITE · updates data · Pay Items · PUT /payslips/{payslip_id}/pay-items/{id}/

Update pay item

Endpoint for updating an existing pay item.

Inputs: id (required), body (required), payslip_id (required), idempotency_key.

wafeq_payslips_retrieveA
Read-onlyIdempotent

🟒 READ-ONLY · Payslips · GET /payslips/{id}/

Retrieve payslip

Endpoint for retrieving a single payslip.

Inputs: id (required).

wafeq_payslips_updateC
Idempotent

🟑 WRITE · updates data · Payslips · PUT /payslips/{id}/

Update payslip

Endpoint for updating an existing payslip.

Inputs: id (required), body (required), idempotency_key.

wafeq_projects_createA

🟑 WRITE · creates data · Projects · POST /projects/

Create project

Endpoint for creating a new project.

Not idempotent β€” calling twice creates two records. Pass idempotency_key (or let the server generate one) to make a retry safe.

Inputs: body (required), idempotency_key.

wafeq_projects_destroyA
DestructiveIdempotent

πŸ”΄ DESTRUCTIVE Β· deletes Β· Projects Β· DELETE /projects/{id}/

Delete project

Endpoint for deleting an existing project.

Permanently removes the record.

Inputs: id (required), idempotency_key.

wafeq_projects_listA
Read-onlyIdempotent

🟒 READ-ONLY · Projects · GET /projects/

List projects

Endpoint for retrieving a list of projects.

Inputs: page, page_size.

wafeq_projects_partial_updateC
Idempotent

🟑 WRITE · updates data · Projects · PATCH /projects/{id}/

Partial update project

Endpoint for partially updating an existing project.

Inputs: id (required), body, idempotency_key.

wafeq_projects_retrieveB
Read-onlyIdempotent

🟒 READ-ONLY · Projects · GET /projects/{id}/

Retrieve project

Endpoint for retrieving a single project.

Inputs: id (required).

wafeq_projects_updateB
Idempotent

🟑 WRITE · updates data · Projects · PUT /projects/{id}/

Update project

Endpoint for updating an existing project.

Inputs: id (required), body (required), idempotency_key.

wafeq_purchase_orders_bill_createA

🟑 WRITE · creates data · Purchase Orders · POST /purchase-orders/{id}/bill/

Convert purchase order to bill

This endpoint can be used to convert a purchase order to a draft bill.

Not idempotent β€” calling twice creates two records. Pass idempotency_key (or let the server generate one) to make a retry safe.

Creates a NEW draft bill from the purchase order. Calling twice creates two bills β€” pass an idempotency_key if you may retry.

Inputs: id (required).

wafeq_purchase_orders_createA

🟑 WRITE · creates data · Purchase Orders · POST /purchase-orders/

Create purchase order

Endpoint for creating a new purchase order.

Not idempotent β€” calling twice creates two records. Pass idempotency_key (or let the server generate one) to make a retry safe.

Inputs: body (required), idempotency_key.

wafeq_purchase_orders_destroyA
DestructiveIdempotent

πŸ”΄ DESTRUCTIVE Β· deletes Β· Purchase Orders Β· DELETE /purchase-orders/{id}/

Delete purchase order

Endpoint for deleting an existing purchase order.

Permanently removes the record.

Inputs: id (required), idempotency_key.

wafeq_purchase_orders_download_retrieveA
Read-onlyIdempotent

🟒 READ-ONLY · returns a PDF · Purchase Orders · GET /purchase-orders/{id}/download/

Download purchase order PDF

Endpoint for downloading a PDF of the purchase order.

Returns the document as base64-encoded PDF bytes plus its size and content type. Nothing is modified.

Inputs: id (required).

wafeq_purchase_orders_line_items_createA

🟑 WRITE · creates data · Purchase Order Line Items · POST /purchase-orders/{purchase_order_id}/line-items/

Create purchase order line item

Endpoint for creating a new purchase order line item.

Not idempotent β€” calling twice creates two records. Pass idempotency_key (or let the server generate one) to make a retry safe.

Inputs: body (required), purchase_order_id (required), idempotency_key.

wafeq_purchase_orders_line_items_destroyA
DestructiveIdempotent

πŸ”΄ DESTRUCTIVE Β· deletes Β· Purchase Order Line Items Β· DELETE /purchase-orders/{purchase_order_id}/line-items/{id}/

Delete purchase order line item

Endpoint for deleting an existing purchase order line item.

Permanently removes the record.

Inputs: id (required), purchase_order_id (required), idempotency_key.

wafeq_purchase_orders_line_items_listB
Read-onlyIdempotent

🟒 READ-ONLY · Purchase Order Line Items · GET /purchase-orders/{purchase_order_id}/line-items/

List purchase order line items

Endpoint for retrieving a list of purchase order line items.

Inputs: purchase_order_id (required), page, page_size.

wafeq_purchase_orders_line_items_partial_updateC
Idempotent

🟑 WRITE · updates data · Purchase Order Line Items · PATCH /purchase-orders/{purchase_order_id}/line-items/{id}/

Partial update purchase order line item

Endpoint for partially updating an existing purchase order line item.

Inputs: id (required), purchase_order_id (required), body, idempotency_key.

wafeq_purchase_orders_line_items_retrieveA
Read-onlyIdempotent

🟒 READ-ONLY · Purchase Order Line Items · GET /purchase-orders/{purchase_order_id}/line-items/{id}/

Retrieve purchase order line item

Endpoint for retrieving a single purchase order line item.

Inputs: id (required), purchase_order_id (required).

wafeq_purchase_orders_line_items_updateC
Idempotent

🟑 WRITE · updates data · Purchase Order Line Items · PUT /purchase-orders/{purchase_order_id}/line-items/{id}/

Update purchase order line item

Endpoint for updating an existing purchase order line item.

Inputs: id (required), body (required), purchase_order_id (required), idempotency_key.

wafeq_purchase_orders_listC
Read-onlyIdempotent

🟒 READ-ONLY · Purchase Orders · GET /purchase-orders/

List purchase orders

Endpoint for retrieving a list of purchase orders.

Inputs: page, branch, status, contact, +9 more.

wafeq_purchase_orders_partial_updateB
Idempotent

🟑 WRITE · updates data · Purchase Orders · PATCH /purchase-orders/{id}/

Partial update purchase order

Endpoint for partially updating an existing purchase order.

Inputs: id (required), body, idempotency_key.

wafeq_purchase_orders_retrieveB
Read-onlyIdempotent

🟒 READ-ONLY · Purchase Orders · GET /purchase-orders/{id}/

Retrieve purchase order

Endpoint for retrieving a single purchase order.

Inputs: id (required).

wafeq_purchase_orders_updateC
Idempotent

🟑 WRITE · updates data · Purchase Orders · PUT /purchase-orders/{id}/

Update purchase order

Endpoint for updating an existing purchase order.

Inputs: id (required), body (required), idempotency_key.

wafeq_quotes_createA

🟑 WRITE · creates data · Quotes · POST /quotes/

Create quote

Endpoint for creating a new quote.

Not idempotent β€” calling twice creates two records. Pass idempotency_key (or let the server generate one) to make a retry safe.

Inputs: body (required), idempotency_key.

wafeq_quotes_destroyA
DestructiveIdempotent

πŸ”΄ DESTRUCTIVE Β· deletes Β· Quotes Β· DELETE /quotes/{id}/

Delete quote

Endpoint for deleting an existing quote.

Permanently removes the record.

Inputs: id (required), idempotency_key.

wafeq_quotes_download_retrieveA
Read-onlyIdempotent

🟒 READ-ONLY · returns a PDF · Quotes · GET /quotes/{id}/download/

Download quote PDF

Endpoint for downloading a PDF of the quote.

Returns the document as base64-encoded PDF bytes plus its size and content type. Nothing is modified.

Inputs: id (required).

wafeq_quotes_invoice_createA

🟑 WRITE · creates data · Quotes · POST /quotes/{id}/invoice/

Convert quote to invoice

This endpoint can be used to convert a quote to an invoice.

Not idempotent β€” calling twice creates two records. Pass idempotency_key (or let the server generate one) to make a retry safe.

Creates a NEW invoice from the quote. Calling twice creates two invoices β€” pass an idempotency_key if you may retry.

Inputs: id (required).

wafeq_quotes_line_items_createB

🟑 WRITE · creates data · Quote Line Items · POST /quotes/{quote_id}/line-items/

Create quote line item

Endpoint for creating a new quote line item.

Not idempotent β€” calling twice creates two records. Pass idempotency_key (or let the server generate one) to make a retry safe.

Inputs: body (required), quote_id (required), idempotency_key.

wafeq_quotes_line_items_destroyA
DestructiveIdempotent

πŸ”΄ DESTRUCTIVE Β· deletes Β· Quote Line Items Β· DELETE /quotes/{quote_id}/line-items/{id}/

Delete quote line item

Endpoint for deleting an existing quote line item.

Permanently removes the record.

Inputs: id (required), quote_id (required), idempotency_key.

wafeq_quotes_line_items_listA
Read-onlyIdempotent

🟒 READ-ONLY · Quote Line Items · GET /quotes/{quote_id}/line-items/

List quote line items

Endpoint for retrieving a list of quote line items.

Inputs: quote_id (required), page, page_size.

wafeq_quotes_line_items_partial_updateC
Idempotent

🟑 WRITE · updates data · Quote Line Items · PATCH /quotes/{quote_id}/line-items/{id}/

Partial update quote line item

Endpoint for partially updating an existing quote line item.

Inputs: id (required), quote_id (required), body, idempotency_key.

wafeq_quotes_line_items_retrieveA
Read-onlyIdempotent

🟒 READ-ONLY · Quote Line Items · GET /quotes/{quote_id}/line-items/{id}/

Retrieve quote line item

Endpoint for retrieving a single quote line item.

Inputs: id (required), quote_id (required).

wafeq_quotes_line_items_updateC
Idempotent

🟑 WRITE · updates data · Quote Line Items · PUT /quotes/{quote_id}/line-items/{id}/

Update quote line item

Endpoint for updating an existing quote line item.

Inputs: id (required), body (required), quote_id (required), idempotency_key.

wafeq_quotes_listC
Read-onlyIdempotent

🟒 READ-ONLY · Quotes · GET /quotes/

List quotes

Endpoint for retrieving a list of quotes.

Inputs: page, branch, status, contact, +9 more.

wafeq_quotes_partial_updateA
Idempotent

🟑 WRITE · updates data · Quotes · PATCH /quotes/{id}/

Partial update quote

Endpoint for partially updating an existing quote.

Inputs: id (required), body, idempotency_key.

wafeq_quotes_retrieveA
Read-onlyIdempotent

🟒 READ-ONLY · Quotes · GET /quotes/{id}/

Retrieve quote

Endpoint for retrieving a single quote.

Inputs: id (required).

wafeq_quotes_updateC
Idempotent

🟑 WRITE · updates data · Quotes · PUT /quotes/{id}/

Update quote

Endpoint for updating an existing quote.

Inputs: id (required), body (required), idempotency_key.

wafeq_reports_balance_sheet_listA
Read-onlyIdempotent

🟒 READ-ONLY · Reports · GET /reports/balance-sheet/

Balance Sheet

Generate balance sheet report in currency at date with period_count periods to compare and group it by group_by parameter.

PARAMETERS: this report takes date (the 'as of' date) and period_count (0-11 extra comparison periods) β€” both REQUIRED. It does NOT take a date range; there is no date_from/date_to/date_after/date_before. group_by (month|year) sets the size of the comparison periods.

Inputs: date (required), period_count (required), currency, group_by, +3 more.

wafeq_reports_cash_flow_listA
Read-onlyIdempotent

🟒 READ-ONLY · Reports · GET /reports/cash-flow/

Cash Flow

Generate cash flow report in currency from date_after to date_before range and group it by group_by parameter.

PARAMETERS: date_after and date_before are both REQUIRED and are the range bounds. There is no date_from/date_to. The same whole-period rule as profit-and-loss applies and is checked before sending.

Inputs: date_after (required), date_before (required), currency, group_by, +3 more.

wafeq_reports_profit_and_loss_listA
Read-onlyIdempotent

🟒 READ-ONLY · Reports · GET /reports/profit-and-loss/

Profit and Loss

Generate profit and loss report in currency from date_after to date_before range and group it by group_by parameter.

PARAMETERS: date_after and date_before are both REQUIRED and are the range bounds. There is no date_from/date_to. The range must cover whole periods: with group_by=month (the default) it must run from the first day of a month to the last day of a month; with group_by=year it must run 1 January to 31 December. A partial year with group_by=year is rejected β€” use group_by=month for a year-to-date figure. This server checks the range before sending and tells you the nearest valid one.

Inputs: date_after (required), date_before (required), currency, group_by, +4 more.

wafeq_reports_trial_balance_listA
Read-onlyIdempotent

🟒 READ-ONLY · Reports · GET /reports/trial-balance/

Trial Balance

Generate trial balance report from from_date to to_date optionally with PNL openings with_pnl_openings and accounts with zero balances include_zero_balances.

PARAMETERS: this report uses from_date and to_date (NOT date_after/date_before, and NOT date_from/date_to). Both are optional; omitting them returns the current financial year. Verified 2026-09-04: the dates ARE honoured when spelled correctly β€” a narrower range returns a smaller report. Wafeq silently ignores misspelled query parameters rather than erroring, so a wrong name looks like a working call that returns the default period.

Inputs: to_date, from_date, branch__in, contact__in, +4 more.

wafeq_requestA
Destructive

πŸ”΄ DESTRUCTIVE Β· arbitrary API call Β· Escape hatch Β· any method, any path

Call any Wafeq endpoint directly, with full control over method, path, query, body AND headers.

This is the FALLBACK, not the primary interface: every documented endpoint already has its own generated tool with a correct input schema and an accurate safety category. Reach for this only for something the bundled spec does not cover.

It is categorized destructive because the effect cannot be known in advance β€” the same tool can read a report or delete an invoice. Confirm with the user before any non-GET call.

Writes get an automatic X-Wafeq-Idempotency-Key unless you supply one in headers. Authorization is always set from the server's own credentials and cannot be overridden.

Inputs: path (required), method (required), body, query, +1 more.

wafeq_revenue_recognitions_destroyA
DestructiveIdempotent

πŸ”΄ DESTRUCTIVE Β· deletes Β· Revenue Recognitions Β· DELETE /revenue-recognitions/{id}/

Delete revenue recognition

Endpoint for deleting an existing revenue recognition.

Permanently removes the record.

Inputs: id (required), idempotency_key.

wafeq_revenue_recognitions_end_early_createA
Destructive

πŸ”΄ IRREVERSIBLE Β· posts the remaining balance to the ledger Β· Revenue Recognitions Β· POST /revenue-recognitions/{id}/end-early/

End revenue recognition early

Endpoint for terminating a revenue recognition early, recognizing the remaining balance against the provided account.

Terminates a schedule early and recognizes its whole remaining balance immediately. There is no API undo. Run the matching preview_... tool first to see exactly what would be posted.

Inputs: id (required), body (required).

wafeq_revenue_recognitions_listC
Read-onlyIdempotent

🟒 READ-ONLY · Revenue Recognitions · GET /revenue-recognitions/

List revenue recognitions

Endpoint for retrieving a list of revenue recognitions.

Inputs: page, duration, page_size, status__in, +5 more.

wafeq_revenue_recognitions_preview_createA
Read-onlyIdempotent

🟒 READ-ONLY · preview / simulation · Revenue Recognitions · POST /revenue-recognitions/preview/

Preview revenue recognition schedule

Endpoint for previewing the revenue recognition events that would be generated for the given schedule, without creating a revenue recognition.

This is a POST, but Wafeq documents it as a simulation: it returns the events that WOULD be generated and writes nothing to the ledger.

Inputs: body (required), duration, status__in, end_date_after, +4 more.

wafeq_revenue_recognitions_preview_end_early_createA
Read-onlyIdempotent

🟒 READ-ONLY · preview / simulation · Revenue Recognitions · POST /revenue-recognitions/{id}/preview-end-early/

Preview early termination

Endpoint for previewing the remaining balance and the posted events that would be reversed by terminating the revenue recognition early at the given date.

This is a POST, but Wafeq documents it as a simulation: it returns the events that WOULD be generated and writes nothing to the ledger.

Inputs: id (required), body (required).

wafeq_revenue_recognitions_retrieveB
Read-onlyIdempotent

🟒 READ-ONLY · Revenue Recognitions · GET /revenue-recognitions/{id}/

Retrieve revenue recognition

Endpoint for retrieving a single revenue recognition.

Inputs: id (required).

wafeq_simplified_invoices_createB

🟑 WRITE · creates data · Simplified Invoices · POST /simplified-invoices/

Create simplified invoice

Endpoint for creating a new simplified invoice.

Not idempotent β€” calling twice creates two records. Pass idempotency_key (or let the server generate one) to make a retry safe.

Inputs: body (required), idempotency_key.

wafeq_simplified_invoices_destroyB
DestructiveIdempotent

πŸ”΄ DESTRUCTIVE Β· deletes Β· Simplified Invoices Β· DELETE /simplified-invoices/{id}/

Delete simplified invoice

Endpoint for deleting an existing simplified invoice.

Permanently removes the record.

Inputs: id (required), idempotency_key.

wafeq_simplified_invoices_download_retrieveA
Read-onlyIdempotent

🟒 READ-ONLY · returns a PDF · Simplified Invoices · GET /simplified-invoices/{id}/download/

Download simplified invoice PDF

Endpoint for downloading a PDF of the simplified invoice.

Returns the document as base64-encoded PDF bytes plus its size and content type. Nothing is modified.

Inputs: id (required).

wafeq_simplified_invoices_line_items_createA

🟑 WRITE · creates data · Simplified Invoice Line Items · POST /simplified-invoices/{invoice_id}/line-items/

Create simplified invoice line item

Endpoint for creating a new simplified invoice line item.

Not idempotent β€” calling twice creates two records. Pass idempotency_key (or let the server generate one) to make a retry safe.

Inputs: body (required), invoice_id (required), idempotency_key.

wafeq_simplified_invoices_line_items_destroyA
DestructiveIdempotent

πŸ”΄ DESTRUCTIVE Β· deletes Β· Simplified Invoice Line Items Β· DELETE /simplified-invoices/{invoice_id}/line-items/{id}/

Delete simplified invoice line item

Endpoint for deleting an existing simplified invoice line item.

Permanently removes the record.

Inputs: id (required), invoice_id (required), idempotency_key.

wafeq_simplified_invoices_line_items_listB
Read-onlyIdempotent

🟒 READ-ONLY · Simplified Invoice Line Items · GET /simplified-invoices/{invoice_id}/line-items/

List simplified invoice line items

Endpoint for retrieving a list of simplified invoice line items.

Inputs: invoice_id (required), page, page_size.

wafeq_simplified_invoices_line_items_partial_updateB
Idempotent

🟑 WRITE · updates data · Simplified Invoice Line Items · PATCH /simplified-invoices/{invoice_id}/line-items/{id}/

Partial update simplified invoice line item

Endpoint for partially updating an existing simplified invoice line item.

Inputs: id (required), invoice_id (required), body, idempotency_key.

wafeq_simplified_invoices_line_items_retrieveB
Read-onlyIdempotent

🟒 READ-ONLY · Simplified Invoice Line Items · GET /simplified-invoices/{invoice_id}/line-items/{id}/

Retrieve simplified invoice line item

Endpoint for retrieving a single simplified invoice line item.

Inputs: id (required), invoice_id (required).

wafeq_simplified_invoices_line_items_updateC
Idempotent

🟑 WRITE · updates data · Simplified Invoice Line Items · PUT /simplified-invoices/{invoice_id}/line-items/{id}/

Update simplified invoice line item

Endpoint for updating an existing simplified invoice line item.

Inputs: id (required), body (required), invoice_id (required), idempotency_key.

wafeq_simplified_invoices_listB
Read-onlyIdempotent

🟒 READ-ONLY · Simplified Invoices · GET /simplified-invoices/

List simplified invoices

Endpoint for retrieving a list of simplified invoices.

Inputs: page, branch, contact, project, +7 more.

wafeq_simplified_invoices_partial_updateC
Idempotent

🟑 WRITE · updates data · Simplified Invoices · PATCH /simplified-invoices/{id}/

Partial update simplified invoice

Endpoint for partially updating an existing simplified invoice.

Inputs: id (required), body, idempotency_key.

wafeq_simplified_invoices_retrieveA
Read-onlyIdempotent

🟒 READ-ONLY · Simplified Invoices · GET /simplified-invoices/{id}/

Retrieve simplified invoice

Endpoint for retrieving a single simplified invoice.

Inputs: id (required).

wafeq_simplified_invoices_tax_authority_report_createA
Destructive

πŸ”΄ IRREVERSIBLE Β· files the document with an external tax authority Β· Simplified Invoices Β· POST /simplified-invoices/{id}/tax-authority/report/

Report simplified invoice to tax authority

Report the simplified invoice to the tax authority for processing and validation.

Submits the document outside your organization for clearance/reporting. It CANNOT be recalled or undone through this API. Confirm with the user before calling, and check the document's contents first.

Inputs: id (required), idempotency_key.

wafeq_simplified_invoices_updateC
Idempotent

🟑 WRITE · updates data · Simplified Invoices · PUT /simplified-invoices/{id}/

Update simplified invoice

Endpoint for updating an existing simplified invoice.

Inputs: id (required), body (required), idempotency_key.

wafeq_tax_rates_listB
Read-onlyIdempotent

🟒 READ-ONLY · Tax Rates · GET /tax-rates/

List tax rates

Endpoint for retrieving a list of tax rates.

Inputs: page, tax_type, page_size, external_id, +4 more.

wafeq_units_of_measure_createB

🟑 WRITE · creates data · Unit Of Measures · POST /units-of-measure/

Create unit of measure

Endpoint for creating a new unit of measure.

Not idempotent β€” calling twice creates two records. Pass idempotency_key (or let the server generate one) to make a retry safe.

Inputs: body (required), idempotency_key.

wafeq_units_of_measure_destroyA
DestructiveIdempotent

πŸ”΄ DESTRUCTIVE Β· deletes Β· Unit Of Measures Β· DELETE /units-of-measure/{id}/

Delete unit of measure

Endpoint for deleting an existing unit of measure.

Permanently removes the record.

Inputs: id (required), idempotency_key.

wafeq_units_of_measure_listB
Read-onlyIdempotent

🟒 READ-ONLY · Unit Of Measures · GET /units-of-measure/

List unit of measures

Endpoint for retrieving a list of unit of measures.

Inputs: page, page_size.

wafeq_units_of_measure_partial_updateC
Idempotent

🟑 WRITE · updates data · Unit Of Measures · PATCH /units-of-measure/{id}/

Partial update unit of measure

Endpoint for partially updating an existing unit of measure.

Inputs: id (required), body, idempotency_key.

wafeq_units_of_measure_retrieveA
Read-onlyIdempotent

🟒 READ-ONLY · Unit Of Measures · GET /units-of-measure/{id}/

Retrieve unit of measure

Endpoint for retrieving a single unit of measure.

Inputs: id (required).

wafeq_units_of_measure_updateB
Idempotent

🟑 WRITE · updates data · Unit Of Measures · PUT /units-of-measure/{id}/

Update unit of measure

Endpoint for updating an existing unit of measure.

Inputs: id (required), body (required), idempotency_key.

wafeq_upload_fileA

🟑 WRITE · creates data · Files · POST /files/

Create file

Endpoint for creating a new file. Upload a file using multipart/form-data.

Not idempotent β€” calling twice creates two records. Pass idempotency_key (or let the server generate one) to make a retry safe.

Send the file with file_base64 plus filename (and optionally content_type); this server builds the multipart/form-data body for you. For a file already on the machine running this server, pass file_path instead.

Inputs: filename (required), file_path, file_base64, content_type.

wafeq_upload_file_rawA

🟑 WRITE · creates data · Files · POST /files/raw/

Create file (advance)

Create file in advance mode by sending raw binary file content directly in the request body. You must include a Content-Disposition header with the filename.

Not idempotent β€” calling twice creates two records. Pass idempotency_key (or let the server generate one) to make a retry safe.

Advanced upload: sends the bytes as the raw request body with a Content-Disposition header. Prefer upload_file unless you specifically need raw mode. Provide file_base64 + filename, or file_path.

Inputs: filename (required), file_path, file_base64, content_type.

wafeq_warehouses_createA

🟑 WRITE · creates data · Warehouses · POST /warehouses/

Create warehouse

Endpoint for creating a new warehouse.

Not idempotent β€” calling twice creates two records. Pass idempotency_key (or let the server generate one) to make a retry safe.

Inputs: body (required), idempotency_key.

wafeq_warehouses_destroyA
DestructiveIdempotent

πŸ”΄ DESTRUCTIVE Β· deletes Β· Warehouses Β· DELETE /warehouses/{id}/

Delete warehouse

Endpoint for deleting an existing warehouse.

Permanently removes the record.

Inputs: id (required), idempotency_key.

wafeq_warehouses_listB
Read-onlyIdempotent

🟒 READ-ONLY · Warehouses · GET /warehouses/

List warehouses

Endpoint for retrieving a list of warehouses.

Inputs: page, page_size.

wafeq_warehouses_partial_updateB
Idempotent

🟑 WRITE · updates data · Warehouses · PATCH /warehouses/{id}/

Partial update warehouse

Endpoint for partially updating an existing warehouse.

Inputs: id (required), body, idempotency_key.

wafeq_warehouses_retrieveA
Read-onlyIdempotent

🟒 READ-ONLY · Warehouses · GET /warehouses/{id}/

Retrieve warehouse

Endpoint for retrieving a single warehouse.

Inputs: id (required).

wafeq_warehouses_updateC
Idempotent

🟑 WRITE · updates data · Warehouses · PUT /warehouses/{id}/

Update warehouse

Endpoint for updating an existing warehouse.

Inputs: id (required), body (required), idempotency_key.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    B3.1/5.0

    Scored across 253 tools

    Disambiguation4/5

    Each of the ~250 tools targets a specific resource-action pair (e.g., list, create, retrieve, update, destroy, partial_update), and resource names in tool names make most selections unambiguous. A few intentional overlaps existβ€”wafeq_upload_file vs wafeq_upload_file_raw, journal_line_items vs account_ledger, and the wafeq_request escape hatchβ€”but their descriptions clearly delineate when to use each.

    Naming Consistency4/5

    The overwhelming majority follow a consistent wafeq_<resource>_<action> snake_case pattern with standardized verbs (list/create/retrieve/update/destroy/partial_update). Minor deviations exist for special tools (wafeq_upload_file, wafeq_account_ledger, wafeq_request) but these are few and intentional.

    Tool Count1/5

    253 tools is an extreme count for a single MCP server, even for a full accounting API. This volume will overwhelm agent context and make tool selection slow and error-prone, pushing the score to the bottom of the scale. A broader API is better served by focused servers per domain (e.g., invoicing, payroll, reports).

    Completeness4/5

    The surface provides full CRUD plus domain actions for nearly every resource: PDF downloads, tax-authority reporting, draft/posted transitions, quote-to-invoice and purchase-order-to-bill conversions, and previews for amortizations and revenue recognitions. Minor gaps exist (organization is retrieve-only, tax_rates are list-only), but the core accounting workflows are well covered.

    Maintenance

    ActivitySlowing
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      B
      quality
      B
      maintenance
      A Model Context Protocol (MCP) server for the Holded Invoice API. This server allows AI assistants like Claude to interact with Holded's invoicing, contacts, products, and more.
      119
      103 npm
      20
      MIT
    • A
      license
      Not graded
      quality
      F
      maintenance
      MCP server for Watermelon.ai that exposes all 13 public API endpoints as tools, enabling AI assistants to manage contacts, conversations, messages, custom fields, and webhooks.
      MIT
    • A
      license
      Not graded
      quality
      D
      maintenance
      Model Context Protocol (MCP) server for SuperFaktura invoicing system. Enables AI assistants to interact with SuperFaktura API for managing invoices, clients, and expenses.
      Apache 2.0