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. Add this server:
https://app.bkkstaff.com/mcp
Sign in once in the browser. 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].