Overview
The Wumex Billing API is a RESTful JSON API that allows you to send invoices digitally to your customers. Recipients receive invoices directly in the Wumex app — with push notifications, automatic categorization, and real-time payment status.
The API is designed for businesses, accounting systems, ERP providers, and developers who want to integrate invoicing into their applications.
Key features:
- Send invoices via API to email addresses or Wumex IDs
- Real-time status tracking (delivered, viewed, paid)
- Webhook notifications for all status changes
- Swiss QR invoice support (QR reference, IBAN)
- Batch processing and attachments
Authentication
All API requests must be authenticated with an API key. Send your key in the X-API-Key header with every request.
You can obtain your API key after registering at Wumex Billing.
Example:
# Replace YOUR_API_KEY with your actual key
curl https://npylglrnvsxkwvynridg.supabase.co/functions/v1/billing-api/invoices \
-H "X-API-Key: YOUR_API_KEY"Base URL
All API endpoints use the following base URL:
https://npylglrnvsxkwvynridg.supabase.co/functions/v1/billing-apiAll requests must be made over HTTPS. HTTP requests will be rejected.
Merchant Profile
GET /billing-api/merchants/me
Returns the profile of the currently authenticated merchant, including plan information and API key prefix.
Example Response
{
"id": "merch_9xK2mP4",
"company_name": "Muster AG",
"email": "billing@muster.ch",
"api_key_prefix": "wmx_live_7kH3...",
"plan": "pro",
"created_at": "2025-11-15T08:00:00Z"
}Create Invoice
POST /billing-api/invoices
Creates a new invoice and delivers it to the recipient.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| external_reference | string | Yes | Unique reference number |
| recipient_email | string | Yes | Customer email address |
| recipient_name | string | No | Recipient name (for matching) |
| recipient_wumex_id | string | No | Direct Wumex user ID |
| amount | number | Yes | Invoice amount |
| currency | string | No | Currency (default: CHF) |
| due_date | string | Yes | Due date in ISO 8601 format |
| issued_date | string | No | Issue date in ISO 8601 format |
| category_hint | string | No | e.g. insurance, medical, rent |
| payment_iban | string | No | IBAN for bank transfer |
| payment_qr_reference | string | No | Swiss QR reference |
| payment_payable_to | string | No | Payee name |
| line_items | array | No | Line items [{description, amount}] |
| attachments | array | No | Attachments [{filename, content_type, url}] |
| metadata | object | No | Free JSON object for custom data |
Example Request
// Create invoice
POST /billing-api/invoices
{
"external_reference": "INV-2026-001",
"recipient_email": "kunde@example.ch",
"recipient_name": "Max Muster",
"amount": 250.00,
"currency": "CHF",
"due_date": "2026-04-01",
"issued_date": "2026-03-01",
"category_hint": "insurance",
"payment_iban": "CH93 0076 2011 6238 5295 7",
"payment_qr_reference": "210000000003139471430009017",
"payment_payable_to": "Muster AG",
"line_items": [
{ "description": "Grundversicherung März 2026", "amount": 200.00 },
{ "description": "Zusatzversicherung", "amount": 50.00 }
],
"attachments": [
{
"filename": "rechnung.pdf",
"content_type": "application/pdf",
"url": "https://example.ch/invoices/INV-2026-001.pdf"
}
],
"metadata": {
"internal_id": "12345",
"department": "billing"
}
}Example Response
// Successful response
{
"id": "inv_7kH3mN9pQ2",
"status": "delivered",
"recipient_matched": true,
"created_at": "2026-03-01T10:00:00Z"
}Get Invoice
GET /billing-api/invoices/:id
Retrieves the current status and all details of an invoice.
Example Response
{
"id": "inv_7kH3mN9pQ2",
"external_reference": "INV-2026-001",
"status": "delivered",
"recipient_email": "kunde@example.ch",
"recipient_name": "Max Muster",
"recipient_wumex_id": "usr_4xK9mP2",
"amount": 250.00,
"currency": "CHF",
"due_date": "2026-04-01",
"issued_date": "2026-03-01",
"created_at": "2026-03-01T10:00:00Z",
"delivered_at": "2026-03-01T10:00:12Z",
"viewed_at": null,
"paid_at": null
}List Invoices
GET /billing-api/invoices?status=delivered&limit=50&offset=0&from=2026-01-01
Returns a paginated list of all invoices.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| status | string | — | Filter by status |
| limit | number | 50 | Items per page (max 100) |
| offset | number | 0 | Offset for pagination |
| from | string | — | From date (ISO 8601) |
Example Response
{
"data": [
{
"id": "inv_7kH3mN9pQ2",
"external_reference": "INV-2026-001",
"status": "delivered",
"amount": 250.00,
"currency": "CHF",
"created_at": "2026-03-01T10:00:00Z"
}
],
"total": 142,
"limit": 50,
"offset": 0
}Update Invoice
PATCH /billing-api/invoices/:id
Updates an existing invoice. You can change the reference, due date, payment info, line items, attachments, and metadata. The amount cannot be changed.
Updatable Fields
| Field | Type | Description |
|---|---|---|
| external_reference | string | New reference number |
| due_date | string | New due date |
| payment_iban | string | IBAN for bank transfer |
| payment_qr_reference | string | Swiss QR reference |
| payment_payable_to | string | Payee name |
| category_hint | string | Category hint (e.g. insurance, medical, rent) |
| line_items | array | Updated line items [{description, amount}] |
| attachments | array | Updated attachments [{filename, content_type, url}] |
| metadata | object | Updated metadata object |
Example
PATCH /billing-api/invoices/inv_7kH3mN9pQ2
{
"due_date": "2026-05-01",
"payment_iban": "CH93 0076 2011 6238 5295 7"
}Cancel Invoice
DELETE /billing-api/invoices/:id
Permanently cancels an invoice. The recipient will be notified about the cancellation.
Example Response
{
"id": "inv_7kH3mN9pQ2",
"status": "cancelled",
"cancelled_at": "2026-03-15T14:30:00Z"
}Payment Reminder
POST /billing-api/invoices/:id/remind
Sends a payment reminder to the recipient. A maximum of one reminder can be sent every 7 days per invoice.
Example Response
{
"id": "inv_7kH3mN9pQ2",
"reminder_sent": true,
"next_reminder_available_at": "2026-03-22T14:30:00Z"
}Webhooks
Webhooks notify your system in real time about status changes. Configure your webhook URL in the dashboard.
Available Events
| Event | Description |
|---|---|
| invoice.delivered | Invoice was delivered to the recipient |
| invoice.viewed | Invoice was viewed by the recipient |
| invoice.paid | Invoice was paid |
| invoice.disputed | Invoice was disputed by the recipient |
| recipient.registered | Recipient registered with Wumex |
HMAC-SHA256 Verification
Verify incoming webhooks with HMAC-SHA256 to ensure they originate from Wumex:
// Verify webhook signature
const crypto = require('crypto');
function verifyWebhook(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
// Express.js example
app.post('/webhooks/wumex', (req, res) => {
const signature = req.headers['x-wumex-signature'];
const isValid = verifyWebhook(
JSON.stringify(req.body),
signature,
process.env.WUMEX_WEBHOOK_SECRET
);
if (!isValid) {
return res.status(401).send('Invalid signature');
}
const { event, data } = req.body;
console.log(`Event: ${event}`, data);
res.status(200).send('OK');
});Status Values
Each invoice goes through different status values:
| Status | Description |
|---|---|
| pending_match | Recipient is being matched / delivery pending |
| delivered | Invoice was successfully delivered |
| viewed | Invoice was viewed by the recipient |
| paid | Invoice was paid |
| disputed | Invoice was disputed by the recipient |
| cancelled | Invoice was cancelled |
| expired | Invoice has expired (past due date) |
Error Handling
The API uses standard HTTP status codes. On errors, a JSON object with an error string is returned.
Error Format
{
"error": "The field 'amount' is required."
}HTTP Status Codes
| Code | Description |
|---|---|
| 400 | Bad Request — Missing or invalid parameters |
| 401 | Unauthorized — API key missing or invalid |
| 403 | Forbidden — No permission for this action |
| 404 | Not Found — Resource does not exist |
| 429 | Rate Limit Exceeded — Too many requests |
| 500 | Server Error — Internal error, please retry |
Rate Limits
API requests are limited per plan. When exceeded, you will receive a 429 status code.
| Plan | Limit |
|---|---|
| Free | 60 requests / minute |
| Pro | 120 requests / minute |
| Business | 300 requests / minute |
| Enterprise | Custom |
Rate limit information is returned in the response headers:
X-RateLimit-Limit: 120 // Maximum requests per minute
X-RateLimit-Remaining: 98 // Remaining requests in the current window
X-RateLimit-Reset: 1709312400 // Unix timestamp of the next resetCode Examples
Complete examples for creating an invoice in different programming languages.
curl -X POST https://npylglrnvsxkwvynridg.supabase.co/functions/v1/billing-api/invoices \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-d '{
"external_reference": "INV-2026-001",
"recipient_email": "kunde@example.ch",
"amount": 150.00,
"currency": "CHF",
"due_date": "2026-04-01",
"line_items": [
{ "description": "Beratung März 2026", "amount": 150.00 }
]
}'