Skip to main content

Base URLs

Credential model

There are no separate live and test keys: every key belongs to one organization. Send server credentials as a Bearer token:
The publishable-key boundary is unconditional: customer reads and mutations return HTTP 403 even if a browser supplies an arbitrary customer ID. Use an authenticated merchant backend for checkout, invoices, subscription status, cancellation, top-ups, entitlements, and credits. That backend derives the Nozle customer from the logged-in user or team and calls Nozle with a least-privilege sk_.

Key permissions

A secret key can be limited to read or write access per resource, for example credit_system:read or plan:write. A key without the permission a route needs gets 403.
  • Permissions restrict a key only when your organization has the API key permissions feature. On other organizations, creating a key with permissions is refused with premium_integration_missing instead of storing permissions that would not apply. A key created without permissions has full access.
  • Rotating a key gives the new key the same permissions as the old one.
  • Plan transition policies have their own resource, plan_transition_policy. Keys that existed before it have the same access to it that they have to plan.
  • Check credit usage needs credit_system:read and Track and consume credits needs credit_system:write.
  • Set a key’s permissions in the dashboard under Developers > API keys, when you create a secret key or with Edit. The read and write picker shows only for secret keys on organizations with API key permissions. With API key permissions, a secret key with read and write on every resource is labelled Full access, and any other key Restricted with its grants, for example Restricted · plan: read. On other organizations, every secret key is labelled Full access (permissions not enforced on this plan). A publishable key is labelled Plan catalog · read only.

Engine routes

On organizations with API key permissions, these Engine routes check the key too. A key without the permission gets 403 with code: permission_denied and the message API key requires <resource>:<mode> permission. Organizations without API key permissions see no change. POST /analytics/snapshot and POST /onboarding/chat are internal to Nozle. They accept only Nozle’s internal service token, and a secret key gets 403 with internal service authentication required.

Browser access (CORS)

The publishable-key plan catalog, GET /plans and GET /plans/{code} on the Engine, answers CORS from any origin, so the React components can load plans on your own site. The catalog and its preflight return Access-Control-Allow-Origin: * and Access-Control-Allow-Methods: GET, OPTIONS, never Access-Control-Allow-Credentials. Every other route answers only the origins Nozle allows, so call them from your backend.
Never expose a secret or master key in client-side code. CORS and Origin headers do not authenticate a caller.

Public authentication endpoints

These are Core routes, for example https://api.nozle.app/core/api/v1/auth/send-otp. The Engine does not serve them.
  • POST /api/v1/auth/send-otp
  • POST /api/v1/auth/verify-otp
  • POST /api/v1/auth/signup
The signup code endpoints answer the same way for every email, so they do not reveal whether an email already has an account:
  • send-otp (email) answers 200 with {"success": true, "expiresIn": 300}. A new email receives a 6-digit code that is valid for 5 minutes; an email that already has an account receives a login email instead of a code. A second request for the same email within 60 seconds, or more than 10 requests from one IP address in an hour, answers 429 with retryAfter in seconds.
  • verify-otp (email, code) answers 200 with {"verified": true, "verificationToken": "..."}, which signup accepts for 10 minutes. A wrong, expired or missing code answers 401 with {"error": "invalid code"}. Before, an expired code answered 410: treat 401 as “invalid or expired, request a new code”. A code that is not 6 digits answers 400.
  • Each email has 5 attempts per 15 minutes, and each IP address 20 per hour. Requesting a new code does not reset the attempts. Past the limit, verify-otp answers 429 with too many attempts, try again later.
Get API keys from app.nozle.dev under Developers > API keys.