GraphQL error responses

Unlike REST APIs, GraphQL servers don’t use HTTP status codes to indicate unsuccessful requests. Instead, the GraphQL response body includes an array of errors when an operation fails.The SEEK API uses four error codes to classify the type of error that occurred. Depending on the type of error there will be further information in the error’s message and extensions.The SEEK API’s error messages are safe to expose to SEEK hirers. However, some errors responses can indicate a problem with your SEEK API integration that’s not actionable by an end user. If you decide to hide those error messages, your software should still log the full message to support debugging issues.

UNAUTHENTICATED

An UNAUTHENTICATED error indicates a problem with the access token included in the request. More details will be available in the error’s message.

Common causes

  • An access token wasn’t included in the request’s Authorization header.
  • The access token has expired. This can happen if the access token is used after the expires_in from the token response.
  • A Playground access token was used to access live data or vice versa.

Example response

JSON
Copy
{
  "errors": [
    {
      "message": "Public test partner token is expired",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": ["candidateProfile"],
      "extensions": {
        "code": "UNAUTHENTICATED"
      }
    }
  ]
}

Retrying authentication errors

If you receive an UNAUTHENTICATED error due to an expired access token as per the example above, your software may request a new access token and use it to automatically retry the request. Limit such behaviour to a single retry; if your software continues to receive the same error with a newly issued token then you have likely misconfigured the request and further retries will not help.You may be able to customise your GraphQL or HTTP client library to implement a retry policy. Ensure that your retry policy takes the error code in the response into account, as retrying a request with a different error like FORBIDDEN is unlikely to produce a different result.

FORBIDDEN

A FORBIDDEN error indicates a valid access token was received but there was a problem authorizing the operation. More details will be available in the error’s message.It’s possible to have access to an object but not all of its nested objects or fields. For example, you can query a PositionProfile for Optimised Apply but wouldn’t be able to query its branding without an additional JobPosting relationship. To help debugging these situations the error’s path will indicate which field encountered the FORBIDDEN error.Requests that fail authorization should not be automatically retried.

Common causes

Example failing query

QueryVariablesResult
query ($id: String!) {
  # Hirer has been disabled
  hiringOrganization(id: $id) {
    name
  }
}

BAD_USER_INPUT

A BAD_USER_INPUT error indicates the operation failed input validation. A top-level summary of the validation failure will be available in the error’s message.Some operations support additional field-level messages in the invalidFields map. Its keys are JSON Pointers  to the invalid fields in the operation’s arguments. These map to a message describing why the field failed validation.Requests that fail validation should not be automatically retried.

Common causes

  • The input was the correct type for the GraphQL schema but violated a more specific constraint.
  • A mutation’s input referenced an object that doesn’t exist.
  • The operation exceeded the SEEK API’s query complexity limit.An operation’s complexity is calculated based on the estimated size of its response. Overly complex operations are rejected before they’re executed to prevent denial of service attacks .

Example failing mutation

MutationVariablesResult
mutation ($input: CreateWebhookSubscriptionInput!) {
  createWebhookSubscription(input: $input) {
    ... on CreateWebhookSubscriptionPayload_Success {
      webhookSubscription {
        id {
          value
        }
      }
    }

    ... on CreateWebhookSubscriptionPayload_Conflict {
      conflictingWebhookSubscription {
        id {
          value
        }
      }
    }
  }
}

RATE_LIMITED

A RATE_LIMITED error indicates that the request has been blocked due to a rate limit being exceeded. To maintain system stability, the SEEK API rate limits requests that significantly exceed typical usage patterns.Rate limits are applied per query/mutation and may vary depending on the specific operation being performed. Certain queries and mutations may have their rate limits documented in the SEEK API schema when appropriate, however most limits are generous but undocumented, and subject to change.

