Proteside Docs

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:

ValueMeaning
sentThe email had no account; an invitation was sent to set a password
existing_userThe email already had an account; it was added as the child's owner, without a notification email
failedThe invitation couldn't be sent; the child was created anyway
skippedThe 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 POST and PATCH: {"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"
SituationResponse
Token without orgs:manage403 insufficient_scope
org_id isn't a direct child of the token's organization404 not_found
org_id not in UUID format400 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.

Next steps

On this page