- How to detect errors
- FORBIDDEN error
- BAD_USER_INPUT error
- Missing required fields
- Invalid datetime
- Invalid country code
- Invalid currency code
- Invalid phone number
- String length exceeded
- GRAPHQL_PARSE_FAILED error
- HTTP 429 Too Many Requests
- Feed type errors
- All jobs on this feed must have seats
- No jobs on this feed may have seats
- Contact validation errors
- No contacts found with type "contact"
- Multiple contacts with type "contact" found
- Salary validation errors
- Maximum amount cannot be less than minimum amount
- Duplicate entry errors
- The request contains duplicate job entries
- The request contains duplicate seat entries
- Multiseat validation errors
- All seats must be located in the same country
- Location validation errors
- cityRegionPostal cannot be null when remote type is not "Fully Remote"
- Job lifecycle issues
- Created job does not appear on Indeed
- Job won't reactivate
- Jobs don't auto-expire
- Retry strategy
- Retryable errors
- Best practices
- Get support
Troubleshoot Job Sync API errors
Common Job Sync API errors and how to resolve them.
How to detect errors
The Job Sync API returns errors in these ways:
- HTTP status codes - Only for rate limiting (HTTP
429) and network-level failures - GraphQL errors array - Most errors return HTTP
200with error details in the response body
Always check the errors array in the response body, even with HTTP 200:
{ "data": null, "errors": [{ "message": "Error description", "extensions": { "code": "BAD_USER_INPUT", "classification": "ValidationError" } }]}The extensions.code field contains the error type (such as FORBIDDEN, BAD_USER_INPUT, GRAPHQL_PARSE_FAILED).
FORBIDDEN error
message | Client is not authorized |
|---|---|
code | FORBIDDEN |
| Summary | The access token is missing, invalid, expired, or lacks the required permissions. |
The Client is not authorized message with FORBIDDEN code means your OAuth client lacks Job Sync API authorization:
{ "data": null, "errors": [{ "extensions": { "code": "FORBIDDEN" }, "message": "Client is not authorized." }]}To resolve:
- Verify the
Authorizationheader format:Authorization: Bearer <YOUR_ACCESS_TOKEN> - Check that the token has not expired (valid for 1 hour).
- Contact your Indeed representative to verify API access.
- Ensure your OAuth application has Job Sync API permissions.
- Verify that
sourceNamematches your registered feed.
For OAuth token errors, see Troubleshoot OAuth errors.
BAD_USER_INPUT error
message | Exception while fetching data |
|---|---|
code | BAD_USER_INPUT |
| Summary | The client sent data that was not valid. |
A BAD_USER_INPUT validation error occurs when the request contains invalid data.
Example with an invalid phone number:
{ "errors": [{ "extensions": { "code": "BAD_USER_INPUT", "classification": "ValidationError" }, "message": "Validation error (WrongType@[jobsIngest/createSourcedJobPostings]) : argument 'input.jobPostings[0].metadata.contacts[0].contactInfo.contactPhone' with value 'StringValue{value='5551234567'}' is not a valid 'PhoneNumber' - String value `5551234567` is not a valid E.164 phone number" }]}Common causes of BAD_USER_INPUT errors:
Missing required fields
The error message indicates which field is missing. Required fields include:
| Section | Required fields |
|---|---|
body | title, description, benefits (can be empty array), location.country |
metadata | jobPostingId, jobSource.sourceName, datePublished, contacts (at least one) |
Invalid datetime
DateTime values must use RFC 3339 format with timezone:
| Format | Valid? |
|---|---|
2024-01-15T10:30:00-05:00 | Yes |
2024-01-15T15:30:00Z | Yes |
2024-01-15 | No (missing time) |
01/15/2024 10:30 | No (wrong format) |
Invalid country code
Country codes must use ISO-3166-1 alpha-2 format (2 uppercase letters):
| Format | Valid? |
|---|---|
US | Yes |
USA | No (use 2-letter code) |
us | No (must be uppercase) |
Invalid currency code
Currency codes must use ISO-4217 format (3 uppercase letters):
| Format | Valid? |
|---|---|
USD | Yes |
$ | No (use ISO code) |
usd | No (must be uppercase) |
Invalid phone number
Phone numbers must use E.164 format:
| Format | Valid? |
|---|---|
+15125551234 | Yes |
512-555-1234 | No (missing country code, no dashes) |
(512) 555-1234 | No (no formatting characters) |
String length exceeded
| Field | Maximum length |
|---|---|
title | 255 characters |
description | 65,000 bytes |
seatPostingId | 250 characters |
sourceName | 250 characters |
GRAPHQL_PARSE_FAILED error
message | Syntax Error: Invalid number, expected digit but got: "a". |
|---|---|
code | GRAPHQL_PARSE_FAILED |
| Summary | A GraphQL operation string contains a syntax error. Usually, this error occurs if you do not escape HTML tags in the |
The GRAPHQL_PARSE_FAILED error indicates syntax errors in the query or mutation:
{ "errors": [{ "message": "Syntax Error: Invalid number, expected digit but got: \"a\".", "locations": [{ "line": 7, "column": 33 }], "extensions": { "code": "GRAPHQL_PARSE_FAILED" } }]}Common causes:
- Unescaped special characters in string values (quotes, backslashes)
- Malformed GraphQL syntax
- Invalid JSON in variables
The description field supports raw HTML when using descriptionFormatting: RICH_FORMATTING. HTML tags do not need escaping.
HTTP 429 Too Many Requests
You exceeded your rate limit. This is one of the few cases where the API returns an HTTP status code other than HTTP 200.
To resolve:
- Check the
Retry-Afterresponse header for seconds to wait before retrying. - Spread requests over time rather than sending large batches.
- Send 1 job per request and call APIs in real-time rather than hourly batches.
For more details, see Rate limiting.
Feed type errors
All jobs on this feed must have seats
You are using a multiseat feed but did not include seats.
Add a seats array with at least one seat:
body: { title: "Software Engineer" location: { country: "US" } seats: [{ seatPostingId: "SEAT-001" seatLocation: { country: "US" cityRegionPostal: "Dallas, TX 75201" } }]}No jobs on this feed may have seats
You are using a standard feed but included seats.
Remove the seats array and specify location at the job level:
body: { title: "Software Engineer" location: { country: "US" cityRegionPostal: "Austin, TX 78701" streetAddress: "100 Congress Ave" }}If unsure of your feed type, try submitting a job without seats first.
Contact validation errors
No contacts found with type "contact"
Your request is missing a contact with "contact" in contactType.
Include exactly one contact with "contact" in its contactType array:
contacts: [{ contactType: ["contact", "hiring manager"] contactInfo: { email: "hr@example.com" }}]Multiple contacts with type "contact" found
More than one contact has contact in its contactType array. Only one contact can have the contact type. Use types like recruiter or hiring manager for other contacts.
Salary validation errors
Maximum amount cannot be less than minimum amount
The maximumMinor value is less than minimumMinor.
Ensure maximumMinor is greater than or equal to minimumMinor, or omit maximumMinor for minimum-only salary:
salary: { currency: "USD" minimumMinor: 5000000 # $50000 maximumMinor: 7500000 # $75000 period: "YEAR"}Salary values are in minor currency units (cents for USD). $50,000 = 5000000, not 50000.
Duplicate entry errors
The request contains duplicate job entries
Each job must have a unique sourceName and jobPostingId pair. The same pair appears more than once in the request.
The request contains duplicate seat entries
Each job must have a unique sourceName and seatPostingId pair. The same pair appears more than once in the request.
Multiseat validation errors
All seats must be located in the same country
Seat locations have different countries than the top-level job location.
All seats must use the same country code as the job's top-level location:
body: { location: { country: "US" } seats: [{ seatPostingId: "SEAT-001" seatLocation: { country: "US" # Must match top - level cityRegionPostal: "Dallas, TX 75201" } }, { seatPostingId: "SEAT-002" seatLocation: { country: "US" # Must match top - level cityRegionPostal: "Austin, TX 78701" } }]}Location validation errors
cityRegionPostal cannot be null when remote type is not "Fully Remote"
Non-remote jobs require cityRegionPostal.
Provide cityRegionPostal or set the job as fully remote:
# Option 1: Provide locationlocation: { country: "US" cityRegionPostal: "Austin, TX 78701"}# Option 2: Set as fully remotelocation: { country: "US"}taxonomyClassification: { remoteType: "Fully Remote"}Job lifecycle issues
Created job does not appear on Indeed
Possible causes:
- Job is still processing (allow 1-2 hours).
- Job was rejected during processing.
- Incorrect
sourceName.
To resolve:
- Wait 1-2 hours for jobs to become searchable.
- Query job status using the
employerJobId. - Check
lifecycleStatusandisRejectedfields. - Verify
sourceNamematches your registered feed.
Job won't reactivate
Jobs can only be reactivated within 30 days of expiration.
-
Within 30 days: Call
createSourcedJobPostingswith originaljobPostingIdandsourceName, and updatedatePublished -
Beyond 30 days: Create as a new job (might receive a new
sourcedPostingId)
Jobs don't auto-expire
Jobs do not automatically expire. You must explicitly call expireSourcedJobsBySourcedPostingId to expire them.
Retry strategy
The Job Sync API uses an upsert pattern, making retries safe. Submitting a job with the same sourceName and jobPostingId updates the existing job rather than creating a duplicate.
Retryable errors
| Error | Retryable? | Strategy |
|---|---|---|
| HTTP 429 Too Many Requests | Yes | Wait for Retry-After header value |
| Network timeout | Yes | Exponential backoff |
| Connection refused | Yes | Exponential backoff |
FORBIDDEN (expired token) | Yes | Refresh token, then retry once |
BAD_USER_INPUT | No | Fix the request |
GRAPHQL_PARSE_FAILED | No | Fix the query syntax |
Best practices
- Use exponential backoff with jitter for retries.
- Start with a 1-second delay, doubling with each retry.
- Add random jitter (0-1 second) to prevent thundering herd.
- Limit to 3-5 retry attempts.
Get support
If you encounter issues not covered in this guide:
- Check the GraphQL error
messageandextensionsobject. - Verify all required fields are present and correctly formatted.
- Test with minimal input first, then add fields incrementally.
- Contact your Indeed representative for feed-specific issues.
See also: