Outreach
Add a person who has agreed to be contacted, send them a first WhatsApp message, read and answer their replies, and move them to onboarding.
Not yet available
Outreach is switched off for the deployment. While it is off, every endpoint here answers an empty 404. These pages describe the endpoints as built; do not build against them until Onboardly tells you they are on for your account.
Add a prospect#
Add a person who has agreed to be contacted, or refresh their contact details, so you can send them a first message.
Headers
X-Api-Keyonb_live_<key_id>_<secret>required- Your issued Partner API key — see Authentication.
Request fields
phonestringrequired- E.164, for example
+447700900321. Identifies the person within your account. first_namestringrequired- 1 to 100 characters, plain text.
last_namestring or nulloptional- Up to 100 characters.
emailstring or nulloptional- Up to 320 characters. The shape is checked; delivery is not.
external_refstring or nulloptional- Your own id for the person, up to 128 characters.
opt_inobjectrequired- The proof the person agreed to be contacted. All three fields inside it are required. It is stored once and never overwritten by a later call.
opt_in.sourcestringrequired- One of
application_form,candidate_match,partner_attested,candidate_initiated. opt_in.atstringrequired- ISO 8601 date and time with a zone, for example
2026-10-20T09:30:00Z. Not in the future and not older than 24 months. opt_in.evidence_refstringrequired- 1 to 512 characters. An opaque reference to your record of the consent (a form-submission id), never a link.
Status codes
2012xx- Prospect created.
2002xx- The person was already a prospect of yours. Their contact fields were refreshed; the stored opt-in was not changed.
4004xx- The body is too large (over 4096 characters), is not a JSON object, has a key this endpoint does not accept, or a field is refused. Read
code:body_too_large,invalid_json,unknown_field,invalid_phone,invalid_first_name,invalid_last_name,invalid_email,invalid_external_ref,opt_in_required,invalid_opt_in_source,invalid_opt_in_at,opt_in_at_in_futureorinvalid_opt_in_evidence_ref.The request body is too large.The request body must be a JSON object.The request body has a field this endpoint does not accept.phone must be an E.164 number such as +447700900123.first_name is required and must be a short plain name.last_name must be a short plain name.email must be a valid e-mail address.external_ref must be a short plain reference.opt_in is required, with source, at and evidence_ref.opt_in.source is not an accepted value.opt_in.at must be an ISO 8601 date and time, and recent enough to still count as consent.opt_in.at must not be in the future.opt_in.evidence_ref is required and must be a short plain reference, not a link. 4014xx- Missing, malformed, unknown, revoked or expired key. Every authentication failure looks the same — see Authentication.
4034xx- The key’s user has the
viewerteam role, or their account could not be read just then (retry) — or the key was created Read only (code: "key_read_only", refused before anything else). Checked before the body or any id — see Authentication.Your team role doesn't allow this. Ask your team's admin or owner.This API key is read-only. Create a full-access key to make changes. 4044xx- Outreach is switched off for the deployment. The body is EMPTY.
4094xx- Refused.
codeisopted_out(your own account holds a STOP or opt-out for this number) orpromoted(the person has already become a candidate). Neither clears on retry.This person has opted out and cannot be contacted.This person has already moved on to onboarding. 4294xx- Per-key or per-account rate limit exceeded. Retry after the
Retry-Afterheader.Too many requests — please try again shortly. 5035xx- A read or write failed, or the service is not ready. Retry shortly.
Temporarily unavailable. Try again shortly.
Not yet available. Outreach is switched off for the deployment, and while it is off this endpoint answers 404 with an EMPTY body (not the JSON envelope), before the API key is checked. Do not build against it until it is switched on for your account.
The limit is checked before the body is read, so a malformed request still uses one request of your rate budget.
Creating a prospect sends nothing. Send the first message with POST /outreach/prospects/{id}/send.
curl -X POST \ "https://rca-onboardly.com/api/v1/outreach/prospects" \ -H "X-Api-Key: $ONB_KEY" \ -H "Content-Type: application/json" \ -d '{ "phone": "+447700900321", "first_name": "Jordan", "last_name": "Ellis", "email": "jordan.ellis@example.com", "external_ref": "aura-person-1187", "opt_in": { "source": "partner_attested", "at": "2026-10-20T09:30:00Z", "evidence_ref": "aura-consent-55120" }}'{ "phone": "+447700900321", "first_name": "Jordan", "last_name": "Ellis", "email": "jordan.ellis@example.com", "external_ref": "aura-person-1187", "opt_in": { "source": "partner_attested", "at": "2026-10-20T09:30:00Z", "evidence_ref": "aura-consent-55120" }}{ "data": { "id": "7c3e9a14-5d2b-4f68-8a1e-3b9d6c2f4e85", "phone": "+447700900321", "first_name": "Jordan", "last_name": "Ellis", "email": "jordan.ellis@example.com", "external_ref": "aura-person-1187", "opt_in_source": "partner_attested", "opt_in_at": "2026-10-20T09:30:00.000Z", "opted_out_at": null, "opted_out_reason": null, "promoted_at": null, "revision": 1, "created_at": "2026-10-27T10:00:00.000Z", "updated_at": "2026-10-27T10:00:00.000Z" }, "error": null}{ "data": { "id": "7c3e9a14-5d2b-4f68-8a1e-3b9d6c2f4e85", "phone": "+447700900321", "first_name": "Jordan", "last_name": "Ellis", "email": "jordan.ellis@example.com", "external_ref": "aura-person-1187", "opt_in_source": "partner_attested", "opt_in_at": "2026-10-20T09:30:00.000Z", "opted_out_at": null, "opted_out_reason": null, "promoted_at": null, "revision": 1, "created_at": "2026-10-27T10:00:00.000Z", "updated_at": "2026-10-27T10:00:00.000Z" }, "error": null}Read one outreach prospect of yours, including whether they have opted out or become a candidate.
Headers
X-Api-Keyonb_live_<key_id>_<secret>required- Your issued Partner API key — see Authentication.
Status codes
2002xx- The prospect. The opt-in evidence reference and the candidate it became are not returned.
4014xx- Missing, malformed, unknown, revoked or expired key. Every authentication failure looks the same — see Authentication.
4044xx- The outreach switch is off (an EMPTY body), or the prospect id is unknown, belongs to another account, or is not a valid id. The last three are one identical response, never a 403.
Not found 4294xx- Per-key or per-account rate limit exceeded. Retry after the
Retry-Afterheader.Too many requests — please try again shortly. 5035xx- A read or write failed, or the service is not ready. Retry shortly.
Temporarily unavailable. Try again shortly.
Not yet available. Outreach is switched off for the deployment, and while it is off this endpoint answers 404 with an EMPTY body (not the JSON envelope), before the API key is checked. Do not build against it until it is switched on for your account.
curl \ "https://rca-onboardly.com/api/v1/outreach/prospects/<candidate id>" \ -H "X-Api-Key: $ONB_KEY"{ "data": { "id": "7c3e9a14-5d2b-4f68-8a1e-3b9d6c2f4e85", "phone": "+447700900321", "first_name": "Jordan", "last_name": "Ellis", "email": "jordan.ellis@example.com", "external_ref": "aura-person-1187", "opt_in_source": "partner_attested", "opt_in_at": "2026-10-20T09:30:00.000Z", "opted_out_at": null, "opted_out_reason": null, "promoted_at": null, "revision": 1, "created_at": "2026-10-27T10:00:00.000Z", "updated_at": "2026-10-27T10:00:00.000Z" }, "error": null}Send the first message#
Send the approved first-contact WhatsApp message to an opted-in prospect.
Headers
X-Api-Keyonb_live_<key_id>_<secret>required- Your issued Partner API key — see Authentication.
Idempotency-Key<your own send id>required- Required, 1–255 characters. Use a new key for each message you want sent. Repeating a key after a delivered message returns that delivery; repeating it for a different request is a 409
idempotency_key_conflict.
Request fields
consultant_namestringrequired- The name the message is sent from. Plain text, up to 60 characters, no links.
role_titlestringrequired- The role the message mentions. Plain text, up to 60 characters, no links.
Status codes
2002xxdata.statusissent.message_idis our id for the message, ornullif it cannot be found. Repeating the same Idempotency-Key after a delivery returns the same result.2022xxdata.statusisheld. Nothing was sent. Retry later with a NEW Idempotency-Key.4004xx- Read
code:idempotency_key_required,body_too_large,invalid_json,unknown_field,invalid_consultant_name,invalid_role_title(not a string), orinvalid_variables(a value is empty, too long, or not acceptable in a first message).An Idempotency-Key header is required (max 255 characters).The request body is too large.The request body must be a JSON object.The request body has a field this endpoint does not accept.consultant_name is required and must be a short plain name.role_title is required and must be a short plain job title.consultant_name or role_title is not acceptable in a first message. 4014xx- Missing, malformed, unknown, revoked or expired key. Every authentication failure looks the same — see Authentication.
4034xx- The key’s user has the
viewerteam role, or their account could not be read just then (retry) — or the key was created Read only (code: "key_read_only", refused before anything else). Checked before the body or any id — see Authentication.Your team role doesn't allow this. Ask your team's admin or owner.This API key is read-only. Create a full-access key to make changes. 4024xx- Your plan has ended (
code: "no_subscription") or this month’s messages are used up (code: "over_message_quota"). Nothing was sent or written. Choose or upgrade a plan, or wait until the 1st. Replies inside an open chat are never refused for the message limit. 5035xx- We could not check your plan just now (
code: "billing_unavailable"). Nothing was sent; retry shortly. 4044xx- The outreach switch is off (an EMPTY body), or the prospect id is unknown, belongs to another account, or is not a valid id. The last three are one identical response, never a 403.
Not found 4094xx- Not sent. Read
code:not_sendable(this prospect cannot be messaged right now; one response for several causes, which are deliberately not told apart),opted_out,promoted,opt_in_missing,quiet_hours(try again later),undeliverable(the number cannot receive WhatsApp) oridempotency_key_conflict.This prospect can't be messaged right now.This person has opted out and cannot be contacted.This person has already moved on to onboarding.This prospect has no opt-in record.Outside your sending hours. Try again later.This number can't receive WhatsApp messages.This Idempotency-Key was already used for a different request. 4294xx- A rate limit (retry after the
Retry-Afterheader), or a daily cap:recruiter_daily_cap(your own account’s) orplatform_cap(the shared limit). Try again later.Too many requests — please try again shortly.Your account has reached its daily first-message limit. Try again later.The daily sending limit has been reached. Try again later. 5035xx- The first-contact message is not available (
template_unavailable), or a read or write failed (unavailable). Retry shortly.The first-contact message is not available right now.Temporarily unavailable. Try again shortly.
Not yet available. Outreach is switched off for the deployment, and while it is off this endpoint answers 404 with an EMPTY body (not the JSON envelope), before the API key is checked. Do not build against it until it is switched on for your account.
Your account may send at most 50 first messages in any 24 hours, inside a shared daily limit across all accounts. The first name comes from the prospect and the agency name from your account.
The send counts against your plan like any other new outbound message: with no plan or no messages left it is a 402 and nothing is sent.
curl -X POST \ "https://rca-onboardly.com/api/v1/outreach/prospects/<candidate id>/send" \ -H "X-Api-Key: $ONB_KEY" \ -H "Idempotency-Key: <your own send id>" \ -H "Content-Type: application/json" \ -d '{ "consultant_name": "Sam Carter", "role_title": "Support Worker"}'{ "consultant_name": "Sam Carter", "role_title": "Support Worker"}{ "data": { "status": "sent", "message_id": "4e1b7a92-3c8d-4f05-9a6e-2d7c1b8f3a59" }, "error": null}{ "data": { "status": "held" }, "error": null}Read and answer replies#
Poll the messages to and from your prospects, newest change first.
Headers
X-Api-Keyonb_live_<key_id>_<secret>required- Your issued Partner API key — see Authentication.
Request fields
limitintegeroptional- 25 if omitted, up to 100. Never clamped — an out-of-range value is a
400. cursorstringoptional- Opaque. Pass back the previous page’s
next_cursorverbatim; omit for the first page. updated_sincestring (ISO-8601)optional- ISO-8601 timestamp with a timezone. Keeps messages whose
updated_atis at or after it. prospect_idstringoptional- Only this prospect’s messages. An id that is not yours returns an empty page.
Status codes
2002xx- A page of messages, newest change first. Keep going until
next_cursorisnull. 4004xx- An out-of-range or malformed query parameter, or a malformed
cursor.prospect_idthat is not a valid id isinvalid_prospect_id.Invalid query parameter: {param}Invalid or expired cursorprospect_id must be a valid prospect id. 4014xx- Missing, malformed, unknown, revoked or expired key. Every authentication failure looks the same — see Authentication.
4294xx- Per-key or per-account rate limit exceeded. Retry after the
Retry-Afterheader.Too many requests — please try again shortly. 5035xx- A read or write failed, or the service is not ready. Retry shortly.
Temporarily unavailable. Try again shortly.
Not yet available. Outreach is switched off for the deployment, and while it is off this endpoint answers 404 with an EMPTY body (not the JSON envelope), before the API key is checked. Do not build against it until it is switched on for your account.
Every page carries watermark: the server’s time minus 60 seconds. Keep the first page’s, follow next_cursor to null, then start the next walk with updated_since set to that watermark and de-duplicate on id plus updated_at. A delivery receipt moves updated_at, so a message can appear again when its delivery_status changes.
external_ref is the id you gave the prospect. The provider message id and our sending number are never returned.
curl \ "https://rca-onboardly.com/api/v1/outreach/messages" \ -H "X-Api-Key: $ONB_KEY"{ "data": { "messages": [ { "id": "4e1b7a92-3c8d-4f05-9a6e-2d7c1b8f3a59", "prospect_id": "9c3f1d2e-6a7b-4c8d-8e9f-0a1b2c3d4e5f", "external_ref": "crm-77", "direction": "inbound", "body": "Yes, I would like to hear more.", "template_key": null, "delivery_status": null, "safety_flag": null, "created_at": "2026-10-28T09:00:00.000000Z", "updated_at": "2026-10-28T09:00:00.000000Z" } ], "next_cursor": null, "watermark": "2026-10-28T09:59:00.000Z" }, "error": null}Move a prospect to onboarding#
Turn a prospect into a normal Onboardly candidate (consent, documents, checks) without re-entering their details.
Headers
X-Api-Keyonb_live_<key_id>_<secret>required- Your issued Partner API key — see Authentication.
Idempotency-Key<your own send id>required- Required, 1–255 characters. Use a new key for each message you want sent. Repeating a key after a delivered message returns that delivery; repeating it for a different request is a 409
idempotency_key_conflict.
Request fields
documentsstring[]optional- The documents to collect, exactly as on Create a candidate.
qualificationsobject[]optional- Qualification checks to record, exactly as on Create a candidate.
application_form_sectionsstring[]optional- Which parts of the application form are shown, exactly as on Create a candidate.
startbooleanoptional- Defaults to
true: Onboardly sends the first WhatsApp message to the new candidate. Sendfalseto create the candidate and start later with Start a candidate.
Status codes
2012xx- The candidate was created from the prospect.
startedistruewhen the first WhatsApp message went out. Repeating the same Idempotency-Key returns the same result withreplayed: true. 4004xx- Read
code:idempotency_key_required,body_too_large,invalid_json,unknown_fieldorinvalid_promote_request. Name, number and e-mail cannot be sent: they come from the prospect.An Idempotency-Key header is required (max 255 characters).The request body is too large.The request body must be a JSON object.The request body has a field this endpoint does not accept.The promotion request is not acceptable: check start, documents, qualifications and application_form_sections. 4014xx- Missing, malformed, unknown, revoked or expired key. Every authentication failure looks the same — see Authentication.
4034xx- The key’s user has the
viewerteam role, or their account could not be read just then (retry) — or the key was created Read only (code: "key_read_only", refused before anything else). Checked before the body or any id — see Authentication.Your team role doesn't allow this. Ask your team's admin or owner.This API key is read-only. Create a full-access key to make changes. 4044xx- The outreach switch is off (an EMPTY body), or the prospect id is unknown, belongs to another account, or is not a valid id. The last three are one identical response, never a 403.
Not found 4094xx- Read
code:already_promotedandcandidate_exists(both carrycandidate_idwhen known),opted_out,prospect_incomplete(add a last name and an e-mail to the prospect first), ornot_sendable(one response for several causes, deliberately not told apart).This person has already been promoted to a candidate.You already have a candidate with this number or e-mail.This person has opted out and cannot be contacted.This prospect needs a last name and an e-mail before it can become a candidate.This prospect can't be messaged right now. 4024xx- Your plan does not allow another candidate (the same refusal as Create a candidate).
4294xx- Per-key or per-account rate limit exceeded. Retry after the
Retry-Afterheader.Too many requests — please try again shortly. 5035xx- A read or write failed, or the service is not ready. Retry shortly.
Temporarily unavailable. Try again shortly.
Not yet available. Outreach is switched off for the deployment, and while it is off this endpoint answers 404 with an EMPTY body (not the JSON envelope), before the API key is checked. Do not build against it until it is switched on for your account.
After a promotion, replies from this person go to the Onboardly compliance conversation, and the outreach endpoints refuse the prospect.
curl -X POST \ "https://rca-onboardly.com/api/v1/outreach/prospects/<candidate id>/promote" \ -H "X-Api-Key: $ONB_KEY" \ -H "Idempotency-Key: <your own send id>" \ -H "Content-Type: application/json" \ -d '{ "documents": [ "Passport", "Proof of address" ], "start": true}'{ "documents": [ "Passport", "Proof of address" ], "start": true}{ "data": { "candidate_id": "2f6b1c34-8d5e-4a07-b9c1-3e4d5f6a7b80", "started": true }, "error": null}POST /api/v1/outreach/prospects
curl -X POST \ "https://rca-onboardly.com/api/v1/outreach/prospects" \ -H "X-Api-Key: $ONB_KEY" \ -H "Content-Type: application/json" \ -d '{ "phone": "+447700900321", "first_name": "Jordan", "last_name": "Ellis", "email": "jordan.ellis@example.com", "external_ref": "aura-person-1187", "opt_in": { "source": "partner_attested", "at": "2026-10-20T09:30:00Z", "evidence_ref": "aura-consent-55120" }}'{ "phone": "+447700900321", "first_name": "Jordan", "last_name": "Ellis", "email": "jordan.ellis@example.com", "external_ref": "aura-person-1187", "opt_in": { "source": "partner_attested", "at": "2026-10-20T09:30:00Z", "evidence_ref": "aura-consent-55120" }}{ "data": { "id": "7c3e9a14-5d2b-4f68-8a1e-3b9d6c2f4e85", "phone": "+447700900321", "first_name": "Jordan", "last_name": "Ellis", "email": "jordan.ellis@example.com", "external_ref": "aura-person-1187", "opt_in_source": "partner_attested", "opt_in_at": "2026-10-20T09:30:00.000Z", "opted_out_at": null, "opted_out_reason": null, "promoted_at": null, "revision": 1, "created_at": "2026-10-27T10:00:00.000Z", "updated_at": "2026-10-27T10:00:00.000Z" }, "error": null}{ "data": { "id": "7c3e9a14-5d2b-4f68-8a1e-3b9d6c2f4e85", "phone": "+447700900321", "first_name": "Jordan", "last_name": "Ellis", "email": "jordan.ellis@example.com", "external_ref": "aura-person-1187", "opt_in_source": "partner_attested", "opt_in_at": "2026-10-20T09:30:00.000Z", "opted_out_at": null, "opted_out_reason": null, "promoted_at": null, "revision": 1, "created_at": "2026-10-27T10:00:00.000Z", "updated_at": "2026-10-27T10:00:00.000Z" }, "error": null}GET /api/v1/outreach/prospects/{id}
curl \ "https://rca-onboardly.com/api/v1/outreach/prospects/<candidate id>" \ -H "X-Api-Key: $ONB_KEY"{ "data": { "id": "7c3e9a14-5d2b-4f68-8a1e-3b9d6c2f4e85", "phone": "+447700900321", "first_name": "Jordan", "last_name": "Ellis", "email": "jordan.ellis@example.com", "external_ref": "aura-person-1187", "opt_in_source": "partner_attested", "opt_in_at": "2026-10-20T09:30:00.000Z", "opted_out_at": null, "opted_out_reason": null, "promoted_at": null, "revision": 1, "created_at": "2026-10-27T10:00:00.000Z", "updated_at": "2026-10-27T10:00:00.000Z" }, "error": null}POST /api/v1/outreach/prospects/{id}/send
curl -X POST \ "https://rca-onboardly.com/api/v1/outreach/prospects/<candidate id>/send" \ -H "X-Api-Key: $ONB_KEY" \ -H "Idempotency-Key: <your own send id>" \ -H "Content-Type: application/json" \ -d '{ "consultant_name": "Sam Carter", "role_title": "Support Worker"}'{ "consultant_name": "Sam Carter", "role_title": "Support Worker"}{ "data": { "status": "sent", "message_id": "4e1b7a92-3c8d-4f05-9a6e-2d7c1b8f3a59" }, "error": null}{ "data": { "status": "held" }, "error": null}GET /api/v1/outreach/messages
curl \ "https://rca-onboardly.com/api/v1/outreach/messages" \ -H "X-Api-Key: $ONB_KEY"{ "data": { "messages": [ { "id": "4e1b7a92-3c8d-4f05-9a6e-2d7c1b8f3a59", "prospect_id": "9c3f1d2e-6a7b-4c8d-8e9f-0a1b2c3d4e5f", "external_ref": "crm-77", "direction": "inbound", "body": "Yes, I would like to hear more.", "template_key": null, "delivery_status": null, "safety_flag": null, "created_at": "2026-10-28T09:00:00.000000Z", "updated_at": "2026-10-28T09:00:00.000000Z" } ], "next_cursor": null, "watermark": "2026-10-28T09:59:00.000Z" }, "error": null}POST /api/v1/outreach/prospects/{id}/messages
curl -X POST \ "https://rca-onboardly.com/api/v1/outreach/prospects/<candidate id>/messages" \ -H "X-Api-Key: $ONB_KEY" \ -H "Idempotency-Key: <your own send id>" \ -H "Content-Type: application/json" \ -d '{ "body": "Thanks for coming back to me. Are you free for a quick call tomorrow?"}'{ "body": "Thanks for coming back to me. Are you free for a quick call tomorrow?"}{ "data": { "status": "sent", "message_id": "4e1b7a92-3c8d-4f05-9a6e-2d7c1b8f3a59" }, "error": null}{ "data": { "status": "held" }, "error": null}POST /api/v1/outreach/prospects/{id}/promote
curl -X POST \ "https://rca-onboardly.com/api/v1/outreach/prospects/<candidate id>/promote" \ -H "X-Api-Key: $ONB_KEY" \ -H "Idempotency-Key: <your own send id>" \ -H "Content-Type: application/json" \ -d '{ "documents": [ "Passport", "Proof of address" ], "start": true}'{ "documents": [ "Passport", "Proof of address" ], "start": true}{ "data": { "candidate_id": "2f6b1c34-8d5e-4a07-b9c1-3e4d5f6a7b80", "started": true }, "error": null}