# Companies and apps

URL: https://bridge.wekoya.tech/docs/companies
Updated: 2026-11-08

> A company has its own wallet, members with roles (owner, admin, member, viewer), and keys. A person's key or signed-in session acts for a company they are…

A company has its own wallet, members with roles (owner, admin, member, viewer), and keys. A person's key or signed-in session acts for a company they are in when the request sends `X-Wekoya-Org: <company id>`. A company the person is not in, or one that is suspended, quietly becomes their own account instead, so a screen holding an old company id still works.

#### Acting for exactly one company
When the person's own wallet must never be charged instead (a service billing a workspace), also send `X-Wekoya-Org-Strict: 1`. The request then acts for exactly that company, or is refused with 403 `not_a_member` and nothing is done.

#### Keys the company owns
A company key stops when the person who made it leaves. For a key that runs the company's own product, an admin makes it with `"owned_by": "organization"` on `POST /v1/keys`: it keeps working when they leave, acting for the company's owner. It can have the `chat`, `models` and `usage` scopes only. Removing a member answers with `company_keys_kept`, the number of such keys they made; revoke any they may still hold a copy of.

#### App budgets
An app is the `app_id` on its keys or, for a request made with a person's session, the `X-Bridge-App: <app id>` header (a key's own label wins). Cap what an app may spend a month with `PUT /v1/app-budgets/<app id>` and `{ "monthly_limit_minor": 500000 }` (in kobo; `null` stops capping). Everything the app spends counts, requests and charges alike, including requests still running. Over it, a request is refused with 402 `app_budget_exceeded`. `GET /v1/app-budgets` lists every app with its month so far. Setting a budget needs an owner or admin.
What one app spent, from Bridge's ledger, to check against your own records: `GET /v1/apps/<app id>/usage?from=2026-10-01&to=2026-10-31&group_by=day` (`group_by` is `day`, `model` or `end_user`; the last 30 days by default, a year at most, UTC days). It counts every request the app made, streams cut short included at what they were billed, and the charges it captured. Reading it needs the `usage` scope with a key.

#### Members

- `GET /v1/organizations/<id>/members/<user id>`: one person's role, for anyone in the company; 404 when they are not in it.
- `GET /v1/whoami?include=organizations` lists the companies the caller is in and their role in each; `include=email` adds their confirmed email, to a signed-in session only.
- `POST /v1/invites/<id>/decline` declines an invitation addressed to you.
- Membership changes are sent as [webhooks](https://bridge.wekoya.tech/docs/webhooks): `organization.member.added`, `.removed` and so on.
- `DELETE /v1/organizations/<id>` with `{ "confirm": "<company name>" }` deletes a company: only its owner, signed in, once its wallet is empty. Its members, keys and invitations go; its records stay.
