Partners and child organizations
Create and manage your clients' organizations with a single token using org_id and the orgs:manage scope.
If you're an agency, e-commerce platform or payment gateway protecting the checkout of several clients, use the partner model: each client becomes a child organization of your organization, with separate stores, scripts, alerts and reports, and you operate all of them with the same token.
How it works
- Your (partner) organization can have multiple children. There's only one level: a child can't create children.
- Each child has its own owner, who receives an email invitation and uses the dashboard as usual.
- Your token still belongs to your organization. To act on a child, you specify which one with
org_id. - In the dashboard, members of the partner organization can view the children's data, but changes to the children are made through the API or by members of the child itself.
Before you start
Create a token in Settings → API with the orgs:manage scope and the scopes for the operations you'll perform on
the children (for example stores:write, scripts:review, webhooks:manage, usage:read). See
Tokens and scopes.
The partner organization needs a store of its own
The dashboard only opens for users who have at least one store. A partner organization with no stores never reaches Settings → API and can't issue the token. Register a store for your own organization (for example, your website) before you start.
Create a child organization
curl -s -X POST "https://app.proteside.com/api/v1/organizations" \
-H "Authorization: Bearer $PROTESIDE_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 8d1f4b2a-0c3e-4a5b-9d6f-1e2a3b4c5d6e" \
-d '{
"name": "My Store",
"owner_email": "you@mystore.com",
"plan": "growth"
}'{
"id": "11112222-3333-4444-8555-666677778888",
"name": "My Store",
"plan": "growth",
"billing_mode": "partner",
"parent_org_id": "7f3c1e2a-0b4d-4c8e-9f10-2a3b4c5d6e7f",
"owner_email": "you@mystore.com",
"partner_settings": {},
"created_at": "2026-10-06T12:05:00.000Z",
"owner_invite": "sent"
}Prop
Type
The owner_invite field tells you what happened with the owner:
| Value | Meaning |
|---|---|
sent | The email had no account; an invitation was sent to set a password |
existing_user | The email already had an account; it was added as the child's owner, without a notification email |
failed | The invitation couldn't be sent; the child was created anyway |
skipped | The invitation wasn't sent; the child was created anyway |
With billing_mode: "partner", the child starts out active: it has no trial period and no store limit, and the
on-demand PCI DSS report is available on any plan. The child also gets the default approval policies.
Scheduled reports depend on the plan
Even with billing_mode: "partner", the scheduled PCI DSS report (weekly or monthly) is only generated on plans
that include compliance. A child on the essential plan can download reports with GET /reports/pci, but doesn't
receive the scheduled one. Choose the child's plan accordingly.
Act on a child
Send the child's ID in org_id:
- in the query string, with any method:
GET /stores?org_id=11112222-…; - or in the JSON body, with
POSTandPATCH:{"org_id": "11112222-…", "domain": "mystore.com"}.
With GET and DELETE, always use the query string. Without org_id, the call acts on your own organization.
CHILD=11112222-3333-4444-8555-666677778888
curl -s "https://app.proteside.com/api/v1/alerts?org_id=$CHILD&status=open" \
-H "Authorization: Bearer $PROTESIDE_TOKEN"| Situation | Response |
|---|---|
Token without orgs:manage | 403 insufficient_scope |
org_id isn't a direct child of the token's organization | 404 not_found |
org_id not in UUID format | 400 invalid_request |
GET /organizations, POST /organizations and GET /organizations/{id}/usage ignore org_id: the first two always
act on the token's organization, and the usage endpoint uses the {id} in the path.
Everything you change in a child is recorded in its audit log with the author api:<token prefix>.
List children and track usage
curl -s "https://app.proteside.com/api/v1/organizations?limit=100" \
-H "Authorization: Bearer $PROTESIDE_TOKEN"
curl -s "https://app.proteside.com/api/v1/organizations/$CHILD/usage" \
-H "Authorization: Bearer $PROTESIDE_TOKEN"Usage always covers the last 7 months (the current one and the 6 before it), from most recent to oldest, with zeros for months with no usage. The counters are updated in real time:
{
"org_id": "11112222-3333-4444-8555-666677778888",
"months": [
{
"period_month": "2026-10-01",
"payment_pageviews": 18420,
"events": 91234,
"alerts": 12,
"synthetic_runs": 4,
"stores": [
{
"store_id": "0c1d2e3f-1111-4222-8333-444455556666",
"payment_pageviews": 18420,
"events": 91234,
"alerts": 12,
"synthetic_runs": 4
}
]
}
]
}The {id} can be your own organization or a child. This endpoint requires usage:read (not orgs:manage).
Shared rate limit
The 120-requests-per-minute limit applies to your organization (the token owner) and adds up the calls made on
all children. If you sync many clients, spread the calls out over time and respect Retry-After. See
Conventions.
Use a unique Idempotency-Key per child
The idempotency key applies to the organization that owns the token and doesn't take org_id into account. If you
use the same Idempotency-Key to create a store in child A and then in child B, the second call returns child A's
store and nothing is created in B. Generate a new UUID for each operation.
Webhooks in children
A child's events only go to the child's own channels. A webhook created in your organization doesn't receive alerts from the children's stores. Create a webhook in each child:
curl -s -X POST "https://app.proteside.com/api/v1/webhooks?org_id=$CHILD" \
-H "Authorization: Bearer $PROTESIDE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"url": "https://ops.parceiro.example/hooks/proteside", "min_severity": "medium"}'You can use the same URL for all children. To know which client each event came from, use the envelope's org_id.
Each webhook has its own secret, so keep each child's secret or send your own secret when creating it. Details in
Webhooks.
Limitations
- There are no endpoints to view, update or delete a specific child: only list (
GET /organizations) and create (POST /organizations). The plan and name chosen at creation can't be changed through the API. - You can't create tokens for a child through the API. The child's owner can create their own tokens in the dashboard.
- A suspended store (
DELETE /stores/{id}) can't be reactivated through the API.