Get started
Quickstart
From nothing to a working integration: create a scoped key, read your contacts, create a deal, and get told when it moves. About five minutes.
- A Nextora workspace. Its address is where you sign in, for example
https://acme.nextora.co. Type yours into the Workspace field in the sidebar — every sample on these pages follows. - Access to Settings → Developers in the app, which workspace admins and roles with settings access have.
- cURL, Node.js 18 or later, or Python 3 with
requests. The JavaScript samples usefetchand top-levelawait: run them as an ES module (.mjs).
In Nextora, open Settings → Developers → API keys and choose Create key. Name it after the integration, and give it only what it needs — for this guide, Contacts (read), Deals (write) and Webhooks (write).
Copy the key when it appears: it starts with
sk_live_and is shown only once. Keep it in an environment variable, never in code:export NEXTORA_API_KEY="sk_live_…"List two contacts. The key goes in the
Authorizationheader as a bearer token:List contactscurl -G https://acme.nextora.co/api/v1/contacts \ -H "Authorization: Bearer $NEXTORA_API_KEY" \ -d limit=2Response200 OK{ "data": [ { "id": "3f1c9a7e-2b4d-4c8e-9f60-1a2b3c4d5e6f", "first_name": "Ada", "last_name": "Brennan", "full_name": "Ada Brennan", "email": "[email protected]", "phone": "+44 20 7946 0958", "position": "Head of Operations", "company_id": "2b7e4c9a-5d1f-4a8e-9b3c-7f0a1d2e4c56", "company": { "id": "2b7e4c9a-5d1f-4a8e-9b3c-7f0a1d2e4c56", "name": "Northwind Analytics" }, "owner_id": "0c4f8e2a-7b3d-4a1f-9e6c-5d2b8a1f3e47", "tags": [ "enterprise", "renewal-2027" ], "source": "website", "custom_fields": { "region": "emea" }, "last_activity_at": "2026-10-08T14:12:09Z", "created_at": "2026-09-14T09:30:00Z", "updated_at": "2026-10-08T14:12:09Z" } ], "meta": { "limit": 2, "has_more": true, "next_cursor": "eyJpZCI6IjNmMWM5YTdlIiwiY3JlYXRlZF9hdCI6IjIwMjYtMDktMTRUMDk6MzA6MDBaIn0" } }Every list looks like this: records in
data, paging inmeta. Passmeta.next_cursorascursorfor the next page — see Pagination. A401means the key is missing or wrong; the error body says which.Create a deal for the contact you just read. The
Idempotency-Keyheader makes the request safe to retry: send it again with the same key and you get the same deal back instead of a second one.Create a dealcurl -X POST https://acme.nextora.co/api/v1/deals \ -H "Authorization: Bearer $NEXTORA_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: 0f1e2d3c-4b5a-4987-8a6b-5c4d3e2f1a0b" \ -d '{ "title": "Northwind Analytics — annual plan", "value": 24000, "currency": "EUR", "contact_id": "3f1c9a7e-2b4d-4c8e-9f60-1a2b3c4d5e6f", "company_id": "2b7e4c9a-5d1f-4a8e-9b3c-7f0a1d2e4c56", "expected_close_date": "2026-11-27" }'Response201 Created{ "data": { "id": "8f2d6c1a-4b7e-4f0a-9c3d-2e1b5a6f7c80", "title": "Northwind Analytics — annual plan", "value": 24000, "currency": "EUR", "status": "in_progress", "pipeline": { "id": "9d4b2f7a-3c8e-4b1d-a6f2-5e7c9b0d1a34", "name": "New business" }, "stage": { "id": "4e8a1c6d-9b2f-4d7a-8c3e-1f5b7a9d0c62", "name": "Qualification", "type": "open" }, "pipeline_id": "9d4b2f7a-3c8e-4b1d-a6f2-5e7c9b0d1a34", "stage_id": "4e8a1c6d-9b2f-4d7a-8c3e-1f5b7a9d0c62", "probability": 20, "expected_close_date": "2026-11-27", "closed_at": null, "forecast_category": null, "loss_reason": null, "competitor": null, "contact_id": "3f1c9a7e-2b4d-4c8e-9f60-1a2b3c4d5e6f", "company_id": "2b7e4c9a-5d1f-4a8e-9b3c-7f0a1d2e4c56", "owner_id": "0c4f8e2a-7b3d-4a1f-9e6c-5d2b8a1f3e47", "custom_fields": {}, "created_at": "2026-10-01T10:12:00Z", "updated_at": "2026-10-01T10:12:00Z" } }Without
pipeline_idandstage_id, the deal lands in the first stage of the default pipeline. Open the pipeline in Nextora and it is there. Deals need the Sales hub in the plan; without it this request returns403 hub_not_in_plan.Subscribe an HTTPS endpoint of yours to
deal.stage_changed. The response carries the signing secret — the only time you see it.Create a webhook subscriptioncurl -X POST https://acme.nextora.co/api/v1/webhooks \ -H "Authorization: Bearer $NEXTORA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Quickstart", "url": "https://hooks.example.com/nextora", "events": [ "deal.stage_changed" ] }'Response201 Created{ "data": { "id": "f3a5c7e9-2b4d-4f6a-8c1e-5d7f9b1a3c60", "name": "Quickstart", "url": "https://hooks.example.com/nextora", "events": [ "deal.stage_changed" ], "is_active": true, "paused_at": null, "paused_reason": null, "failing_since": null, "last_success_at": null, "last_failure_at": null, "created_at": "2026-10-10T09:00:00Z", "updated_at": "2026-10-10T09:00:00Z", "secret": "whsec_9f3b7c1e5a2d8f4b6c0e3a7d1f5b9c2e8a4d6f0b3c7e1a5d" } }Now drag the deal to another stage in the app. Within seconds your endpoint receives a signed
POSTwith the deal and its previous stage. Verify the signature before you trust it, and answer2xxwithin 10 seconds.
Every endpoint follows the same rules, so one small client covers the whole API.
| Rule | |
|---|---|
| Base URL | https://acme.nextora.co/api/v1. On a custom domain, https://<your domain>/api/v1. HTTPS only. |
| Format | JSON in and out, UTF-8. Send Content-Type: application/json with a body. |
| Names | snake_case everywhere: expected_close_date, custom_fields. |
| IDs | UUID strings. |
| Time | Timestamps in ISO 8601, UTC: 2026-10-10T09:15:02Z. Dates as YYYY-MM-DD. |
| Responses | One record in data; lists in data with paging in meta. Errors in error — see Errors. |
| Updates | PATCH and PUT both change only the fields you send. Unknown fields in a body are ignored. |
| Deletes | Move records to Trash; POST …/{id}/restore brings them back. |
| Browsers | No CORS: call the API from your server, and never ship a key to a browser or an app. |