Docs
    GuidesAPI Reference
    Sign inCreate account
    Overview

    Getting started

    API keysQuickstart

    Integration

    Load your catalogTracking EventsIdentity StitchingPersonalisation

    Production

    Errors & troubleshootingRetries & rate limits

    Reference

    API ReferenceVersioningChangelog
    HomeDocumentationErrors & troubleshooting
    Previous
    Personalisation
    Next
    Retries & rate limits

    Skip the ML, Ship the Revenue

    Product

    • How It Works
    • Features
    • For Startups
    • For Developers

    Developers

    • Documentation

    Company

    • Contact

    © 2026 Lehnz, Inc. All rights reserved.

    Reference

    Errors & troubleshooting

    Every error response lehnz returns, the conditions that trigger it, what to do about it, and fixes for the most common integration issues.

    Response envelope

    All responses share the same shape:

    success-response.json
    {
      "success": true,
      "data": { ... },
      "message": "..."
    }
    error-response.json
    {
      "success": false,
      "message": "Human-readable summary",
      "data": null,
      "error": "Optional detail or array of field errors"
    }

    Check success, not just the HTTP status. message is safe to surface to users; error is for logs and debugging.

    Status codes

    StatusMeaningRetry?
    200OK: synchronous request succeedednone
    202Accepted: queued for async processingnone
    400Bad request: validation failure or malformed payloadNo (fix the request)
    401Unauthorized: credential missing, invalid, or expiredNo (fix auth)
    403Forbidden: wrong key type, insufficient role, or suspendedNo (use correct key/role)
    404Not found: resource does not exist or belongs to another tenantNo (verify ID)
    413Payload too large: file or batch exceeds limitsNo (split request)
    429Too many requests: rate limit exceededYes (with backoff)
    500Internal server errorYes (with backoff)

    Ingestion and auth endpoints return 400 for validation failures, not 422. The recommendation service is the exception: it returns 422 when a strategy is missing its required input (see Personalisation).

    400 Bad Request

    Missing field, wrong type, or schema mismatch. Validation errors include a per-field error array:

    validation-error.json
    {
      "success": false,
      "message": "Validation Failed",
      "error": [
        { "path": "email", "message": "Invalid email" },
        { "path": "password", "message": "String must contain at least 8 character(s)" }
      ]
    }
    TriggerWhereFix
    Missing required fieldsPOST /auth/register, /auth/loginProvide all required fields with valid types.
    Password shorter than 8 charactersPOST /auth/registerUse 8+ characters.
    Invalid email formatPOST /auth/register, /auth/loginEmail must match standard format.
    Inviting a user as OWNERPOST /organizations/:slug/membersInvite as ADMIN, DEVELOPER, or MEMBER. Ownership is exclusive to the org creator.
    API key name empty or over 50 charsPOST /organizations/:slug/api-keysProvide a name between 1 and 50 characters.
    Upsert payload not a valid object or arrayPOST /v1/ingest/items/upsert, /users/upsertBody must be a single record object or an array of records.
    Record missing primary keyPOST /v1/ingest/items/upsert, /users/upsertEvery record must include a non-empty primary key.

    401 Unauthorized

    Credentials are missing, invalid, or expired. Never retry a 401 with the same credentials.

    TriggerMessageFix
    Wrong email or passwordInvalid credentialsVerify the password. Retry loops trigger rate limits.
    Email not verifiedPlease verify your email address before logging in.Click the verification link from sign-up. Request a new one if expired.
    Verification token invalid or expiredInvalid or expired verification tokenTokens expire after 24 hours. Request a fresh email.
    X-API-KEY header missingMissing required X-API-KEY headerAdd the header. There is no Bearer prefix.
    Malformed API keyInvalid API Key formatKey must start with lehnz_pk_ or lehnz_sk_ and match the format from the dashboard.
    API key revokedInvalid API KeyGenerate a new pair from the dashboard. Old keys cannot be reactivated.

    403 Forbidden

    The credential is valid but lacks permission for this resource or action.

    TriggerMessageFix
    Account suspendedYour account has been suspendedContact support to discuss reinstatement.
    Secret key on a public endpointSecret keys are prohibited on public endpoints. Use a Publishable key (pk_).Switch to your publishable key for events and recommendations.
    Publishable key on a non-public pathPublishable keys are restricted to events and recommendations.Use a secret key for upsert and admin endpoints.
    Caller's role lacks permissionInsufficient permissions / ForbiddenAsk an OWNER or ADMIN to perform the action.
    Caller is not an active org memberForbiddenAccept any pending invitations first.

    404 Not Found

    The resource doesn't exist, or it belongs to a different organization. lehnz does not leak existence: a 404 looks the same whether the ID is invalid or belongs to another tenant.

    TriggerFix
    API key ID does not exist or belongs to another orgVerify the ID in the dashboard.
    User is not a member of the organizationInvite the user before changing their role or removing them.
    No pending invitation foundAn invitation was never sent or was already accepted.
    Authenticated user has no organizationUser must be invited to or own an organization first.

    429 Too Many Requests

    You hit a rate limit. Responses include RateLimit-* headers (draft-7) for computing the right backoff.

    ScopeLimitAffects
    Auth (per IP)10 requests / 15 minutes/auth/register, /auth/login
    Organization1 000 requests / 15 minutesAll authenticated API endpoints

    See Retries & rate limits for backoff strategies.

    500 Internal Server Error

    An unexpected server-side failure. Internal details are scrubbed before reaching the client.

    500-response.json
    {
      "success": false,
      "message": "An unexpected error occurred",
      "data": null,
      "error": null
    }

    500s are exceptional. Retry once with a short delay, then escalate. If you see them in volume, contact support with timestamps and any request IDs from your client logs.

    A defensive client

    Branch on success, log the error field, surface message to the user, and only retry 429 or 500.

    callLehnz.ts
    async function callLehnz(url: string, init?: RequestInit) {
      const res = await fetch(url, init);
      const body = await res.json();
    
      if (body.success) return body.data;
    
      console.error('lehnz error', { status: res.status, body });
    
      if (res.status === 429 || res.status >= 500) {
        throw new RetryableError(body.message);
      }
      throw new TerminalError(body.message);
    }

    Common issues

    Recommendations look generic or stale. Users with fewer than ~10 behavioral events get popularity-based fallback results. Quality improves as events accumulate. If you recently uploaded catalog items, allow a few minutes for async processing. Also check that items have status: "active" and that anonymous and authenticated sessions are stitched (see Identity stitching).

    Events not showing in the dashboard. A 202 Accepted means events are queued; they typically appear within seconds. If they never arrive, open the Network tab and check for failed POSTs to api.lehnz.com. Common causes: ad-blockers, a strict CSP, or the request being cancelled on page navigation (add keepalive: true). Browser-side calls require a publishable key (lehnz_pk_); secret keys return 403.

    "Invalid API Key" but the key looks right. Hidden whitespace from password managers can cause this: trim the value before sending. Also confirm the key hasn't been revoked in the dashboard, that you're sending it as X-API-KEY with no Bearer prefix, and that you haven't swapped a staging key into production (or vice versa).

    CORS errors in the browser. lehnz allows browser-origin calls to ingestion and recommendations endpoints with publishable (lehnz_pk_) keys. If you're seeing CORS failures: confirm you're using the publishable key (not the secret one) and that the URL is https://. Many reported CORS errors are actually auth failures misreported by the browser; inspect the Network tab for the real response body.

    CSV upload rejected. The first row must be column names. Save the file as UTF-8 (Latin-1 and other encodings produce malformed-CSV errors). Wrap fields containing commas in double quotes: "red, large". Avoid smart quotes from word processors; use a plain text editor or a database export tool.

    Still stuck? Contact support@lehnz.com with your organization slug, the request URL, the request payload (with secrets redacted), and the full response body. Including the timestamp helps correlate against server logs.

    What's next

    Retries & rate limits

    Backoff strategy, idempotency, batching guidance.

    API Reference

    Full endpoint reference, headers, schemas, and rate limits.