Jobiflow LogoDocs

Errors

HTTP status codes, the error body, error codes and rate limits

Errors

The Jobiflow API uses conventional HTTP status codes. Every error on a /public/v1/ endpoint answers with the same JSON body, ErrorDetails.


HTTP Status Codes

CodeMeaning
200 OKRequest succeeded
201 CreatedResource created
204 No ContentRequest succeeded, no body (deletes)
400 Bad RequestThe body or a parameter is invalid
401 UnauthorizedMissing, unknown, revoked or expired API key, or an invalid bearer header next to it
402 Payment RequiredPublishing a listing: the company's credits do not suffice
403 ForbiddenThe key lacks the endpoint's scope
404 Not FoundThe resource does not exist or belongs to another company, or no endpoint has this path
405 Method Not AllowedThe path exists, but not with this method; the Allow header lists the methods it takes
409 ConflictExternal application: the candidate already applied to this listing. Deleting a listing that has applications
415 Unsupported Media TypeThe body is not sent as application/json
429 Too Many RequestsThe key's rate limit is used up
500 Internal Server ErrorUnexpected failure in the API
502 Bad GatewayA service behind the API failed
503 Service UnavailableA service behind the API did not answer

Error Body

{
  "errorCode": "INVALID_REQUEST",
  "message": "Invalid request",
  "statusCode": 400,
  "path": "/public/v1/job-listings",
  "timestamp": "2026-10-25T12:00:00.123",
  "fieldErrors": [
    { "field": "position", "message": "must not be null" }
  ]
}
FieldDescription
errorCodeMachine-readable error code (see below); branch on this
messageEnglish description, for logs
statusCodeThe HTTP status code
pathThe request path
timestampWhen the error happened, ISO 8601 without offset
fieldErrorsOnly on validation errors: the fields that failed, each with field and message

Error Codes

CodeStatusDescription
INVALID_REQUEST400The body or a parameter is invalid; fieldErrors lists the fields on a validation error
INVALID_REQUEST404, 405, 415The request matches no endpoint: unknown path (404), a method the path does not take (405), a body that is not JSON (415)
INVALID_API_KEY401No X-API-Key header, or the key is unknown, revoked or expired
TOKEN_INVALID401A valid key was sent with an invalid Authorization: Bearer header
INSUFFICIENT_CREDITS402Publishing needs more credits than the company has
ACCESS_DENIED403The key lacks the endpoint's scope
NOT_FOUND404The listing, application or other resource does not exist or belongs to another company
JOBSEEKER_NOT_FOUND404The candidate does not exist or is not visible to your company
WEBHOOK_SUBSCRIPTION_NOT_FOUND404The webhook subscription does not exist or belongs to another company
JOBSEEKER_ALREADY_APPLIED409External application: the candidate already applied to this listing
JOBLISTING_HAS_APPLICATIONS409The listing has applications, so it cannot be deleted; archive it instead (PATCH /public/v1/job-listings/{id}/archive)
RATE_LIMIT_EXCEEDED429The key's rate limit is used up; wait for Retry-After
UNEXPECTED_ERROR500, 502, 503A failure in the API or in a service behind it; retry later

A 400 that a service behind the API raises keeps that service's code, for example INVALID_JOBLISTING_STATUS_TRANSITION for a status change the listing cannot make.

A 404 therefore carries NOT_FOUND (or a resource's own code) when the endpoint exists but the resource does not, and INVALID_REQUEST when no endpoint has the path. The key is checked first: without a valid key every one of these answers 401 INVALID_API_KEY.


Handling Errors

const res = await fetch('https://api.jobiflow.com/public/v1/job-listings', {
  headers: { 'X-API-Key': process.env.JOBIFLOW_API_KEY },
});

if (!res.ok) {
  const err = await res.json();
  console.error(`[${err.errorCode}] ${err.message}`);

  for (const field of err.fieldErrors ?? []) {
    console.error(`  - ${field.field}: ${field.message}`);
  }

  throw new Error(err.errorCode);
}

const { data, pagination } = await res.json();

Rate Limits

Each API key may send 60 requests per minute and 10 per second. Beyond that the API answers 429 Too Many Requests with RATE_LIMIT_EXCEEDED and a Retry-After header: the number of seconds to wait.

HTTP/1.1 429 Too Many Requests
Retry-After: 1

On this page