Introduction
The billware API lets you create and maintain articles, customers, addresses and orders in your billware account from your own systems – for example a shop, an ERP or a script that imports orders from somewhere billware has no extension for.
Before you start
The API is an extension of your billware account. Activate it once, then open API configuration in your customer area. There you find the two values every request needs:
| API-Appid | Identifies your account. Sent in plain text as the first part of X-Bw-Hmac. |
| API secret | Signs the request body. Never send it and never put it in client-side code. |
How a call is built
There is one endpoint for everything. The method is not part of the URL – it goes into the
X-Bw-Method header, the parameters go into the request body as JSON.
| URL | https://www.billware.de/api/v1 |
| Method | POST – for every function, including read ones |
X-Bw-Method |
Name of the function, e.g. order.create |
X-Bw-Hmac |
API-Appid, a colon and the calculated HMAC, e.g. appid:hmac |
Content-Type |
application/json |
The HMAC is a SHA-256 signature of the raw request body, base64 encoded. Sign the exact bytes you send: if you re-encode the payload after signing it, the signature no longer matches. See Authentication for examples in five languages.
Your first call
test.connection takes no parameters and only tells you whether your credentials work.
A good way to check the signature before touching real data.
# Get your API credentials from your billware customer area
API_APPID="your-app-id"
API_SECRET="your-api-secret"
PAYLOAD='[]'
# The HMAC is calculated over the exact request body that is sent
HMAC=$(printf '%s' "$PAYLOAD" | openssl dgst -sha256 -hmac "$API_SECRET" -binary | base64)
curl -X POST "https://www.billware.de/api/v1" \
-H "X-Bw-Hmac: $API_APPID:$HMAC" \
-H "X-Bw-Method: test.connection" \
-H "Content-Type: application/json" \
-d "$PAYLOAD"<?php
// Get your API credentials from your billware customer area
$apiAppId = 'your-app-id';
$apiSecret = 'your-api-secret';
$payload = '{}';
// The HMAC is calculated over the exact request body that is sent
$hmac = base64_encode(hash_hmac('sha256', $payload, $apiSecret, true));
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => 'https://www.billware.de/api/v1',
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'X-Bw-Hmac: '.$apiAppId.':'.$hmac,
'X-Bw-Method: test.connection',
'Content-Type: application/json',
],
]);
$response = curl_exec($curl);
curl_close($curl);
print_r(json_decode($response, true));import crypto from 'node:crypto';
// Get your API credentials from your billware customer area
const apiAppId = 'your-app-id';
const apiSecret = 'your-api-secret';
const payload = JSON.stringify({});
// The HMAC is calculated over the exact request body that is sent
const hmac = crypto.createHmac('sha256', apiSecret).update(payload).digest('base64');
const response = await fetch('https://www.billware.de/api/v1', {
method: 'POST',
headers: {
'X-Bw-Hmac': `${apiAppId}:${hmac}`,
'X-Bw-Method': 'test.connection',
'Content-Type': 'application/json'
},
body: payload
});
console.log(await response.json());import base64
import hashlib
import hmac
import json
import requests
# Get your API credentials from your billware customer area
api_appid = "your-app-id"
api_secret = "your-api-secret"
payload = json.dumps({})
# The HMAC is calculated over the exact request body that is sent
signature = base64.b64encode(
hmac.new(api_secret.encode(), payload.encode(), hashlib.sha256).digest()
).decode()
response = requests.post(
"https://www.billware.de/api/v1",
data=payload,
headers={
"X-Bw-Hmac": f"{api_appid}:{signature}",
"X-Bw-Method": "test.connection",
"Content-Type": "application/json",
},
)
print(response.json())using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
// Get your API credentials from your billware customer area
const string apiAppId = "your-app-id";
const string apiSecret = "your-api-secret";
var payload = JsonSerializer.Serialize(new { });
// The HMAC is calculated over the exact request body that is sent
using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(apiSecret));
var signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(payload)));
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://www.billware.de/api/v1")
{
Content = new StringContent(payload, Encoding.UTF8, "application/json")
};
request.Headers.Add("X-Bw-Hmac", $"{apiAppId}:{signature}");
request.Headers.Add("X-Bw-Method", "test.connection");
var response = await client.SendAsync(request);
Console.WriteLine(await response.Content.ReadAsStringAsync());Response format
Every response is a JSON object with the same three fields. data holds the result and is
null when a method returns nothing.
{
"response": true,
"data": {
"order_ident": "154xy0817679B1kJ"
},
"message": "order created"
}
A request that was understood but could not be carried out – a missing required field, an unknown
identifier – still answers with HTTP 200 and "response": false. Always
evaluate response, not the status code alone.
Some methods add fields next to the three above. order.list, for example, returns the
pagination values on the top level.
Status codes
| Code | Meaning |
|---|---|
200 |
The request was processed. Check response for the outcome. |
401 |
The HMAC does not match, or the API-Appid is unknown. |
402 |
The call limit of your account is used up. |
403 |
The method belongs to an extension that is not active for your account. |
404 |
X-Bw-Method is missing or names a function that does not exist. |
503 |
billware is in maintenance mode. Retry later. |
Call limit
Calls are counted per account over a rolling window of one hour. How many are included depends on
your API package. When the window is used up, further requests answer with
402 and the message "Api call limit reached"
until the oldest calls fall out of the window.
Seeing your own calls
API configuration lists every call of the last hour with the time, the method, the status code, the message billware answered with and the calling IP address. That is usually the fastest way to find out why an integration is not doing what you expect – and it also shows how much of your call limit is left.
Identifiers and formats
| Identifiers | Articles, customers, addresses and orders are addressed by their *_ident string,
for example order_ident. You receive it from the matching create
call and from read.
|
| Date and time | "YYYY-MM-DD HH:MM:SS", e.g.
"2025-07-16 10:00:00" |
| Numbers | Prices and quantities are sent as numbers, not as strings. Decimal separator is the dot. |
| Booleans | Flags such as is_paid use 0 and
1.
|
Where to go next
| Authentication | Signing a request, and the connection test. |
| Articles | Create, read, update and delete articles. |
| Customers | Customers and their delivery addresses. |
| Orders | Orders, payments and invoice numbers. |
| Postman | A ready-made collection with every method. |