Organizations and projects

Set up Saanora for a team: who can do what, how to keep production and staging apart, and how to cap what each app can spend.

Everything in the console lives in an organization. An organization holds the credit, the rate limits and the people. Inside it, projects hold API keys, usage and spend limits. Every API key belongs to exactly one project, and the key alone decides which project and organization a request is billed to: nothing in the request body names either.

How it fits together

LevelBelongs toHolds
OrganizationIts membersPrepaid credit, the usage tier and its rate limits, members and roles, billing details, receipts and invoices, and its projects.
ProjectOne organizationAPI keys, usage history and an optional monthly spend limit.
API keyOne projectNothing of its own. Each request is recorded under the key's project and paid from the organization's credit.

Some things are shared by every project in an organization, others are kept apart:

Shared across the organizationSeparate for each project
Credit: one balance pays for every project.API keys: a key works only for its own project.
Rate limits: requests per minute, tokens per minute and questions per request come from the organization's tier.Usage: filter and export by project, with a breakdown by key.
Members and roles: a role applies to every project. There are no per-project roles.Monthly spend limit: optional, set per project.
Spend limits cap money, not traffic. A project's spend limit stops it from using more than its share of the credit. It does not reserve any of the rate limit. A busy staging project draws on the same requests and tokens per minute as production. See Rate limits.

Personal and team organizations

When you sign up, with email and password (confirmed with a 6-digit verification code) or with Google, Saanora creates a personal organization named after you, with one project called Default project. You are its owner. It is meant for you alone, so invite people into a team organization instead: in a personal organization the console offers no role changes, no member removal and no way to leave.

For shared work, create a team organization:

  1. Open Settings > Organization in the console, or choose + New organization at the bottom of the organization switcher.
  2. Enter a name (up to 80 characters) and choose Create.
  3. The console switches to the new organization. You are its owner, and it starts with a Default project, no credit and Tier 0, which is sign-up only: add credit to unlock Tier 1 and the API.

Each organization is fully separate. Credit, tier, billing details, invoices, projects, keys and members do not carry over between organizations, and the console has no way to move credit from one to another. You can own up to 10 organizations and be a member of any number.

Switching organizations and projects

The organization switcher at the top of the console sidebar lists every organization you belong to, marked Personal or Team with your role. Picking one switches the whole console (keys, usage, billing, members) to that organization and selects its first active project.

The project switcher in the top bar picks a project inside the current organization. It sets the project the console shows and the project new keys go to by default. Your selection is remembered in this browser.

The console selection never affects the API. A key always acts for the organization and project it was created in.

Organization settings

Under Settings > Organization you see the organization's name, its ID, your role and when it was created. Owners and admins can rename it. Quote the organization ID when you write to support@saanora.com.

Roles

Every member has exactly one role in an organization. Roles apply to the whole organization, across all projects. Give each person the least access they need.

ActionOwnerAdminDeveloperBillingReader
View projects, members, keys (name and prefix only), usage and limitsYesYesYesYesYes
Export usage as CSVYesYesYesYesYes
Create API keys in any projectYesYesYesNoNo
Revoke keys they createdYesYesYesNoNo
Revoke anyone's keysYesYesNoNoNo
Add credit, see payments, receipts, invoices and credit history, edit billing detailsYesYesNoYesNo
Create, rename and archive projects, set spend limitsYesYesNoNoNo
Invite members, revoke pending invites, remove membersYesYesNoNoNo
Rename the organizationYesYesNoNoNo
Change anyone's role, remove an ownerYesNoNoNoNo
Leave the organizationYesYesYesYesYes

Which role fits whom:

Keep two owners. If your only owner leaves the company, nobody can change roles. Promote a second trusted person to owner when you set up a team organization.

Changing roles and removing members

Owners change a member's role on the Members page: pick the new role next to their name and choose Update. Any role can be given, including owner. The change applies on the member's next page load. It does not touch keys: keys the member already created keep working, and they can still revoke them.

Owners and admins remove members with Remove; only an owner can remove another owner. Any member can leave a team organization with Leave, unless they are its last owner.

Removing a member does not revoke their keys. Keys belong to the project, not to the person who created them, so they keep working after that person leaves. Before you remove someone, check the Created by column on the API keys page and replace or revoke the keys they made: once they have left, their keys no longer show a creator. A revoked key stops working within 60 seconds.

Inviting people

Owners and admins invite people by email address:

  1. Open Members in the console, enter the person's email address and pick a role: admin, developer (the default), billing or reader. To make someone an owner, invite them with another role and promote them after they join.
  2. Let them know they have been invited.
  3. They sign in, or sign up, with exactly that address, with Google or with email and password. They join the organization the next time they open the console signed in with it.
  4. The organization appears in their organization switcher. Their own personal organization stays as it was.

Details worth knowing:

Projects

A project is a container for API keys. Use one per environment (Production, Staging, Development) or one per app or customer you want to track and cap separately. Each project has its own keys, usage and optional monthly spend limit, and shares the organization's credit and rate limits.

SettingWhoDetails
Create a projectOwner, adminProjects > New project. Names up to 80 characters. Up to 50 active projects per organization.
RenameOwner, adminEdit the name on the project's card and choose Save. Keys are not affected.
Monthly spend limitOwner, adminA dollar amount, or empty for no limit (the default). See below.
Create keysOwner, admin, developerOn API keys, pick the project. Key names up to 64 characters. Up to 100 active keys per organization, across all projects.
ArchiveOwner, adminRevokes every key in the project. See below.

