Error Handling
The Fribl API uses standard HTTP status codes and returns JSON error bodies to indicate what went wrong.
Most API errors follow this structure:
{
"error": "Human-readable error description"
}
Update endpoints can also proxy structured validation errors from the ingestion service:
{
"detail": {
"message": "Update validation failed.",
"invalid_skills": [
{
"id": "not-a-real-skill-id",
"field": "hard_skills",
"message": "Skill does not exist in the canonical graph/taxonomy."
}
]
}
}
Schema mismatches on update use 422 Unprocessable Entity with structured details:
{
"detail": {
"message": "Payload does not match VacancyUpdate schema for entity_type=Vacancy.",
"schema": "VacancyUpdate",
"errors": [
{
"type": "missing",
"loc": ["information", "title"],
"msg": "Field required"
}
]
}
}
HTTP status codes
| Code | Meaning | When it occurs |
|---|
200 | OK | Request succeeded |
400 | Bad Request | Invalid request body, missing required fields, invalid file format, weight sum exceeds 1.0, or update validation failed |
401 | Unauthorized | Missing or invalid x-api-key header |
402 | Payment Required | Workspace has insufficient tokens for the requested operation |
404 | Not Found | Requested CV, job, or match does not exist |
422 | Unprocessable Entity | Update payload does not match the expected CV or job update schema |
429 | Too Many Requests | Rate limit exceeded |
500 | Internal Server Error | Unexpected server-side failure |
502 | Bad Gateway | Upstream service error (sourcing endpoints) |
503 | Service Unavailable | Required external service is not configured (sourcing endpoints) |
Common error examples
Invalid API key
{
"error": "Invalid API Key."
}
Fix: Verify your x-api-key header contains a valid key.
Insufficient tokens
Billable endpoints return 402 Payment Required with a structured body when your workspace can’t cover the request. No work is performed and nothing is charged.
{
"code": "INSUFFICIENT_TOKENS",
"message": "Insufficient tokens: have 3, need 10",
"balance": 3,
"required": 10
}
Fix: Switch on code (not the message), add tokens in the Fribl Console, confirm with GET /tokens/balance, then retry — charging is idempotent, so re-sending the same request is safe. See Tokens & Billing for the full pricing and refund model.
Missing required field
{
"error": "Missing required fields."
}
Fix: Ensure your request body includes all required fields. For analyze endpoints, the inputs field must be a non-empty array of strings.
Update validation failure
{
"detail": {
"message": "content_language is required and must be a valid ISO 639-1 language code."
}
}
Fix: On PUT /jobs/{id} and PUT /cvs/{id}, send content_language (or set the Accept-Language header — the API auto-forwards it), include at least one allowed dimension (information, experience/experience_preference, education/education_preference, hard_skills, soft_skills), and use split hard_skills / soft_skills arrays with canonical lowercase relationship values: required, optional, satisfies.
Resource not found
{
"error": "CV not found"
}
Fix: Verify the ID exists and that the resource has finished processing. Check with the status endpoint first.
Match weight validation
{
"error": "Sum of weights cannot be greater than 1"
}
Fix: Ensure that experience + hardSkills + softSkills + education in your weights object does not exceed 1.0.
Processing statuses
CV and job analysis is asynchronous. After submitting a document, poll the status endpoint to track progress. The public API uses a single normalized vocabulary across POST /analyze, POST /analyze/files, POST /{cvs,jobs}/status, and GET /{cvs,jobs}/{id}:
| Status | Meaning |
|---|
PENDING | The task is queued, actively being processed, or being retried after a transient failure. Keep polling. |
COMPLETED | Analysis is finished — retrieve results or run matching. |
FAILED | Analysis errored out — resubmit the document. |
NOT_FOUND | No record exists for that ID in the requested resource type. Returned only by the batch POST /status endpoints. |
Failed tasks are refunded. When a task ends in FAILED, the tokens charged for it are returned automatically — you only pay for work that completes. The same applies to server errors (5xx). See Tokens & Billing.
Poll the status endpoint at reasonable intervals (e.g., every 2–3 seconds) rather than in a tight loop. Continue polling while the status is PENDING. Typical analysis completes within a few seconds.
GET /cvs/{id} and GET /jobs/{id} use HTTP status codes to signal readiness: an in-flight task returns 404 with body { "message": "...", "status": "PENDING" } (keep polling), and a ready entity returns 200 with status: "COMPLETED". A 404 with an { "error": "..." } body means the ID does not exist.