Error Reference
HTTP status codes, error shapes, and recommended responses.
All errors return a JSON body with an error field describing what went wrong. Some errors include additional context (e.g. creditsRemaining, needsCredits).
Status codes
| Code | Meaning | What to do |
|---|---|---|
400 | Bad Request | Check required fields (jobId, coverLetter). Verify field format. |
401 | Unauthorized | API key is missing or invalid. Check your x-api-key header. |
402 | Insufficient Credits | You don't have enough auto-apply credits. Top up in the dashboard. |
404 | Not Found | Job not found. Verify the jobId is correct and the job has been scraped. |
409 | Conflict | Already applied to this job or application is already processing. |
422 | Unprocessable Entity | Request was well-formed but semantically invalid (e.g. unknown timeline value). |
429 | Rate Limited | Too many requests. See the Retry-After header and back off. |
500 | Server Error | Something went wrong on our end. Retry after a brief delay. |
503 | Service Unavailable | Upwork itself is down or rate-limiting us. Retry after a minute. |
Error shape
Retryable vs. terminal
Retryable: 429, 500, 503. Use exponential backoff with jitter.
Terminal: 400, 401, 402, 404, 409, 422. Retrying without changing the request will hit the same error.
Retry helper
Mapping applicationStatus failures
The status endpoint returns business-level failure reasons even when the HTTP response is 200. Most production integrations treat these as errors too:
| Status | Meaning |
|---|---|
failed | Generic failure — inspect errorMessage for details. |
not_eligible | Upwork profile does not meet the job requirements. Not retryable. |
not_enough_connects | Top up Connects on Upwork, then retry from scratch. |
logged_out | Transient — UpHunt reconnects the business developer automatically. Retry after a short delay. |
not_available | Job was removed. Not retryable. |