Organizations
List, create, update, and delete the organizations that own your agents, phone numbers, and billing, including the legacy single-URL webhook configuration.
Organizations are the top-level container for every ThunderPhone resource — agents, phone numbers, calls, billing, and keys. An API key is bound to exactly one organization; the endpoints on this page are the handful that let you enumerate or manage the org resource itself.
The dashboard lets a single user belong to multiple organizations and switch between them. The API treats your key's bound org as implicit on every other page in this reference — you do not need an org id in URLs for resource operations. See Authentication for the full story.
Endpoints
| Method | Path | Description |
|---|---|---|
GET | /v1/orgs/ | List organizations the caller belongs to |
POST | /v1/orgs/ | Create an organization |
GET | /v1/orgs/{id}/ | Retrieve a single organization |
PATCH | /v1/orgs/{id}/ | Update organization name |
DELETE | /v1/orgs/{id}/ | Delete the organization |
GET | /v1/webhook | Get the single-URL webhook (see note below) |
PUT / PATCH | /v1/webhook | Set the single-URL webhook |
Organization object
{
"id": 42,
"name": "Acme Operations",
"role": "owner",
"created_at": "2026-04-20T18:24:10.113Z",
"updated_at": "2026-04-20T18:24:10.113Z"
}| Field | Type | Description |
|---|---|---|
id | integer | Server-assigned organization id |
name | string | Display name |
role | string | null | On list responses, the caller's role in this org (owner, admin, member) |
created_at | timestamp | ISO 8601 in UTC |
updated_at | timestamp | ISO 8601 in UTC |
List organizations
Returns every organization the caller is a member of.
curl https://api.thunderphone.com/v1/orgs/ \
-H "Authorization: Bearer sk_live_YOUR_API_KEY"resp = requests.get(
"https://api.thunderphone.com/v1/orgs/",
headers={"Authorization": "Bearer sk_live_YOUR_API_KEY"},
)
orgs = resp.json()const orgs = await fetch("https://api.thunderphone.com/v1/orgs/", {
headers: { Authorization: `Bearer ${process.env.THUNDERPHONE_API_KEY}` },
}).then((r) => r.json());Response is a JSON array of Organization objects.
Create organization
curl -X POST https://api.thunderphone.com/v1/orgs/ \
-H "Authorization: Bearer sk_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "Acme Operations"}'resp = requests.post(
"https://api.thunderphone.com/v1/orgs/",
headers={"Authorization": "Bearer sk_live_YOUR_API_KEY"},
json={"name": "Acme Operations"},
)
org = resp.json()| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | 1–120 characters |
Returns 201 Created with the new Organization object.
The creator becomes the owner member automatically.
Get organization
curl https://api.thunderphone.com/v1/orgs/42/ \
-H "Authorization: Bearer sk_live_YOUR_API_KEY"resp = requests.get(
f"https://api.thunderphone.com/v1/orgs/{org_id}/",
headers={"Authorization": "Bearer sk_live_YOUR_API_KEY"},
)Returns 200 OK with an Organization object, or 404 if
the caller is not a member of the requested org.
Update organization
curl -X PATCH https://api.thunderphone.com/v1/orgs/42/ \
-H "Authorization: Bearer sk_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "Acme Ops"}'resp = requests.patch(
f"https://api.thunderphone.com/v1/orgs/{org_id}/",
headers={"Authorization": "Bearer sk_live_YOUR_API_KEY"},
json={"name": "Acme Ops"},
)Returns 200 OK with the updated Organization object.
Delete organization
curl -X DELETE https://api.thunderphone.com/v1/orgs/42/ \
-H "Authorization: Bearer sk_live_YOUR_API_KEY"resp = requests.delete(
f"https://api.thunderphone.com/v1/orgs/{org_id}/",
headers={"Authorization": "Bearer sk_live_YOUR_API_KEY"},
)Returns 204 No Content.
| Status | Condition |
|---|---|
204 | Deleted |
400 | Other members still present, or this is the caller's only org |
403 | Caller is not the owner |
Legacy single-URL webhook
Get webhook config
curl https://api.thunderphone.com/v1/webhook \
-H "Authorization: Bearer sk_live_YOUR_API_KEY"resp = requests.get(
"https://api.thunderphone.com/v1/webhook",
headers={"Authorization": "Bearer sk_live_YOUR_API_KEY"},
)Returns 200 OK with the webhook row, or 404 if the org has not
configured a webhook yet.
{
"url": "https://example.com/thunderphone-webhook",
"secret": "whsec_abc123...",
"created_at": "2026-04-20T18:24:10.113Z",
"updated_at": "2026-04-20T18:24:10.113Z"
}Set webhook URL
curl -X PUT https://api.thunderphone.com/v1/webhook \
-H "Authorization: Bearer sk_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com/thunderphone-webhook"}'resp = requests.put(
"https://api.thunderphone.com/v1/webhook",
headers={"Authorization": "Bearer sk_live_YOUR_API_KEY"},
json={"url": "https://example.com/thunderphone-webhook"},
)| Field | Type | Required | Description |
|---|---|---|---|
url | string | yes | HTTPS URL; http:// is allowed only for localhost during local dev |
The secret is generated server-side and rotated only when you
explicitly call PUT again. Store it in your secret manager and use it
to verify the X-ThunderPhone-Signature HMAC on inbound payloads — see
Webhooks overview.