Open in
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 the organization's name or reporting settings |
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",
"timezone": "America/Los_Angeles",
"business_hours": {
"mon": [{"start": "09:00", "end": "17:00"}]
},
"excluded_numbers": ["+14155550199"],
"max_concurrent_calls": 20,
"min_seconds_between_calls_to_same_number": 10,
"new_agent_max_call_duration_seconds": 3600,
"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) |
timezone | string | IANA time zone (up to 64 characters) for call-report business hours. "" means UTC |
business_hours | object | Weekly schedule keyed by mon … sun; each day holds at most four {start, end} windows in 24-hour HH:MM, end later than start. {} means no after-hours split |
excluded_numbers | array | The organization's own test numbers (up to 50, E.164). Calls from or to them are left out of report counts and Client Portals |
max_concurrent_calls | integer | Read-only. Most calls this organization can have in progress at once, across inbound, outbound, web and test calls. Default 20. See Call limits |
min_seconds_between_calls_to_same_number | integer | Read-only. Minimum seconds between outbound calls from this organization to the same number. Default 10; 0 means no spacing. See Call limits |
new_agent_max_call_duration_seconds | integer | null | Read-only. The max_call_duration_seconds a new agent starts with when you create it without one: 3600 (one hour) unless ThunderPhone set another value for your organization; null means new agents have no per-agent limit |
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.
Owners and admins can send name, timezone, business_hours and
excluded_numbers; see Organization settings
for an example.
Delete organization
curl -X DELETE https://api.thunderphone.com/v1/orgs/42/ \
-H "Authorization: Token YOUR_SESSION_TOKEN"resp = requests.delete(
f"https://api.thunderphone.com/v1/orgs/{org_id}/",
headers={"Authorization": "Token YOUR_SESSION_TOKEN"},
)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, or the request used an API key |
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-V2 signature on inbound requests — see
Webhooks overview.