Each project's card on the Projects page shows its number of active keys, its spend so far this month and its limit. Usage breaks spend down by project and by key, and its CSV export includes the project and key name for every request.

Monthly spend limits

A spend limit caps what one project can spend in a calendar month, measured in UTC. It resets at 00:00 UTC on the first of each month. Projects without a limit can spend until the organization's credit runs out.

The check happens before the model runs. Saanora adds the request's worst-case cost (the same amount it holds against your credit) to the project's spend so far this month. If the total would go over the limit, the request is refused with 429 project_spend_limit, nothing runs and nothing is charged. Because the check uses the worst case, a request close to the limit can be refused slightly early. Requests still running are not part of the check, so with many requests in parallel, spend can end slightly above the limit.

429 project_spend_limit
{
  "error": {
    "type": "rate_limit_error",
    "code": "project_spend_limit",
    "message": "this project reached its monthly spend limit; an owner or admin can raise it under Projects in the console",
    "param": null
  },
  "request_id": "req_6f1c0e9a5d2d8e7f3a5c1b90"
}

A request can be stopped at the project, organization or key level. Tell them apart by error.code:

ResponseScopeWhat happenedWho can fix it
429 project_spend_limitOne projectThe project reached its monthly spend limit.An owner or admin raises the limit, or wait for the next UTC month.
402 insufficient_creditWhole organizationThe credit cannot cover the request's worst-case cost.An owner, admin or billing member adds credit.
429 rate_limit_exceededWhole organizationRequests or tokens per minute for your tier are used up.Wait for Retry-After seconds. Higher tiers come with purchases over time.
401 invalid_api_keyOne keyThe key was revoked, its project was archived, or it is mistyped.An owner, admin or developer creates a new key.

Refused requests are never charged and do not count toward tokens per minute. The full list is in Errors.

Archiving a project

Owners and admins archive a project with Archive and revoke its keys on its card. Archiving:

An organization always keeps at least one active project, so the last one cannot be archived. Archiving cannot be undone from the console: to bring an app back, create a new project and new keys.

This setup keeps environments apart, makes leaked keys cheap to replace, and stops a test run from spending production's money.

  1. Create a team organization for the company, rather than using your personal one. Promote a second owner.
  2. Invite people with the least role they need: engineers as developers, leads as admins, finance as billing, everyone else as readers.
  3. Create one project per environment. Rename the Default project to Production, then add Staging and, if you want, Development.
  4. Create one key per service in each environment, named after the service, such as checkout-api or support-triage-worker. A leaked key can then be revoked without touching anything else, and Usage shows which service spent what.
  5. Set spend limits. Give Staging and Development low limits. Give Production a limit above your expected monthly peak, so a runaway loop is stopped before it drains the credit.
  6. Store each key in that environment's secrets, as an environment variable such as SAANORA_API_KEY. Never copy a production key into staging, a laptop or a repository.
ProjectKeysMonthly limit (example)
Productioncheckout-api, support-triage-workerAbove your expected peak, for example $500
Stagingcheckout-api, support-triage-worker, ci$25
DevelopmentOne per developer, such as dev-ana$10

The code is the same in every environment. Only the key changes, and the key decides which project pays:

.env (one per environment)
# Production secrets (key "checkout-api" in project Production)
SAANORA_API_KEY=sk_sa_...

# Staging secrets (key "checkout-api" in project Staging)
SAANORA_API_KEY=sk_sa_...

After deploying a key, run a quick check from that environment. Then use a client that tells a project-level stop apart from an organization-level one:

# 1. Check that this environment's key works. Lists the live models.
curl -sS https://api.saanora.com/v1/models \
  -H "Authorization: Bearer $SAANORA_API_KEY"

# 2. Make one small decision. It is billed to the key's project.
curl -sS https://api.saanora.com/v1/decisions \
  -H "Authorization: Bearer $SAANORA_API_KEY" \
  -H "Content-Type: application/json" \
  --max-time 120 \
  -d '{
    "model": "clara-1",
    "state": {"ticket": "I was charged twice for order 1182", "plan": "pro"},
    "questions": {
      "refund": {"type": "noul", "instructions": "Is the customer asking for a refund?"}
    }
  }'

Rotating a key without downtime

  1. Create a new key in the same project, with the same service name plus a suffix, such as checkout-api-2.
  2. Deploy it to the service's secrets and restart or redeploy the service.
  3. On API keys, wait until the old key's Last used time stops moving.
  4. Revoke the old key. It stops working within 60 seconds.

Keys are shown once when created and stored only as SHA-256 hashes, so a lost key cannot be recovered: rotate it instead. More in Authentication.

Sharing rate limits between environments

Rate limits belong to the organization, so staging traffic and production traffic share the same requests and tokens per minute. Before a load test in staging, check the x-ratelimit-remaining-requests and x-ratelimit-remaining-tokens headers on your production responses, keep the test short, and run it outside production's busy hours. Your tier and its limits are listed under Limits in the console and in Rate limits.

What is recorded

For every request Saanora stores the time, organization, project, key, model, mode, status, number of questions, input tokens, latency, cost and request ID. Every member can see this in Usage and export it as CSV. The record you send in state and your questions are processed in memory and never written to the database. See Data handling and Billing and credit.