Reference documentation for the MyJobMag Ghana ATS inbound API
Every request must include an Authorization header with your API key:
Authorization: Bearer mjm_<cc>_<token>
Where cc is the two-letter country code for this site (for example, gh for Ghana). Each credential is tied to a specific employer account and to one country host. Sending a key to the wrong country host returns 401. Key rotation generates a new credential and immediately invalidates the old one.
All endpoints are on the same URL. The HTTP method, and in one case a query parameter, determine the operation.
| Method | URL | Operation |
|---|---|---|
| POST | /api/ats/jobs.php | Create a job |
| PUT | /api/ats/jobs.php | Update a job (external_id in body) |
| POST | /api/ats/jobs.php?action=close | Close a job (external_id in body) |
| GET | /api/ats/jobs.php?external_id=<id> | Get one job by external ID |
| GET | /api/ats/jobs.php | List all jobs for this integration |
Request:
POST /api/ats/jobs.php HTTP/1.1
Host: www.myjobmag.com
Authorization: Bearer mjm_gh_AbCdEfGhIjKlMnOpQr...
Content-Type: application/json
{
"external_id": "JOB-2024-0042",
"title": "Software Engineer",
"description": "We are looking for a software engineer to join our team...",
"company_name": "Acme Corporation",
"company_website": "https://www.acmecorp.example.com",
"company_about": "Acme Corporation builds innovative tools for developers worldwide.",
"company_logo_url": "https://www.acmecorp.example.com/logo.png",
"deadline": "2024-09-30",
"apply_url": "https://careers.example.com/apply/42",
"min_experience": 2,
"max_experience": 5
}
Response (HTTP 201):
{
"external_id": "JOB-2024-0042",
"state": "pending_review",
"received_date": "2024-06-18 09:14:32",
"published_date": "",
"public_link": "",
"amount_charged": "50"
}
If the account is configured for auto-publish, state will be published and public_link will contain the live URL. Otherwise state is pending_review while the job is checked by our team.
The external_id field is your idempotency key. If you POST a job with an external_id you have already submitted, the API returns the existing job record with HTTP 200 and does not create a duplicate or charge you again. This means retrying a failed request is always safe.
Send payload as a JSON body. Unknown keys are ignored.
Each job names its own hiring company via company_name. The hiring company does not need a MyJobMag account; the API credential and billing are tied to your integration account, not to the company being advertised.
| Field | Type | Required | Notes |
|---|---|---|---|
| external_id | string | Yes | Your system's unique job identifier. 1 to 191 characters. Idempotency key. |
| title | string | Yes | Job title. Truncated to 255 characters if longer. |
| description | string | Yes | Full job description. HTML is accepted. |
| company_name | string | Yes | The hiring company's name. Jobs are published under this company. Companies are matched by name within the country, or created if no match is found. Truncated to 255 characters if longer. |
| company_website | string | No | The hiring company's website URL. Truncated to 255 characters if longer. |
| company_about | string | No | Short description of the hiring company. Truncated to 5000 characters if longer. |
| company_logo_url | string | No | URL to the company logo image. Used by our team during manual review only; the logo is not fetched or stored automatically. Truncated to 500 characters if longer. |
| deadline | string | No | Application deadline. Recommended format: Y-m-d. Unparseable values are silently ignored. |
| apply_url | string | No | URL for candidates to apply. Takes precedence over apply_email if both are provided. |
| apply_email | string | No | Email address for applications. Used when apply_url is not provided. |
| min_experience | integer | No | Minimum years of experience required. Defaults to 0. |
| max_experience | integer | No | Maximum years of experience. Defaults to 0. |
| salary | integer | No | Salary figure (currency is per account configuration). |
| specialization | integer | No | Specialization/category ID from the site taxonomy. |
| show_company_name | boolean | No | Whether to display the company name on the listing. Defaults to true. |
| states | array of integers | No | State/region IDs where the job is located. Non-positive values are ignored. |
| qualifications | array of integers | No | Qualification/education level IDs required for the role. Non-positive values are ignored. |
Each accepted job is charged at your account's per-job price, deducted from your wallet balance at the time the job is received. The create call returns 402 if your balance cannot cover the fee or if the balance is negative; in that case no job is created and no charge is made.
If a job that was manually reviewed by our team is disapproved, the charge is automatically refunded to your wallet.
If your account has a minimum monthly spend commitment, the difference between your actual spend and the minimum is reconciled against your wallet on the 1st of each month.
| HTTP status | Meaning |
|---|---|
| 401 | Missing, invalid, or disabled credential. Also returned when a valid key is used against the wrong country host. |
| 402 | Insufficient funds. The wallet balance is below the per-job price, or the balance is negative. |
| 405 | Method not allowed. The HTTP method and query parameter combination does not match any operation. |
| 409 / 422 | Duplicate or validation error. A create returns 422 if required fields are missing or invalid. Note: a repeated create with the same external_id returns 200, not 409. |
| 429 | Rate limit exceeded. Maximum 120 requests per minute per API key. Wait before retrying. |
Questions about implementation or your account setup? Contact us and we will assist.
Request integration Back to ATS integration overview