Skip to main content

Error classification

Always classify errors by HTTP status code first. The response body provides additional context but should not be used as the primary decision point.
StatusKindMeaningRetryable?
400ValidationRequest body or query parameters failed validationNo — fix the request
401AuthMissing, expired, or invalid bearer tokenNo — re-authenticate
403ForbiddenValid token but insufficient permissionsNo — check your application scope
404Not foundResource doesn’t exist or isn’t visible to your applicationNo
409ConflictConcurrent modification, duplicate key, or consumed OTPNo — check state and retry if appropriate
422ValidationBody parsed but semantics are invalidNo — fix the request
429Rate limitedToo many requestsYes — back off and retry
5xxServer errorServer or upstream failureYes — retry idempotent requests with backoff

Error response shape

Error responses follow the same standard envelope as success responses, with data set to null:
{
  "data": null,
  "status": 422,
  "message": "missing_field: amount must be greater than 0"
}
FieldDescription
dataAlways null for errors
statusThe HTTP status code — matches the status on the wire
message"code: description" — the code prefix is the stable, machine-readable error identifier; the description is a human-readable explanation
The X-Request-Id header is always present on error responses. Include it in support tickets.

Handling errors in code

import "github.com/ZeamMoney/zeam-sdk-go"

result, err := client.Business().ListAssociations(ctx, session)
if err != nil {
    var sdkErr *zeam.Error
    if errors.As(err, &sdkErr) {
        switch {
        case errors.Is(err, zeam.KindAuth):
            // Re-authenticate
        case errors.Is(err, zeam.KindTransient):
            // Retry with backoff
        case errors.Is(err, zeam.KindValidation):
            // Fix the request
        }
        fmt.Printf("Request ID: %s\n", sdkErr.RequestID)
    }
}

Request IDs

Every response (including errors) includes an X-Request-Id header. Always capture and log this value:
  • Include it in error logs for debugging
  • Surface it in user-facing error messages
  • Send it to Zeam support when filing a ticket

Retry strategy

For retryable errors (429, 5xx):
  1. Read the Retry-After header if present
  2. Use exponential backoff with jitter (e.g., 1s, 2s, 4s, 8s)
  3. Set a maximum retry count (e.g., 3-5 attempts)
  4. Only retry idempotent requests (GET, PUT, DELETE) automatically
  5. For non-idempotent POST requests, check the response or use an idempotency key before retrying