Errors

Every userGist API error follows the same envelope. Wire your client to it once and you're done.

Envelope

{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid request",
    "details": []
  }
}
FieldTypeNotes
successfalseDistinguishes errors from successful data envelopes.
error.codestringStable, upper snake case; safe to switch on.
error.messagestringHuman-readable, not localised.
error.detailsunknown?Code-specific structured details.

Status codes

HTTPCodeWhen
400VALIDATION_ERROR / BAD_REQUESTInvalid body, query, or operation.
401UNAUTHORIZEDMissing, invalid, expired, or revoked credential.
402SUBSCRIPTION_REQUIREDWorkspace or app cannot currently use the product.
403FORBIDDENCredential is valid but lacks role, scope, consent, or subject ownership.
404NOT_FOUNDResource does not exist or is not visible to the caller.
409CONFLICT or operation-specific codeThe request conflicts with current state.
429RATE_LIMITEDHonour Retry-After.
500INTERNAL_ERRORUnexpected server failure.
502UPSTREAM_ERROR or provider-specific codeAn upstream service failed.

Idempotency

Idempotency is explicit on operations where a duplicate would create user-visible state. Feature-request submissions, request comments, prompt responses, and transactional push accept an idempotencyKey in their JSON bodies. Reuse the same value when retrying the same logical operation.

POST /v1/apps/:appId/push/transactional
Content-Type: application/json
 
{ "campaignId": "…", "externalId": "user_42", "idempotencyKey": "order-1042-shipped" }

Retries

Retry 429, 500, 502, and network timeouts only when the operation is read-only or uses its documented idempotency field.

Use exponential backoff with jitter, capped at 30s. The SDKs do this automatically.

What's next