Core concepts

Errors

Gemlead answers with an HTTP status and a JSON error whose type and code never change, so your code can branch on them.

The error object

Every error has the same shape. message is for people and may change, type and code are for your code. Every response, error or not, also carries its Request-Id header.

Attributes

  • typestring
    The family of the error, one per HTTP status.
  • codestring
    What went wrong exactly. See the codes below.
  • messagestring
    A sentence that explains the error.
  • paramstring or null
    The parameter at fault, when there is one.
  • request_idstring
    The request's ID, the same as its Request-Id header. Send it to us when you need help.
  • doc_urlstring
    This page, at the code's entry.
Response400
{
  "error": {
    "type": "invalid_request_error",
    "code": "parameter_invalid",
    "message": "score_min must be an integer from 0 to 100.",
    "param": "score_min",
    "request_id": "req_7Hq2LmX9pT4vK1sN",
    "doc_url": "https://gemlead.ai/docs/errors#parameter_invalid"
  }
}

HTTP status codes

StatusTypeMeaning
400invalid_request_errorThe request has a missing, unknown or invalid parameter. A method the path does not take gets this type too, with a 405.
401authentication_errorNo key, a wrong key or a revoked key.
403permission_errorThe key is valid but cannot do this, like a read key writing, or an account on the Free or Starter plan.
404not_found_errorNo such object on the key's account, or no such route.
409idempotency_errorAn Idempotency-Key was reused for another request, or its first request is still running.
429rate_limit_errorToo many requests. Wait for Retry-After seconds.
500api_errorSomething went wrong on our side, or 501 for an endpoint not available yet. Retry later with the same Idempotency-Key.

Error codes

CodeStatusMeaning
api_key_missing401The request has no Authorization or X-Api-Key header.
api_key_invalid401No key matches. Check that you copied all of it, gl_live_ included.
api_key_revoked401The key was revoked in the app. Create a new one.
token_expired401An OAuth access token of an AI assistant expired. The assistant refreshes it on its own.
insufficient_scope403The key has the read scope and the request changes data. Use a key with write.
plan_required403The account's owner is on the Free or Starter plan. The API works on Business and Enterprise, trial included, and the same key works again once the account is on one of them.
forbidden403The key's user may not do this on the X account, like a team member who changes the team without being an admin, or shares a persona.
parameter_missing400A required parameter is missing. param names it.
parameter_invalid400A parameter has a value the API does not accept, like a score above 100 or a date that is not ISO 8601. param names it.
parameter_unknown400The query or the body has a parameter this endpoint does not take. param names it.
body_invalid400The body is not valid JSON, or not a JSON object.
cursor_invalid400The cursor is not one the API gave, or was made for other filters.
idempotency_key_invalid400The Idempotency-Key is longer than 255 characters.
method_not_allowed405This path does not take this method. The Allow header lists the ones it takes.
url_invalid400A webhook URL is not HTTPS, has credentials in it, does not resolve, or points to a private address.
webhook_endpoint_limit_reached400The account already has 10 webhook endpoints. Delete one first.
resource_already_exists400It is there already, like a source the persona has with this method or a keyword search it has.
limit_reached400A limit is reached, like 100 personas on an account, 500 keyword searches on a persona or 50 board columns.
seed_source_refused400A starting source of a new persona is refused, like an investor, an accelerator or a media account. They bring no buyers.
x_profile_not_found400X has no readable profile at this username.
lead_without_x_id400The lead has no X account ID yet, so it cannot be followed.
lead_not_convertible400The lead belongs to no persona, so it cannot become a source.
campaign_archived400The campaign is archived. Duplicate it to run it again.
campaign_not_started400The campaign is a draft, so there is nothing to pause.
campaign_flow_empty400The campaign's flow has no step yet. Add one before you start it.
column_protected400This column belongs to the board, like Inbox or a persona column, and cannot be deleted.
shared_account_has_campaigns400An X account you take out of a shared persona still has campaigns on it. Delete them, then try again.
owner_cannot_leave400The owner of an X account cannot leave its team. Remove the members instead.
translation_off400The conversation's translation is off. Turn it on, or translate one message at a time.
recipient_not_messageable400X refused the DM. The lead closed their DMs or blocked the account.
media_kind_unsupported400The conversation cannot take this kind of file. A voice note needs an X Chat conversation.
x_session_expired409The X account's session expired. Reconnect it in the app, then try again.
assistant_busy409Julien AI is still answering a message of this chat, or 3 messages of this X account. Wait for that reply, then send again.
conversation_unavailable409The conversation has no X user to write to yet.
resource_missing404No object with this ID on the key's account. An ID of another account answers the same.
route_not_found404No endpoint at this path.
idempotency_key_reused409This Idempotency-Key was used in the last 24 hours for a different method, path or body.
idempotency_key_in_use409The first request with this Idempotency-Key is still running. Retry in a second.
rate_limit_exceeded429More than 120 requests in the minute with this key. Wait for Retry-After seconds.
export_rate_limit_exceeded429More than 10 exports in the hour on this account.
dm_paused429X limits the account's DMs for now. Retry-After says when they start again.
dm_rate_limited429More than 10 DMs in the minute from this account.
dm_daily_limit429300 DMs today in UTC from this account, or X's own daily quota for it.
assistant_rate_limited429More than 6 messages to Julien AI in the minute from this X account, or 150 in the hour for its owner, the app's chat included.
assistant_daily_limit429100 messages to Julien AI today in UTC from this X account.
passcode_rate_limited429More than 5 X Chat passcode tries in the hour on this account. X counts every try.
internal_error500An unexpected error on our side. The request_id helps us find it.
request_timeout500The request took too long. Retry it, with the same Idempotency-Key if it changes data.
not_implemented501This endpoint is not available yet.
upstream_unavailable502X or a Gemlead service did not answer. Nothing changed, try again in a minute.

Handle errors

  • 400, 401, 403 and 404 never succeed as they are. Fix the request before sending it again.
  • 409 with idempotency_key_in_use succeeds a second later. Retry with the same Idempotency-Key.
  • 429 succeeds after Retry-After seconds. See Rate limits.
  • 500 can be retried after a short wait. Send the same Idempotency-Key for requests that change data, so nothing happens twice.
  • Log the request_id of every error, it lets us find the request in seconds.