API
Post jobs and receive applications for your account. Each request needs an API key. A key can only see and change jobs on that account.
1. Authenticate
Base URL:
https://app.bkkstaff.com/api/v1
Send your key on every request. Use a Bearer token (preferred) or the X-API-Key
header. Ask us for a key at [email protected].
Authorization: Bearer YOUR_API_KEY
2. Create a job
POST /jobs
Creates a job on your account and returns the apply page and apply email. You do not need a second call for those links.
Send one of these bodies
Option A — fields. Send a title and a description. Add any other fields you know.
curl -X POST https://app.bkkstaff.com/api/v1/jobs \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Line Cook",
"description": "Nights and weekends on the line.",
"category": "Hospitality",
"work_mode": "onsite",
"employment_type": "full_time",
"location": "Kingston"
}'
Option B — pasted ad. Send the full ad as text. We
fill title, description, location, and pay from that text. If you also
send a field (for example title), we keep your value.
curl -X POST https://app.bkkstaff.com/api/v1/jobs \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"text": "Busy Kingston restaurant needs a line cook, nights & weekends..."
}'
What you get back
HTTP 201. JSON body. Always includes:
id— use this to fetch the job laterslug— short code, also used in apply linksapplication_url— web page where a candidate appliesapplication_email— email address that receives applications-
status—pending(not open yet) oractive(open) -
apply_mode—cv(default) orquiz. We do not pick this from the ad text. Sendapply_modeif you want quiz. payment_required— see below
If payment is not required
payment_required
is false. The job opens for
applications shortly. Share application_url
and application_email
with candidates.
{
"id": 61,
"slug": "j4821",
"status": "pending",
"title": "Line Cook",
"apply_mode": "cv",
"application_url": "https://app.bkkstaff.com/job/j4821",
"application_email": "[email protected]",
"payment_required": false
}
If payment is required
payment_required is true. The job is saved but
not open. Send the account owner to pay_url. After they pay,
the job opens. The apply links in the same response stay valid.
{
"id": 61,
"slug": "j4821",
"status": "pending",
"title": "Line Cook",
"apply_mode": "cv",
"application_url": "https://app.bkkstaff.com/job/j4821",
"application_email": "[email protected]",
"payment_required": true,
"pay_url": "https://app.bkkstaff.com/dashboard/jobs/61/pay"
}
Request fields
| Field | Required | Description |
|---|---|---|
title |
Yes, unless you send text |
Job title |
description |
Yes, unless you send text |
Full job post (plain text or HTML) |
text |
Yes, unless you send title and description | Full ad as one string. Same as ad_text. |
summary |
No | Short blurb |
category |
No | For example Hospitality |
location |
No | Place name, for example Kingston |
work_mode |
No | onsite, hybrid, or remote |
employment_type |
No | full_time, part_time, or contract |
salary_min, salary_max |
No | Whole numbers |
salary_period |
No |
hourly, daily, weekly, monthly, or
annually
|
salary_negotiable |
No | true or false |
apply_mode |
No | cv (default) or quiz |
locale |
No | Language code, for example en |
timezone |
No | IANA name, for example America/Jamaica |
ask_work_authorization |
No | true to ask if the candidate may work in the country |
company, email, phone |
No | Public contact shown on this job only |
3. Get a job
GET /jobs/{id or slug}
Optional. Use the id
or slug
from create.
Returns the job fields plus accepting_applications
(true when candidates can apply now).
curl https://app.bkkstaff.com/api/v1/jobs/61 \
-H "Authorization: Bearer YOUR_API_KEY"
4. Update a job
PATCH
or PUT
/jobs/{id or slug}
Change title, description, summary, pay, location, or public contact. You cannot change status or payment through this call.
5. Send an application
POST
/jobs/{id or slug}/applications
Use multipart/form-data
if you attach a CV. The file field
name is cv. A cover note without a file is allowed. Send name, or
first_name
and last_name.
curl -X POST https://app.bkkstaff.com/api/v1/jobs/j4821/applications \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "name=Daniel Brown" \
-F "[email protected]" \
-F "phone=+1876..." \
-F "cover_note=I have five years on the line..." \
-F "opted_in=true" \
-F "cv=@/path/to/cv.pdf"
→ 201
{ "id": 50231, "status": "received" }
Other fields: country, timezone, cover_note, opted_in.
Errors
Failures return JSON: {"error": "code"}.
| HTTP | error | Meaning |
|---|---|---|
| 401 | unauthorized |
Missing or wrong API key |
| 404 | not_found |
No job with that id on this account |
| 409 | duplicate |
This person already applied to this job |
| 422 | invalid |
Send title and description, or send text |
| 422 | could_not_parse_ad |
We could not read the pasted ad. Send title and description instead. |
| 422 | not_accepting |
This job is not open for applications |
| 422 |
missing_name, invalid_email, missing_content
|
Application is missing a name, a valid email, or any content |
| 502 | cv_upload_failed |
CV file did not save. Retry. |
Chat assistant (optional)
If you use Claude or another MCP client, you can do the same work in chat. There is no API key. Add this server and sign in at app.bkkstaff.com:
https://app.bkkstaff.com/mcp
Sign in once in the browser. The assistant names the selected account.
Ask it to switch when you have more than one. Then you can list jobs,
create a job (fields or a pasted ad), and send a candidate email. Create follows the
same payment rules as POST /jobs. The assistant never
charges a card; it returns a pay link when payment is due.
JSON config for some clients:
{
"mcpServers": {
"bkkstaff": { "url": "https://app.bkkstaff.com/mcp" }
}
}
Need a key or help? Email [email protected].