API guide

Connect your own tools to Nuvabill

The REST API lets your scripts, accounting software or website read and change clients, services, invoices and tickets. It speaks JSON and is part of Nuvabill 0.4 and newer.

1. API keys

  1. Sign in to your admin area and open Your profile → API keys.
  2. Give the key a name, for example "Accounting sync". Tick Can change data only if the tool needs to create or change things.
  3. Copy the key. It starts with nb_ and is shown only once. Nuvabill keeps only a hash of it.

A key acts as you. It can only do what your role allows, so make a staff member with a small role for each tool. Delete a key on the same page to stop it at once. The API is turned off on the public demo.

2. Making requests

Send the key in the Authorization header of every request, to the address of your Nuvabill followed by /api/v1:

curl https://billing.yourhost.com/api/v1/me \
  -H "Authorization: Bearer nb_your_key" \
  -H "Accept: application/json"
  • Amounts are in cents (the smallest unit of the currency): 2500 is $25.00. Every amount comes with its currency.
  • Lists are paged. Add ?per_page=50&page=2 (up to 100 per page). The answer has data, links and meta.total.
  • Filters: most lists take client_id and status, for example /invoices?status=unpaid.
  • Send request bodies as JSON with Content-Type: application/json.

3. Endpoints

RequestWhat it doesRole permission
GET /meThe staff member and key, and the Nuvabill versionAny
GET /productsProducts with their pricesAny
GET /clientsClients. Filters: email, statusView clients
GET /clients/{id}One client, with wallet balanceView clients
POST /clientsCreate a clientManage clients
GET /servicesServices. Filters: client_id, statusManage services
GET /services/{id}One serviceManage services
POST /services/{id}/suspendSuspend on the server. Optional reasonManage services
POST /services/{id}/unsuspendUnsuspend on the serverManage services
POST /services/{id}/terminateRemove the account from the serverManage services
GET /invoicesInvoices. Filters: client_id, statusView billing
GET /invoices/{id}One invoice with its lines and paymentsView billing
POST /invoicesCreate an invoiceManage billing
POST /invoices/{id}/paymentsRecord a payment, for example a bank transferManage billing
GET /ordersOrders. Filters: client_id, statusManage orders
GET /ticketsTickets, newest reply first. Filters: client_id, statusManage support
GET /tickets/{number}One ticket with every replyManage support
POST /tickets/{number}/repliesReply as the key's staff member. The client gets the usual emailManage support

Read-only keys can use every GET request above. Requests that change data need a key that can change data.

4. Examples

Create a client

curl -X POST https://billing.yourhost.com/api/v1/clients \
  -H "Authorization: Bearer nb_your_key" \
  -H "Content-Type: application/json" \
  -d '{"first_name": "Mer", "last_name": "Las", "email": "[email protected]", "country": "IQ"}'

Other fields: company_name, phone, address_1, city, state, postcode, tax_id and password. Without a password, the client sets one with "Forgot password".

Create an invoice

curl -X POST https://billing.yourhost.com/api/v1/invoices \
  -H "Authorization: Bearer nb_your_key" \
  -H "Content-Type: application/json" \
  -d '{"client_id": 42, "send_email": true, "items": [
        {"description": "Website design", "amount": 25000},
        {"description": "Domain setup", "amount": 1500, "taxed": false}
      ]}'

Tax is added from your tax rules, like invoices made in the admin area. Add "draft": true to keep it hidden from the client, due_at for a due date and notes for a note.

Record a payment

curl -X POST https://billing.yourhost.com/api/v1/invoices/310/payments \
  -H "Authorization: Bearer nb_your_key" \
  -H "Content-Type: application/json" \
  -d '{"amount": 26500, "gateway": "banktransfer", "reference": "BANK-7781"}'

A payment with the same gateway and reference is only recorded once, so it is safe to send again after a timeout. When the invoice is paid, services are set up or unsuspended, like any other payment.

Reply to a ticket

curl -X POST https://billing.yourhost.com/api/v1/tickets/482913/replies \
  -H "Authorization: Bearer nb_your_key" \
  -H "Content-Type: application/json" \
  -d '{"message": "Your site is back online.", "status": "closed"}'

5. Errors and limits

StatusMeaning
401No key, a wrong key, or the staff member is turned off
403The key can only read, or the role does not allow this
404Not found
422Something in the request is not valid. errors lists each field
429Too many requests. Each key can send 120 requests a minute

Every error has a message in plain English. Questions or ideas for new endpoints? Open an issue on GitHub.