API
A REST API for managing your organization's job postings and applicant statuses from your own systems — an ATS, a scheduling tool, a nightly sync job. Questions? Get in touch.
Generate a key from your organization's API keys page (Org dashboard → API — only the organization owner can create or revoke keys). Every request needs it:
Authorization: Bearer cc_live_...The full OpenAPI 3.0 spec has every field. This page covers the common paths.
Requests and responses
- Base URL:
https://callingcard.work/api/v1 - Request bodies are JSON (
Content-Type: application/json). - Every response is JSON:
{ "data": ... }on success,{ "error": { "message": "..." } }on failure. - Lists are paginated: pass
?cursor=<id>from a response'snextCursorto get the next page.nextCursorisnullon the last page. - Rate limit: 120 requests per 60 seconds per key. A
429means you've hit it.
| Status | Meaning |
|---|---|
| 401 | Missing or invalid API key |
| 403 | Not allowed yet — usually an unverified organization trying to publish |
| 404 | No such job/application for your organization |
| 422 | The request body failed validation |
| 429 | Rate limit exceeded |
List jobs
GET /jobs
Query params: status (DRAFT, PUBLISHED, or CLOSED), limit (default 25, max 100), cursor.
curl https://callingcard.work/api/v1/jobs?status=PUBLISHED \
-H "Authorization: Bearer cc_live_..."Create a job
POST /jobs
title, description, and employmentType (FULL_TIME, PART_TIME, CONTRACT, INTERNSHIP, or VOLUNTEER) are required. status defaults to DRAFT — set it to PUBLISHED to publish immediately, which is checked against your plan's job quota and your organization's verification status the same way publishing from the dashboard is. Some states require salaryMin/salaryMax before a job can publish.
curl -X POST https://callingcard.work/api/v1/jobs \
-H "Authorization: Bearer cc_live_..." \
-H "Content-Type: application/json" \
-d '{
"title": "Warehouse Associate",
"description": "Full-time role at our downtown facility.",
"employmentType": "FULL_TIME",
"payType": "HOURLY",
"salaryMin": 18,
"salaryMax": 22,
"status": "PUBLISHED"
}'Update a job
PATCH /jobs/{jobId}
Send only the fields you're changing — everything else is left as-is. Include status to publish or close it in the same request.
curl -X PATCH https://callingcard.work/api/v1/jobs/JOB_ID \
-H "Authorization: Bearer cc_live_..." \
-H "Content-Type: application/json" \
-d '{ "status": "CLOSED" }'List a job's applications
GET /jobs/{jobId}/applications
Query params: limit, cursor. Each application includes the applicant's name and email, but never their résumé or full profile — this API is for pipeline status, not candidate data export.
curl https://callingcard.work/api/v1/jobs/JOB_ID/applications \
-H "Authorization: Bearer cc_live_..."Update an application's status
PATCH /applications/{applicationId}
status is required: SUBMITTED, REVIEWING, INTERVIEW, OFFER, REJECTED, or WITHDRAWN. Moving to most of these sends the applicant a status email — and a text, if they've opted in and verified a phone number — the same way changing it from the dashboard does. orgMessage is shown to the applicant and included in that email.
To schedule an interview, send interviewType, interviewAtLocal, and interviewTimezone together — a partial interview update is ignored and the application's existing interview details (if any) are left alone.
curl -X PATCH https://callingcard.work/api/v1/applications/APPLICATION_ID \
-H "Authorization: Bearer cc_live_..." \
-H "Content-Type: application/json" \
-d '{
"status": "INTERVIEW",
"orgMessage": "Thanks for applying — we would like to talk.",
"interviewType": "VIRTUAL",
"interviewLocation": "https://meet.example.com/abc",
"interviewAtLocal": "2026-09-20T14:00",
"interviewTimezone": "America/Chicago"
}'