Connect any system to CAM POS
Any accounting system, ERP or spreadsheet tool can read a CAM POS business's books and records. The shop owner makes a key in CAM POS (Configuration → Accounting software → API keys) and gives it to whoever builds the connection. Keys can only read: nothing in CAM POS can be changed with them.
QuickBooks Online, Xero and Sage Business Cloud Accounting can also be linked directly, with no programming: Configuration → Accounting software → Live link. Any other system can import the files CAM POS makes for it (QuickBooks, Xero, Sage, Pastel, Zoho Books, or a plain journal).
- Keys and limits
- Amounts, days, accounts
- Business
- Chart of accounts
- Journal
- Trial balance
- Sales
- Products and stock
- Customers
- Webhooks
- Errors
Keys and limits
Every request carries the key in the Authorization header. Addresses start with https://campos.camtechsolutions.co.zw/api/v1/.
curl https://campos.camtechsolutions.co.zw/api/v1/journal?from=2026-10-01&to=2026-10-31&daily=1 \
-H "Authorization: Bearer cpk_..."
- A key belongs to one business. The owner can remove it at any time; it stops working at once.
- At most 120 requests a minute per key. Answers are JSON unless a CSV
formatis asked for. - Keep keys on a server, never in a web page or a phone app.
- When the business's CAM POS subscription is not active, requests are refused with
403.
Amounts, days and accounts
- Amounts are numbers in the business's currency with two decimals (
12.5is 12.50). Unit prices and costs can have up to six decimals. - Days are Harare days (
Africa/Harare, UTC+2) written2026-10-21. Times are ISO 8601 in UTC. - Every journal entry balances: its debits equal its credits. Each line names the CAM POS account by key (
cash,salesF…) and by the code and name the business set under Chart of accounts, so the codes can match yours.
GET/api/v1/business
Who the key belongs to: name, number, currency, TIN, VAT number and contacts.
GET/api/v1/accounts
The chart of accounts CAM POS books into: key, code, name and type (asset, liability, equity, income, contra-income, expense).
GET/api/v1/journal
The books: every sale, refund, payment on account, stock delivery, supplier payment, expense, cash movement, stock adjustment and cash count, as balanced journal entries.
| Parameter | Meaning |
|---|---|
from, to | First and last day (both included). Leave out for everything. |
daily=1 | One entry per day with the day's totals by account (reference CAMPOS-2026-10-21). Best for posting to a ledger. |
format | json (the default), or a CSV import file: quickbooks, xero, sage, pastel, zoho, camtech (plain journal). |
taxRate | Xero file only: the tax rate name on each line (default Tax Exempt). |
yearStart | Pastel file only: the month the financial year starts (1 to 12), for the period numbers. |
{
"currency": "USD", "from": "2026-10-21", "to": "2026-10-21", "daily": true,
"entries": [{
"number": "CAMPOS-2026-10-21", "day": "2026-10-21", "reference": "CAMPOS-2026-10-21",
"description": "CAM POS takings and records for 2026-10-21 (42 entries)", "kind": "day",
"lines": [
{ "account": "cash", "code": "1000", "name": "Cash on hand", "debit": 512.40, "credit": 0 },
{ "account": "salesF", "code": "4000", "name": "Sales - fiscal", "debit": 0, "credit": 445.57 },
{ "account": "vat", "code": "2200", "name": "VAT output (ZIMRA)", "debit": 0, "credit": 66.83 }
]
}]
}
GET/api/v1/trial-balance
Each account's movement for from to to, as a debit or a credit. format=csv gives a file.
GET/api/v1/sales
Sales and refunds (refunds have kind: "refund" and negative amounts), oldest first, with their lines. Fiscal receipts carry their ZIMRA details.
| Parameter | Meaning |
|---|---|
from, to | Days, as above. |
limit | How many (1 to 1000, default 200). |
after | The next value from the previous page. more: true means there are more. |
GET/api/v1/products
Products with price, cost, barcode, reorder level, crate or pack details, and units on hand for products whose stock is counted.
GET/api/v1/customers
Saved customers: name, phone, email, TIN, VAT number, address, credit limit.
Webhooks
Instead of asking, a system can be told. The owner gives an https:// address under Configuration → Accounting software → Webhook and chooses the events:
sale.created: each new sale or refund, as in/api/v1/sales, as soon as the till has synced it.day.closed: after midnight, each finished day's journal, as in/api/v1/journal?daily=1.
Each one is a POST with a JSON body and these headers:
X-CamPOS-Event: sale.created
X-CamPOS-Timestamp: 1792569600
X-CamPOS-Signature: sha256=<hex HMAC-SHA256 of "<timestamp>.<body>" with your signing secret>
{ "id": "evt_...", "event": "sale.created", "createdAt": "...", "business": { "id": "...", "name": "...", "number": "..." }, "data": { ... } }
Check the signature with the secret shown when the webhook was turned on, and refuse messages older than a few minutes. Answer with any 2xx within 15 seconds. Anything else is tried again after 1, 5 and 30 minutes, then 2, 6, 12 and 24 hours. The same id can arrive twice, so ignore ones you already have.
// Node.js
const expected = "sha256=" + crypto.createHmac("sha256", SECRET).update(req.headers["x-campos-timestamp"] + "." + rawBody).digest("hex");
const ok = crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(req.headers["x-campos-signature"]));
Errors
An error answer has a status code and { "error": "what went wrong, in words" }: 400 wrong parameters, 401 no key or a removed key, 403 subscription not active, 429 too many requests.
Questions: contact CamTech and Financial Solutions through Help in CAM POS.