Endpoints Reference
All endpoints are under https://onboarding-hub.com/api/v1/ and require Bearer token authentication.
For the interactive API reference with request/response schemas, see the Swagger UI.
Contacts
Manage the people you are onboarding. Contacts can be associated with organisations and enrolled in guides.
Scopes: contacts:read (read), contacts:write (write)
List contacts
GET /api/v1/contacts
Query parameters:
| Parameter | Type | Description |
|---|---|---|
page |
integer | Page number (default: 1) |
email |
string | Filter by exact email |
organisation_id |
uuid | Filter by organisation |
curl:
curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
"https://onboarding-hub.com/api/v1/contacts?page=1"
Response (200):
{
"data": [
{
"id": "01234567-89ab-cdef-0123-456789abcdef",
"email": "[email protected]",
"first_name": "Jane",
"last_name": "Doe",
"external_id": "cust_123",
"organisation_id": "fedcba98-7654-3210-fedc-ba9876543210",
"metadata": { "plan": "pro" },
"created_at": "2026-01-15T10:30:00Z",
"updated_at": "2026-01-15T10:30:00Z"
}
]
}
Get a contact
GET /api/v1/contacts/:id
Create a contact
POST /api/v1/contacts
Body:
{
"contact": {
"email": "[email protected]",
"first_name": "Jane",
"last_name": "Doe",
"external_id": "cust_123",
"organisation_id": "fedcba98-7654-3210-fedc-ba9876543210",
"metadata": { "plan": "pro" }
}
}
curl:
curl -X POST -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"contact":{"email":"[email protected]","first_name":"Jane","last_name":"Doe"}}' \
https://onboarding-hub.com/api/v1/contacts
Ruby:
require "net/http"
require "json"
uri = URI("https://onboarding-hub.com/api/v1/contacts")
req = Net::HTTP::Post.new(uri, {
"Authorization" => "Bearer YOUR_ACCESS_TOKEN",
"Content-Type" => "application/json"
})
req.body = {
contact: { email: "[email protected]", first_name: "Jane", last_name: "Doe" }
}.to_json
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
puts JSON.parse(res.body)
Python:
import requests
response = requests.post(
"https://onboarding-hub.com/api/v1/contacts",
headers={"Authorization": "Bearer YOUR_ACCESS_TOKEN"},
json={
"contact": {
"email": "[email protected]",
"first_name": "Jane",
"last_name": "Doe",
}
},
)
print(response.json())
JavaScript:
const response = await fetch("https://onboarding-hub.com/api/v1/contacts", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_ACCESS_TOKEN",
"Content-Type": "application/json",
},
body: JSON.stringify({
contact: {
email: "[email protected]",
first_name: "Jane",
last_name: "Doe",
},
}),
});
const data = await response.json();
Response (201):
{
"data": {
"id": "01234567-89ab-cdef-0123-456789abcdef",
"email": "[email protected]",
"first_name": "Jane",
"last_name": "Doe",
"external_id": null,
"organisation_id": null,
"metadata": {},
"created_at": "2026-02-09T12:00:00Z",
"updated_at": "2026-02-09T12:00:00Z"
}
}
Update a contact
PATCH /api/v1/contacts/:id
Only include the fields you want to change.
Delete a contact
DELETE /api/v1/contacts/:id
Soft-deletes the contact (sets deleted_at). Returns 204 No Content.
Search contacts
GET /api/v1/contacts/search?query=jane
Searches by first name, last name, and email. Designed for Zapier's "Find Contact" action.
Organisations
Group contacts into organisations for easier management and enrollment tracking.
Scopes: organisations:read (read), organisations:write (write)
List organisations
GET /api/v1/organisations
Query parameters:
| Parameter | Type | Description |
|---|---|---|
page |
integer | Page number (default: 1) |
per_page |
integer | Items per page (default: 25, max: 100) |
name |
string | Filter by name (partial, case-insensitive) |
domain |
string | Filter by exact domain |
Get an organisation
GET /api/v1/organisations/:id
Create an organisation
POST /api/v1/organisations
{
"organisation": {
"name": "Acme Corp",
"domain": "acme.com",
"metadata": { "industry": "SaaS" }
}
}
Update an organisation
PATCH /api/v1/organisations/:id
Delete an organisation
DELETE /api/v1/organisations/:id
Permanently deletes the organisation. Returns 204 No Content.
Enrollments
Enrollments represent a contact's assignment to a guide. Track progress, completion, and feedback.
Scopes: enrollments:read (read), enrollments:write (write)
List enrollments
GET /api/v1/enrollments
Query parameters:
| Parameter | Type | Description |
|---|---|---|
page |
integer | Page number (default: 1) |
per_page |
integer | Items per page (default: 25, max: 100) |
contact_id |
uuid | Filter by contact |
guide_id |
uuid | Filter by guide |
organisation_id |
uuid | Filter by organisation (via contact) |
status |
string | Filter by status: invited, in_progress, completed, expired |
Response (200):
{
"data": [
{
"id": "...",
"contact_id": "...",
"guide_id": "...",
"organisation_id": "...",
"status": "in_progress",
"progress_percentage": 66.7,
"access_token": "abc123",
"started_at": "2026-01-15T10:30:00Z",
"completed_at": null,
"expires_at": null,
"metadata": {},
"created_at": "2026-01-15T10:00:00Z",
"updated_at": "2026-01-15T10:30:00Z"
}
],
"meta": {
"page": 1,
"per_page": 25,
"total": 42,
"total_pages": 2
}
}
Get an enrollment
GET /api/v1/enrollments/:id
The detail view includes additional fields: progress, completed_step_ids, total_steps, days_to_completion, ces_score, nested contact and guide objects.
Create an enrollment
POST /api/v1/enrollments
{
"enrollment": {
"contact_id": "01234567-...",
"guide_id": "fedcba98-...",
"metadata": { "source": "api" }
}
}
The access_token is auto-generated by the model.
Update an enrollment
PATCH /api/v1/enrollments/:id
{
"enrollment": {
"status": "completed",
"metadata": { "completed_via": "api" }
}
}
Delete an enrollment
DELETE /api/v1/enrollments/:id
Permanently deletes the enrollment. Returns 204 No Content.
Guides
Read-only access to published guides and their structure (sections and steps).
Scopes: guides:read
List published guides
GET /api/v1/guides
Returns only published guides. Draft and archived guides are not included.
Query parameters:
| Parameter | Type | Description |
|---|---|---|
page |
integer | Page number (default: 1) |
per_page |
integer | Items per page (default: 25, max: 100) |
Get a guide
GET /api/v1/guides/:id
Returns the full guide structure with nested sections and steps:
{
"data": {
"id": "...",
"title": "Getting Started Guide",
"description": "Welcome to our platform",
"sections_count": 3,
"steps_count": 12,
"published_at": "2026-01-10T09:00:00Z",
"created_at": "2026-01-05T14:00:00Z",
"updated_at": "2026-01-10T09:00:00Z",
"sections": [
{
"id": "...",
"title": "Welcome",
"position": 0,
"steps": [
{
"id": "...",
"title": "Introduction",
"position": 0,
"type": "simple_content"
}
]
}
]
}
}
Webhook Endpoints
Manage outbound webhook subscriptions. See Webhooks for event types and payload formats.
Scopes: webhooks:manage
List webhook endpoints
GET /api/v1/webhook_endpoints
Get a webhook endpoint
GET /api/v1/webhook_endpoints/:id
Includes the 10 most recent delivery records.
Create a webhook endpoint
POST /api/v1/webhook_endpoints
{
"webhook_endpoint": {
"url": "https://yourapp.com/webhooks/onboardinghub",
"events": ["enrollment.created", "enrollment.completed"],
"description": "Production webhook"
}
}
The signing secret is included in the response only on create. Store it securely.
Update a webhook endpoint
PATCH /api/v1/webhook_endpoints/:id
Delete a webhook endpoint
DELETE /api/v1/webhook_endpoints/:id
Send test ping
POST /api/v1/webhook_endpoints/:id/test
Sends a test ping event to the endpoint and returns the result synchronously.
Next steps
- Error handling -- understand error responses
- Rate limiting -- rate limit details and headers
- Webhooks -- event types and payload formats