Public API v1
A REST API for roles, applications, interviews, scorecards, offers and webhooks. It is in beta: these paths and names are fixed, and anything we add will not break them.
Status
Public API v1
In betaThe endpoints below.
API keys with scopes
In betaMade by a workspace owner, each with its own scopes.
OAuth access tokens
In betaFor partner apps, acting as the person who signed in.
OpenAPI 3.1 specification
In betaAt /openapi.json under the base URL.
Available: live in production today. In beta: deployed and usable today; it may still change. Coming soon: not usable yet.
Basics
- Base URL: https://api.octrahire.ai/api/v1/public
- JSON in and out. Times are ISO 8601 in UTC
- Lists take ?limit= (default 25, up to 100) and ?cursor=, and return {"data": [...], "next_cursor": ...}
- Writes accept an Idempotency-Key header; the first response is replayed for 24 hours
- Rate limits are per credential. Over the limit you get 429 with Retry-After
- OpenAPI 3.1 specification: https://api.octrahire.ai/api/v1/public/openapi.json
Authentication
Send a credential as a bearer token. API keys start with ohk_ and OAuth access tokens with oat_. An API key can also go in an X-Api-Key header.
curl https://api.octrahire.ai/api/v1/public/me \
-H "Authorization: Bearer ohk_your_key"/me returns the workspace, the seat the credential acts as, and its scopes.
Scopes
A key or grant has only the scopes chosen for it, and never more than the seat that made it.
| Scope | Allows |
|---|---|
| roles:read | See your roles and their pipelines |
| roles:write | Create and edit roles |
| candidates:read | See candidates and applications |
| applications:write | Add candidates and move them between stages |
| interviews:read | See AI interview results, reports and transcripts |
| interviews:write | Invite candidates to interviews and schedule them |
| scorecards:read | See scorecards and notes |
| scorecards:write | Submit scorecards and add notes |
| offers:read | See offers |
| offers:write | Draft offers and send them for approval |
| approvals:write | Approve or decline requisitions and offers (owner only) |
| ask | Ask questions across interviews |
| reports:read | See hiring and Emiratisation reports |
| webhooks:manage | Manage webhook endpoints (owner only) |
Endpoints
| Endpoint | What it does | Scope |
|---|---|---|
| GET /me | The workspace, seat and scopes | any |
| GET /roles | List roles; ?status=open, closed or draft | roles:read |
| GET /roles/{role_id} | One role | roles:read |
| POST /roles | Create a role: title, description, location, language, interview preset | roles:write |
| PATCH /roles/{role_id} | Edit a role | roles:write |
| POST /roles/{role_id}/open | Open a role (also /close) | roles:write |
| GET /roles/{role_id}/pipeline | Counts per stage | roles:read |
| GET /applications | List applications; ?role_id=, ?stage=, ?updated_since= | candidates:read |
| GET /applications/{id} | One application | candidates:read |
| POST /applications | Add a candidate to a role | applications:write |
| POST /applications/{id}/move | Move to a stage, with a reason | applications:write |
| POST /applications/{id}/reject | Reject, with a reason category and note | applications:write |
| POST /applications/{id}/interview-invites | Invite to an AI interview by email or WhatsApp | interviews:write |
| GET /applications/{id}/interview | Report summary, scores and evidence | interviews:read |
| GET /applications/{id}/transcript | The interview transcript | interviews:read |
| POST /applications/{id}/schedule | Schedule a human interview | interviews:write |
| GET /applications/{id}/scorecards | Scorecards | scorecards:read |
| POST /applications/{id}/scorecards | Submit a scorecard as your seat | scorecards:write |
| GET /applications/{id}/notes | Notes | scorecards:read |
| POST /applications/{id}/notes | Add a note | scorecards:write |
| GET /offers | List offers; ?application_id= | offers:read |
| GET /offers/{offer_id} | One offer | offers:read |
| POST /offers | Draft an offer | offers:write |
| POST /offers/{offer_id}/submit | Send a draft for approval | offers:write |
| POST /offers/{offer_id}/send | Send an approved offer to the candidate | offers:write |
| GET /approvals | Approvals waiting for your seat | approvals:write |
| POST /approvals/{approval_id} | Approve or decline | approvals:write |
| GET /webhooks | List webhooks | webhooks:manage |
| POST /webhooks | Add a webhook; the secret is shown once | webhooks:manage |
| DELETE /webhooks/{webhook_id} | Remove a webhook | webhooks:manage |
| POST /webhooks/{webhook_id}/rotate-secret | Rotate a webhook's secret | webhooks:manage |
| GET /events | The event catalogue | any |
Add a candidate
curl -X POST https://api.octrahire.ai/api/v1/public/applications \
-H "Authorization: Bearer ohk_your_key" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 6f1c2a90-applicant-4471" \
-d '{"role_id": "rol_123", "source": "careers-site",
"candidate": {"name": "Mariam Al Hashimi", "email": "mariam@example.com"}}'Errors
Every error has the same shape, with the HTTP status:
{"error": {"code": "insufficient_scope", "message": "This key needs applications:write"}}Codes: unauthorized, insufficient_scope, forbidden, not_found, validation_error, conflict, rate_limited, idempotency_conflict.
Blind review
When a role hides candidate identity, name, email, phone and photo come back as null and anonymous_label is set, for every credential, including the owner's.
Read next
See Octrahire with your own roles
A 30-minute walkthrough with your jobs or your programmes.
