Skip to content
Cowliss is in beta: features and pricing may change.

Partner

A partner is a business that sells Cowliss inside its own product, one organization per customer, and the customer never signs in. These routes take a partner key (Authorization: Bearer cpk_...), issued by arrangement, and accept nothing else; every other route refuses a partner key. create returns an org:admin pipeline key once, and from then on the partner talks to that organization with it on the ordinary routes (apps, sources, keys, sending domains, automations, broadcasts, the billing summary): in an organization a partner created, that key acts as org:admin everywhere a signed-in admin would, because nobody can sign in. An organization the partner did not create is a 404 on every route here. Plan, overage, suspension and purge are the partner’s to call in whatever order its own lifecycle needs; Cowliss enforces none of that ordering. See the Partners guide.

Create an organization for a customer

Creates the organization with nobody in it, records the partner on it, and mints one org:admin pipeline key for it. The key is in this response and nowhere else; store it. A second create with the same externalId is allowed: the partner decides what one customer maps to.

Auth: Session token.

Request body

{
"data": {
"name": "string",
"slug": "string",
"externalId": "string"
}
}
Field Type Required Constraints
data object yes
data.name string yes length 1–100
data.slug string no length 1–100
data.externalId string no length 1–200

Response 201

{
"data": {
"orgId": "string",
"slug": "string",
"pipelineKey": "string"
},
"meta": {
"requestId": "string",
"nextCursor": "string",
"hasMore": true,
"warnings": [
{
"code": "string",
"message": "string",
"suggestion": "string"
}
]
}
}
Field Type Required Constraints
data object yes
data.orgId string yes
data.slug string yes
data.pipelineKey string 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.

Read an organization the partner created

Auth: Session token.

Response 200

{
"data": {
"orgId": "string",
"slug": "string",
"name": "string",
"externalId": "string",
"plan": "free",
"overageAllowed": true,
"status": "active",
"createdAt": "2026-01-15T09:30:00.000Z"
},
"meta": {
"requestId": "string",
"nextCursor": "string",
"hasMore": true,
"warnings": [
{
"code": "string",
"message": "string",
"suggestion": "string"
}
]
}
}
Field Type Required Constraints
data object yes
data.orgId string yes
data.slug string | null yes
data.name string | null yes
data.externalId string | null yes
data.plan “free” | “plus” yes
data.overageAllowed boolean yes
data.status “active” | “suspended” yes
data.createdAt string (date-time) 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.

Set the organization’s plan and whether overage is allowed

The plan set here wins over any subscription. With overageAllowed, usage past the included amount is counted (see overageMicros on the billing summary) and never refused, for the partner to bill through its own channel. Included usage, app and sending-domain limits per plan are unchanged.

Auth: Session token.

Request body

{
"data": {
"plan": "free",
"overageAllowed": true
}
}
Field Type Required Constraints
data object yes
data.plan “free” | “plus” yes
data.overageAllowed boolean yes

Response 200

{
"data": {
"orgId": "string",
"slug": "string",
"name": "string",
"externalId": "string",
"plan": "free",
"overageAllowed": true,
"status": "active",
"createdAt": "2026-01-15T09:30:00.000Z"
},
"meta": {
"requestId": "string",
"nextCursor": "string",
"hasMore": true,
"warnings": [
{
"code": "string",
"message": "string",
"suggestion": "string"
}
]
}
}
Field Type Required Constraints
data object yes
data.orgId string yes
data.slug string | null yes
data.name string | null yes
data.externalId string | null yes
data.plan “free” | “plus” yes
data.overageAllowed boolean yes
data.status “active” | “suspended” yes
data.createdAt string (date-time) 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.

Suspend the organization

Ingestion refuses, no automation starts a run (runs in flight finish with their sends skipped), nothing is sent, and no broadcast can be scheduled. Data is kept. Already suspended is a no-op.

Auth: Session token.

Response 200

{
"data": {
"orgId": "string",
"slug": "string",
"name": "string",
"externalId": "string",
"plan": "free",
"overageAllowed": true,
"status": "active",
"createdAt": "2026-01-15T09:30:00.000Z"
},
"meta": {
"requestId": "string",
"nextCursor": "string",
"hasMore": true,
"warnings": [
{
"code": "string",
"message": "string",
"suggestion": "string"
}
]
}
}
Field Type Required Constraints
data object yes
data.orgId string yes
data.slug string | null yes
data.name string | null yes
data.externalId string | null yes
data.plan “free” | “plus” yes
data.overageAllowed boolean yes
data.status “active” | “suspended” yes
data.createdAt string (date-time) 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.

Restore a suspended organization

Clears the suspension; automations that are on trigger again. Not suspended is a no-op.

Auth: Session token.

Response 200

{
"data": {
"orgId": "string",
"slug": "string",
"name": "string",
"externalId": "string",
"plan": "free",
"overageAllowed": true,
"status": "active",
"createdAt": "2026-01-15T09:30:00.000Z"
},
"meta": {
"requestId": "string",
"nextCursor": "string",
"hasMore": true,
"warnings": [
{
"code": "string",
"message": "string",
"suggestion": "string"
}
]
}
}
Field Type Required Constraints
data object yes
data.orgId string yes
data.slug string | null yes
data.name string | null yes
data.externalId string | null yes
data.plan “free” | “plus” yes
data.overageAllowed boolean yes
data.status “active” | “suspended” yes
data.createdAt string (date-time) 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.

Delete the organization and everything in it

Starts the purge and returns at once: every run is cancelled, every row and event removed, sending domains released, keys revoked, and the organization itself deleted last. Irreversible. A second call while it runs, or after it finished, answers the same.

Auth: Session token.

Response 202

{
"data": {
"workflowId": "string"
},
"meta": {
"requestId": "string",
"nextCursor": "string",
"hasMore": true,
"warnings": [
{
"code": "string",
"message": "string",
"suggestion": "string"
}
]
}
}
Field Type Required Constraints
data object yes
data.workflowId string 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.