Connect Emnaro to your other systems
A simple JSON API and signed webhooks for contacts, deals, invoices, tasks and support tickets.
Getting started
- As a workspace owner or admin, open Workspace settings, then API keys and webhooks.
- Create a key and tick only the permissions it needs. It is shown once, so save it somewhere safe.
- Send the key as a Bearer token with each request.
curl https://my.emnaro.com/api/v1/contacts?per_page=10 \
-H "Authorization: Bearer emn_your_key_here"Amounts are whole minor units with their currency, so 1250 in USD means 12.50. Lists return data and meta with page, per_page, total and last_page. You can make 120 requests a minute with each key. Invoices are read-only for now.
Endpoints
| Request | Permission | What it does |
|---|---|---|
GET /api/v1/me | Any | Which workspace and permissions this key has |
GET /api/v1/contacts | contacts:read | List contacts. Filter with search, role, status, updated_since |
GET /api/v1/contacts/{id} | contacts:read | One contact |
POST /api/v1/contacts | contacts:write | Add a contact |
PATCH /api/v1/contacts/{id} | contacts:write | Change a contact |
GET /api/v1/deals | deals:read | List deals. Filter with status, contact_id, updated_since |
GET /api/v1/deals/{id} | deals:read | One deal |
POST /api/v1/deals | deals:write | Add a deal |
PATCH /api/v1/deals/{id}/stage | deals:write | Move a deal to another stage, including won or lost |
GET /api/v1/invoices | invoices:read | List invoices and quotes. Filter with type, status, contact_id, updated_since |
GET /api/v1/invoices/{id} | invoices:read | One document with its lines |
GET /api/v1/task-lists | tasks:read | The task lists the key’s owner can see |
GET /api/v1/tasks | tasks:read | List tasks. Filter with list_id, status, open, updated_since |
GET /api/v1/tasks/{id} | tasks:read | One task |
POST /api/v1/tasks | tasks:write | Add a task |
PATCH /api/v1/tasks/{id} | tasks:write | Change a task |
Webhooks
Emnaro sends a POST with a JSON body to your https address. A reply outside the 200 range is retried up to five more times over about 15 hours. A webhook switches off after 20 failures in a row, and you get a notification.
contact.createdA contact is addeddeal.createdA deal is addeddeal.wonA deal is wondeal.lostA deal is lostinvoice.issuedAn invoice is issuedinvoice.paidAn invoice is paid in fulltask.completedA task on a shared team list is finishedticket.createdA support ticket arrives. Only its reference and state are sentticket.resolvedA support ticket is resolved. Only its reference and state are sent
Check that a message really came from Emnaro
Each message has an X-Emnaro-Signature header like t=1700000000,v1=abc123. Join t, a full stop and the raw body, then work out the HMAC-SHA256 of that text using your signing secret. It must equal v1. Reject messages whose t is more than five minutes old.
$expected = hash_hmac('sha256', $t.'.'.$rawBody, $signingSecret);
$valid = hash_equals($expected, $v1) && abs(time() - (int) $t) < 300;The same event can arrive twice if a reply was lost, so use the id in the message to ignore repeats.
