MSP Pentesting Logo
Beta · early access

MSPP Provisioning API — /api/v1

Status: Beta — endpoints and payloads may change. Contact us for early access.

Programmatic API for partners (distributors, resellers/MSPs) to provision org trees, mint keys, launch pentests, and pull results.


Conventions


Org tree

A general tree of typed nodes: platform → distributor → reseller → tenant. Every node carries a materialized path[] (root→self).

POST /orgs

Create a node anywhere in the tree.

// request
{
  "type": "reseller",                 // distributor | reseller | tenant
  "parentOrgId": "org_distributor",
  "name": "Acme MSP",
  "slug": "acme",                     // optional; used for portal subdomain
  "tierId": "tier_pro",               // optional; inherited from ancestor if omitted
  "branding": { "logoUrl": "...", "primaryColor": "#0b5" },  // optional; inherited if omitted
  "billing": { "mode": "inherited" }  // consolidated | direct | inherited
}
// 201
{ "id": "org_acme", "type": "reseller", "parentOrgId": "org_distributor",
  "path": ["org_platform","org_distributor","org_acme"], "status": "active" }

GET /orgs/{id} · GET /orgs/{id}/children · GET /orgs?subtreeOf={id}

Fetch a node, its direct children, or the whole subtree.

PATCH /orgs/{id}

Update name, status (active|suspended), tierId, branding, billing.


Quota & allocations

A pool lives on the purchasing node (usually the distributor), denominated in per-SKU buckets (ai_pentest, external, internal, manual, …). Draw-down is shared across the subtree; child caps are optional ceilings.

PUT /orgs/{id}/quota (pool-holding node)

{ "purchased": { "ai_pentest": 200, "external": 50 },
  "replenish": "monthly",            // monthly | one_time
  "policy": { "ai_pentest": "soft", "external": "hard" } }  // soft = allow overage & bill it

PUT /orgs/{id}/caps (child node)

{ "caps": { "ai_pentest": 40 }, "policy": { "ai_pentest": "hard" } }

GET /orgs/{id}/quota

Current pool state for the subtree.

{ "purchased": { "ai_pentest": 200 }, "reserved": { "ai_pentest": 5 },
  "consumed": { "ai_pentest": 30 }, "available": { "ai_pentest": 165 } }

API keys

POST /orgs/{id}/api-keys

Mint a scoped key. The full secret is returned once; only a SHA-256 hash + prefix are stored.

// request
{ "name": "Partner provisioning", "scopes": ["orgs:write","pentests:write","usage:read"] }
// 201
{ "id": "key_123", "prefix": "mspp_live_a1b2", "secret": "mspp_live_a1b2c3…", "orgId": "org_distributor" }

GET /orgs/{id}/api-keys · DELETE /api-keys/{keyId}

List (prefix + metadata only) / revoke.


Pentests

POST /pentests

Launch. Runs a walk-up entitlement check (tier capability + pool/cap), reserves units, and enqueues the job.

// request
{ "tenantId": "org_client_x",
  "scanType": "ai_pentest",          // maps to a SKU
  "targets": ["example.com", "10.0.0.0/24"],
  "webhookUrl": "https://partner.example/hooks/mspp",  // optional per-launch override
  "metadata": { "poNumber": "PO-4471" } }
// 202 (queued)
{ "id": "pt_789", "status": "queued", "tenantId": "org_client_x",
  "sku": "ai_pentest", "units": 2, "reserved": true, "createdAt": "2026-07-13T…Z" }
// 402 if hard-blocked
{ "error": { "code": "quota_exhausted", "message": "ai_pentest pool exhausted", "details": { "available": 0 } } }

GET /pentests?tenantId=&resellerId=&status= · GET /pentests/{id}

List (scoped to the key's subtree) / fetch status + findings summary.

GET /pentests/{id}/report?format=pdf|json

Branded report artifact (white-label cover applied from the org's resolved branding).


Usage & reporting

GET /orgs/{id}/usage?from=&to=&groupBy=sku|child|day

Rollup over the subtree from the append-only usage ledger — the same data consolidated invoices are computed from.

{ "from": "2026-07-01", "to": "2026-07-31",
  "totals": { "ai_pentest": 30, "external": 12 },
  "overage": { "ai_pentest": 0 },
  "byChild": [ { "orgId": "org_acme", "ai_pentest": 18 } ] }

Outbound webhooks

Register endpoints and MSPP POSTs signed events (X-MSPP-Signature, HMAC-SHA256, with retry).

POST /orgs/{id}/webhooks

{ "url": "https://partner.example/hooks/mspp",
  "events": ["pentest.completed","report.ready","quota.soft_exceeded"] }

Event types: pentest.queued · pentest.completed · pentest.failed · report.ready · quota.soft_exceeded · quota.exhausted.

// example delivery
{ "type": "pentest.completed", "id": "evt_…", "createdAt": "…",
  "data": { "pentestId": "pt_789", "tenantId": "org_client_x", "sku": "ai_pentest",
            "findingsCount": 14, "reportUrl": "…" } }

Endpoint summary

Method & pathPurpose
POST /orgs · GET /orgs/{id} · GET /orgs/{id}/children · PATCH /orgs/{id}Manage org tree
PUT /orgs/{id}/quota · PUT /orgs/{id}/caps · GET /orgs/{id}/quotaPools & caps
POST /orgs/{id}/api-keys · GET … · DELETE /api-keys/{id}Scoped keys
POST /pentests · GET /pentests · GET /pentests/{id} · GET /pentests/{id}/reportLaunch & results
GET /orgs/{id}/usageConsumption reporting / billing source
POST /orgs/{id}/webhooksOutbound event subscriptions

Want partner access or an API key? Get in touch.