Zapier
CursusOffice for Zapier: documentation
This page describes how CursusOffice connects to Zapier: how to authenticate, what each trigger, action and search does, what the errors look like and how to test everything. It also lists the public API endpoints the app uses.
Overview
CursusOffice is a business management suite for agencies, professionals and small businesses: customers, quotes, invoices, payments and projects in one place, with electronic invoicing for the countries it supports. Every customer of CursusOffice has their own workspace with its own address, for example yourcompany.cursusoffice.com.
The CursusOffice integration lets a workspace exchange data with the other apps connected to Zapier. It uses the public CursusOffice REST API (JSON, over HTTPS only) and outgoing webhooks, which are the same ones documented on this page.
Status: the CursusOffice app for Zapier is built and tested and is being prepared for the Zapier App Directory. Until it is listed there, you can connect CursusOffice with the "Webhooks by Zapier" app, as described on the integration page.
Authentication
The app uses API key authentication. When you connect your account, Zapier asks for two values:
Your CursusOffice address: the address of your workspace, withouthttps://, for exampleyourcompany.cursusoffice.com.API token: a token that starts withco_.
- In CursusOffice, open Management, then API and webhooks, then the API tokens tab.
- Create a token and choose only the permissions you need (see the table below). The token is shown once: copy it right away.
- In Zapier, connect your CursusOffice account and paste the address and the token.
Every request is sent to https://<your address>/api/v1 with the header Authorization: Bearer <token>. HTTP is not accepted in production. A token belongs to one workspace only, can have an expiry date and can be revoked at any time; the revocation applies from the next request. The connection test is GET /api/v1/, which answers 200 when the address and the token are valid.
| Permission | What it allows | Used by |
|---|---|---|
| customers:read | Read customers | New Customer (sample data), Find Customer, customer drop-down |
| customers:write | Create and update customers | Create Customer |
| products:read | Read products and VAT rates | New Product (sample data), VAT rate drop-down |
| quotes:read | Read quotes | Quote Accepted (sample data) |
| quotes:write | Create quote drafts | Create Quote Draft |
| invoices:read | Read invoices | Invoice Issued (sample data), Find Invoice |
| invoices:write | Create invoice drafts | Create Invoice Draft |
| payments:read | Read payments | New Payment (sample data) |
| projects:read | Read projects | New Project (sample data) |
| webhooks:write | Subscribe and unsubscribe webhooks | All instant triggers |
Triggers
All triggers are instant (REST hooks). When a Zap is turned on, Zapier subscribes its own address with POST /api/v1/webhooks; when the Zap is turned off, it removes the subscription with DELETE /api/v1/webhooks/{id}. A token can only see and delete the subscriptions it created.
Events are queued when the action happens in CursusOffice and delivered by a background job that runs every minute, so a trigger can take up to about one minute to reach Zapier. Failed deliveries are retried after 1 minute, 5 minutes, 30 minutes, 2 hours and 12 hours. Each event has a unique id (id in the envelope), so duplicates can be ignored.
The data of a trigger is the object itself (the same shape the API returns). Amounts are decimal strings, dates and times are ISO 8601 with time zone, and ids are integers.
| Trigger | Fires when | Event | Sample data from |
|---|---|---|---|
| New Customer | A customer is created | customer.created | GET /customers |
| Invoice Issued | An invoice is issued | invoice.issued | GET /invoices |
| Quote Accepted | A customer accepts a quote | quote.accepted | GET /quotes?status=accepted |
| New Payment | A payment is recorded against an invoice (it only records an incoming payment: no money is moved by the app) | payment.received | GET /payments |
| New Project | A project is created | project.created | GET /projects |
| New Product | A product or service is created | product.created | GET /products |
| New Website Request | A request arrives from a website form connected to CursusOffice | site_request.received | Static sample |
Actions
Actions create data in CursusOffice. Quotes and invoices are always created as drafts: numbering, issuing and sending a document stay a deliberate step of a person inside CursusOffice (invoices have tax effects). Totals and VAT are always calculated by CursusOffice, never by Zapier.
Lines as text lets a Zap build the lines from another app without line-item mapping. Write one line per row: description | quantity | unit price (net) | VAT rate | unit (optional). The VAT rate can be a percentage such as 22, the code of a VAT rate as listed by GET /vat-rates, or # followed by the id of the VAT rate. Example:
Website project | 1 | 1200 | 22
Monthly maintenance | 3 | 80 | 22 | month The Customer and VAT Rate drop-downs are filled from the workspace (GET /customers and GET /vat-rates).
| Action | Endpoint | Fields |
|---|---|---|
| Create Customer | POST /customers | Type (company or person), Company Name, First Name, Last Name, Email, Phone, VAT Number, Tax Code, Country, Address, ZIP, City, Province, Notes |
| Create Invoice Draft | POST /invoices | Customer (required), Issue Date, Due Date (required), Reference, Notes, Lines (Description, Quantity, Unit, Unit Price net, VAT Rate) or Lines as text |
| Create Quote Draft | POST /quotes | Customer (required), Issue Date, Valid Until, Reference, Notes, Lines (as above) or Lines as text |
Searches
| Search | Endpoint | Finds |
|---|---|---|
| Find Customer | GET /customers?q=... | Customers whose name, email, VAT number or code contains the text (up to 5 results) |
| Find Invoice | GET /invoices?q=... | Invoices whose number, reference or customer name contains the text (up to 5 results) |
Errors and limits
Errors are returned as JSON with a stable code (in English), a readable message and, when relevant, the name of the field. The message is written in the language of the workspace (Italian for an Italian workspace); the messages added by the app itself are in English. The app shows the message and the field in the Zap history:
Creating records accepts an Idempotency-Key header: the same key with the same body within 24 hours returns the first answer instead of creating a second document.
{ "error": { "code": "bad_parameter", "message": "Data non valida: usa il formato AAAA-MM-GG o AAAA-MM-GGTHH:MM:SS.", "field": "updated_since" } } | HTTP status | Meaning |
|---|---|
| 400 | Invalid JSON or parameter |
| 401 | Missing, wrong, revoked or expired token |
| 403 | The token does not have the needed permission, or the workspace is suspended or closing |
| 404 | The record does not exist |
| 409 | Request already in progress, or limit reached |
| 422 | Validation error (the field is named in the error) |
| 429 | More than 120 requests per minute for the token: wait for the number of seconds in the Retry-After header |
How to test the app
A workspace for testing, with an administrator account, is provided in the Zapier submission form; its credentials are never published here. To see everything working:
- Connect the account with the workspace address and an API token that has all the permissions listed above.
- New Customer: create a customer in the workspace. New Product: create a product or service. New Project: create a project. New Website Request: send a test request to one of the workspace website forms.
- Invoice Issued: create an invoice for a customer and issue it. New Payment: record a payment on that issued invoice. Quote Accepted: send a quote to a customer and accept it from the public link in the email.
- Actions: Create Customer, Create Invoice Draft and Create Quote Draft create records you can see in the Customers, Invoices and Quotes pages. The invoice and quote stay drafts, without a number.
- Searches: Find Customer and Find Invoice return the records created above.
Triggers are delivered by a background job that runs every minute: if "Test trigger" finds nothing right after the event, wait a minute and test again.
API endpoints used by the app
Base address: https://<your address>/api/v1. All responses are JSON. Lists are paginated with page and per_page (maximum 100) and accept updated_since.
| Method and path | Permission | Notes |
|---|---|---|
| GET / | none | Connection test and information |
| GET /customers, GET /customers/{id} | customers:read | Filters q, state, country, updated_since |
| POST /customers, PATCH /customers/{id} | customers:write | Same checks as the interface (VAT number, tax code, country) |
| GET /products, GET /products/{id}, GET /vat-rates | products:read | The VAT rate id is used in document lines |
| GET /quotes, GET /quotes/{id} | quotes:read | Filters q, status, customer_id, updated_since |
| POST /quotes | quotes:write | Creates a draft |
| GET /invoices, GET /invoices/{id} | invoices:read | Includes credit notes (type) |
| POST /invoices | invoices:write | Creates a draft |
| GET /payments, GET /payments/{id} | payments:read | Filters invoice_id, paid_from, paid_to |
| GET /projects, GET /projects/{id} | projects:read | Filters status, customer_id, q |
| POST /webhooks, DELETE /webhooks/{id} | webhooks:write | Subscribe and unsubscribe (events listed above) |
Contact us
Questions about the integration? Write to us from the contact page. Contact us
