Help center
https://api.certo.bio/v1openapi.json
Create a position
POST
/v1/positionsscope hiring:writeA position: the terms an invitation to it starts from (what the candidate shares and must have ready). Owners, admins and recruiters.
As an MCP tool: create_position
Request body
| Name | Type | Required | Description |
|---|---|---|---|
| title | string | Yes | The position's title, 1 to 120 characters. |
| location | string or null | Where the work is, at most 120 characters. | |
| description | string or null | What the work is, at most 1000 characters. | |
| scope_types | array of one of employment, education, certification, role, language, right_to_work or null | What the candidate is asked to share: record types, or null (or every one) for all of them. | |
| include_contact | boolean | Invitations to it ask for the candidate's contact details too. | |
| include_birth_date | boolean | Invitations to it ask for the date of birth too (with birth_date_reason). | |
| birth_date_reason | string or null | Why the date of birth is needed, 3 to 280 characters; required with include_birth_date. The candidate reads it. | |
| requirements | object or null | What the candidate must have ready, docs/request-requirements.md: {"v": 1, "work_years", "education_min_level", "certifications", "right_to_work", "contact"}; null for the defaults. | |
| ats_job_id | uuid or null | The ATS job (the organisation's, from the ATS integration) that feeds this position, or null. | |
| custom_data | object or null | Your own data on the position: any JSON object (an id from your ATS or HR system, a requisition number), at most 4096 bytes. certo stores it and answers it back on the reads and in your webhook events; it never reads it, and the candidate never sees it. A change replaces it whole; null clears it. |
Response fields
- position
- object. The position.
- position.id
- uuid. The position's id.
- position.title
- string. Its title.
- position.location
- string or null. Where the work is.
- position.status
- one of open, closed. open, or closed (kept with its candidates; it only leaves the invite picker).
- position.counts
- object. How far the position is.
- position.counts.invited
- integer. Invitations and asks under the position.
- position.counts.accepted
- integer. Of those, accepted or approved.
- position.counts.ready
- integer. Candidates under it whose checklist is complete.
- position.custom_data
- object or null. Your own data on the position, as you sent it; null for none.
- position.created_at
- string. When it was made, ISO 8601.
- scope_types
- array of string. What invitations to it ask to share; empty for everything.
- include_contact
- boolean. Invitations ask for contact details.
- include_birth_date
- boolean. Invitations ask for the date of birth.
- requirements
- object or null. What the candidate must have ready; null for the defaults.
Errors
- 400 position.invalid
- 400 position.ats_job_invalid
- 409 position.ats_job_taken
- 400 invite.birth_date_reason_required
- 400 request.unknown_field
- 409 api.idempotency_mismatch
- 409 api.idempotency_in_progress
- 400 api.credential_in_url
- 401 api.key_invalid
- 401 api.key_expired
- 401 api.key_revoked
- 401 api.key_suspended
- 403 api.scope_missing
- 429 api.rate_limited