Sources
A source is one inbound pipe into an app: each app is created with one first-party api source and may hold several, each with a name unique among the app’s active sources, while a clerk source is one per app. A deactivated source refuses everything naming it until it is activated again. Sources are created and listed under their parent app, and these routes address one by its own id. All writes are attributed to the source’s parent app. The signing secret in config is write-only and never present in any response: configured reports whether one is stored. The webhook receiver is public: the caller’s signature is the authorization, and the route answers with plain text rather than the envelope. See the Apps and sources guide.
GET /v1/sources/{id}
Section titled “GET /v1/sources/{id}”Fetch one source
Auth: Session token.
Response 200
{ "data": { "id": "string", "orgId": "string", "appId": "string", "kind": "api", "name": "string", "config": "string", "lastReceivedAt": "2026-01-15T09:30:00.000Z", "createdAt": "2026-01-15T09:30:00.000Z", "updatedAt": "2026-01-15T09:30:00.000Z", "deactivatedAt": "2026-01-15T09:30:00.000Z", "status": "active", "configured": true }, "meta": { "requestId": "string", "nextCursor": "string", "hasMore": true, "warnings": [ { "code": "string", "message": "string", "suggestion": "string" } ] }}| Field | Type | Required | Constraints |
|---|---|---|---|
data |
object | yes | |
data.id |
string | yes | |
data.orgId |
string | yes | |
data.appId |
string | yes | |
data.kind |
“api” | “clerk” | yes | |
data.name |
string | yes | |
data.config |
string | number | boolean | null | record<string, any> | any[] | yes | |
data.lastReceivedAt |
string (date-time) | null | yes | |
data.createdAt |
string (date-time) | yes | |
data.updatedAt |
string (date-time) | yes | |
data.deactivatedAt |
string (date-time) | null | yes | |
data.status |
“active” | “inactive” | yes | |
data.configured |
boolean | yes | |
meta |
object | no | |
meta.requestId |
string | no | |
meta.nextCursor |
string | null | no | |
meta.hasMore |
boolean | no | |
meta.warnings |
object[] | no | |
meta.warnings[] |
object | no | |
meta.warnings[].code |
string | yes | |
meta.warnings[].message |
string | yes | |
meta.warnings[].suggestion |
string | no |
Errors follow the shared envelope and code table.
PATCH /v1/sources/{id}
Section titled “PATCH /v1/sources/{id}”Rename a source, or set or rotate its config
Admin only. The name must be unique among the app’s active sources. A clerk source is named after its kind, so it takes a config and no name.
Auth: Session token.
Request body
{ "data": { "name": "string", "config": {} }}| Field | Type | Required | Constraints |
|---|---|---|---|
data |
object | yes | |
data.name |
string | no | length 1–100 |
data.config |
any | no |
Response 200
{ "data": { "id": "string", "orgId": "string", "appId": "string", "kind": "api", "name": "string", "config": "string", "lastReceivedAt": "2026-01-15T09:30:00.000Z", "createdAt": "2026-01-15T09:30:00.000Z", "updatedAt": "2026-01-15T09:30:00.000Z", "deactivatedAt": "2026-01-15T09:30:00.000Z", "status": "active", "configured": true }, "meta": { "requestId": "string", "nextCursor": "string", "hasMore": true, "warnings": [ { "code": "string", "message": "string", "suggestion": "string" } ] }}| Field | Type | Required | Constraints |
|---|---|---|---|
data |
object | yes | |
data.id |
string | yes | |
data.orgId |
string | yes | |
data.appId |
string | yes | |
data.kind |
“api” | “clerk” | yes | |
data.name |
string | yes | |
data.config |
string | number | boolean | null | record<string, any> | any[] | yes | |
data.lastReceivedAt |
string (date-time) | null | yes | |
data.createdAt |
string (date-time) | yes | |
data.updatedAt |
string (date-time) | yes | |
data.deactivatedAt |
string (date-time) | null | yes | |
data.status |
“active” | “inactive” | yes | |
data.configured |
boolean | yes | |
meta |
object | no | |
meta.requestId |
string | no | |
meta.nextCursor |
string | null | no | |
meta.hasMore |
boolean | no | |
meta.warnings |
object[] | no | |
meta.warnings[] |
object | no | |
meta.warnings[].code |
string | yes | |
meta.warnings[].message |
string | yes | |
meta.warnings[].suggestion |
string | no |
Errors follow the shared envelope and code table.
POST /v1/sources/{id}/deactivate
Section titled “POST /v1/sources/{id}/deactivate”Deactivate a source
Admin only. Calls and webhook deliveries naming this source are refused from now on, until it is activated again. Its id stays the same, and everything it already sent keeps pointing at it.
Auth: Session token.
Response 200
{ "data": { "id": "string", "orgId": "string", "appId": "string", "kind": "api", "name": "string", "config": "string", "lastReceivedAt": "2026-01-15T09:30:00.000Z", "createdAt": "2026-01-15T09:30:00.000Z", "updatedAt": "2026-01-15T09:30:00.000Z", "deactivatedAt": "2026-01-15T09:30:00.000Z", "status": "active", "configured": true }, "meta": { "requestId": "string", "nextCursor": "string", "hasMore": true, "warnings": [ { "code": "string", "message": "string", "suggestion": "string" } ] }}| Field | Type | Required | Constraints |
|---|---|---|---|
data |
object | yes | |
data.id |
string | yes | |
data.orgId |
string | yes | |
data.appId |
string | yes | |
data.kind |
“api” | “clerk” | yes | |
data.name |
string | yes | |
data.config |
string | number | boolean | null | record<string, any> | any[] | yes | |
data.lastReceivedAt |
string (date-time) | null | yes | |
data.createdAt |
string (date-time) | yes | |
data.updatedAt |
string (date-time) | yes | |
data.deactivatedAt |
string (date-time) | null | yes | |
data.status |
“active” | “inactive” | yes | |
data.configured |
boolean | yes | |
meta |
object | no | |
meta.requestId |
string | no | |
meta.nextCursor |
string | null | no | |
meta.hasMore |
boolean | no | |
meta.warnings |
object[] | no | |
meta.warnings[] |
object | no | |
meta.warnings[].code |
string | yes | |
meta.warnings[].message |
string | yes | |
meta.warnings[].suggestion |
string | no |
Errors follow the shared envelope and code table.
POST /v1/sources/{id}/activate
Section titled “POST /v1/sources/{id}/activate”Activate a source
Admin only. Calls and webhook deliveries naming this source are accepted again. Refused when another active source on the app holds its name, or, for a clerk source, when the app already has an active one.
Auth: Session token.
Response 200
{ "data": { "id": "string", "orgId": "string", "appId": "string", "kind": "api", "name": "string", "config": "string", "lastReceivedAt": "2026-01-15T09:30:00.000Z", "createdAt": "2026-01-15T09:30:00.000Z", "updatedAt": "2026-01-15T09:30:00.000Z", "deactivatedAt": "2026-01-15T09:30:00.000Z", "status": "active", "configured": true }, "meta": { "requestId": "string", "nextCursor": "string", "hasMore": true, "warnings": [ { "code": "string", "message": "string", "suggestion": "string" } ] }}| Field | Type | Required | Constraints |
|---|---|---|---|
data |
object | yes | |
data.id |
string | yes | |
data.orgId |
string | yes | |
data.appId |
string | yes | |
data.kind |
“api” | “clerk” | yes | |
data.name |
string | yes | |
data.config |
string | number | boolean | null | record<string, any> | any[] | yes | |
data.lastReceivedAt |
string (date-time) | null | yes | |
data.createdAt |
string (date-time) | yes | |
data.updatedAt |
string (date-time) | yes | |
data.deactivatedAt |
string (date-time) | null | yes | |
data.status |
“active” | “inactive” | yes | |
data.configured |
boolean | yes | |
meta |
object | no | |
meta.requestId |
string | no | |
meta.nextCursor |
string | null | no | |
meta.hasMore |
boolean | no | |
meta.warnings |
object[] | no | |
meta.warnings[] |
object | no | |
meta.warnings[].code |
string | yes | |
meta.warnings[].message |
string | yes | |
meta.warnings[].suggestion |
string | no |
Errors follow the shared envelope and code table.
POST /v1/sources/{sourceId}/webhook
Section titled “POST /v1/sources/{sourceId}/webhook”Source webhook receiver (public)
Auth: None: verifies the caller’s own signature/token.
Errors follow the shared envelope and code table.