Potential causes

  • Inefficient requests: Making redundant or unoptimised requests to the SEEK API, e.g. polling the API for new events rather than using webhooks.
  • Uncontrolled loops: If SEEK API requests are made in a loop, take care to ensure the loop terminates appropriately. An uncontrolled loop could cause your software to call the SEEK API in an infinite loop, quickly exceeding your request quota.
  • Excessive retries: Retrying failed requests too aggressively could cause your software to consume its request quota quickly.
If you consistently encounter rate limiting or are planning to significantly increase your request volume, contact SEEK’s support team . We’ll work with you to resolve the issue and adjust rate limits if necessary.

Example response

JSON
Copy
{
  "errors": [
    {
      "message": "Too many requests. Contact SEEK for assistance.",
      "path": ["postPosition"],
      "extensions": {
        "code": "RATE_LIMITED"
      }
    }
  ]
}

INTERNAL_SERVER_ERROR

An INTERNAL_SERVER_ERROR indicates an unexpected failure occurred while processing the request.Error details are omitted from the response to avoid exposing sensitive information about SEEK’s systems. However, the message will contain a reference code SEEK can use to find more details in our internal logs.

Example response

JSON
Copy
{
  "errors": [
    {
      "message": "Oops. Something went wrong. If you continue to experience issues, contact support and quote error reference '112c-4edf-af8e'.",
      "path": ["positionProfile"],
      "extensions": {
        "code": "INTERNAL_SERVER_ERROR"
      }
    }
  ]
}

Retrying server errors

Your software should have a reasonable retry policy on INTERNAL_SERVER_ERROR errors for robustness . This increases the likelihood that your integration will remain operational through transient failures in the SEEK API. You may also time out and retry a request if it has taken too long for the SEEK API to respond.Requests that carry a mutation must be idempotent  to prevent retries from unintentionally creating or modifying multiple objects. For example, you must use the same idempotencyId when retrying a job posting mutation to ensure that only one job ad is created.You may be able to customise your GraphQL or HTTP client library to implement a retry policy. Ensure that your retry policy takes the error code in the response into account, as retrying a request with a different error like FORBIDDEN is unlikely to produce a different result.The policy behaviour may differ based on the use case. A shorter request timeout and backoff may be appropriate a high-volume interactive hirer experience like location suggest. On the other hand, a back-end process like exporting applications could have a longer delay between retries and send persistent failures to a dead letter queue  for manual reprocessing once the SEEK API has restored service.Your software should cap the number of request retries and implement exponential backoff and jitter  as best practices. By progressively increasing the delay between retries and introducing a random factor to the calculation, you space out your requests and avoid overwhelming the SEEK API, increasing the likelihood that your requests will be served sooner. Generally speaking, you should not retry a request more than 3 times.Contact SEEK if you need to discuss the specifics of your retry policy.

Other errors

The GraphQL error codes above accompany a HTTP status code of 200. However, the SEEK API may return HTTP status codes other than 200 in some scenarios.If you encounter any of these and need assistance, contact SEEK’s support team  with details such as your tracing headers, the request body, as well as the status code, headers and body of the response.HTTP response status codes other than 200 may include:
  • 400, alongside a GRAPHQL_PARSE_FAILED or GRAPHQL_VALIDATION_FAILED GraphQL error codes. These error codes indicate a problem with GraphQL syntax or schema usage with your software, and generally should only occur during development.
  • 400 or 403 codes may be returned if security controls are triggered. In this scenario, the response body might not be JSON.
  • A 429 status code may be returned by attachment download endpoints if the request rate exceeds the allowed limit.
  • 500, 502, 503 and other 5xx codes may indicate the SEEK API is experiencing an outage or other technical issue. You can check the status page  for any known issues. In this scenario, the response body might not be JSON. Your software should implement a retry policy for these errors.
  • Networking errors may surface in different forms depending on your technology stack. For example, connection timeouts, socket timeouts, socket hangups, or otherwise. This could indicate a problem in the SEEK API, your networking, or anything in between. You can check the status page  for any known issues. Your software should implement a retry policy for these errors.