For partners
Provisioning clients
Create client orgs, put them on plans, register redirect URIs and, if you prefer, give each client its own key.
Provisioning uses the Partner API under /v1/partner/** with your partner key. No X-Tenant-Id header is needed there. It never returns a client's content, only counts and settings.
Plans
A plan sets an org's limits. Each limit is optional, and a limit left out means unlimited.
curl -X POST https://connect.social.wasparks.com/v1/partner/plans \
-H "Authorization: Bearer $WASPARKS_KEY" \
-H "Content-Type: application/json" \
-d '{
"code": "growth",
"name": "Growth",
"limits": { "social_accounts": 10, "posts_per_month": 500, "members": 5, "workspaces": 3 }
}'
await fetch("https://connect.social.wasparks.com/v1/partner/plans", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.WASPARKS_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({
code: "growth",
name: "Growth",
limits: { social_accounts: 10, posts_per_month: 500, members: 5, workspaces: 3 },
}),
});
import os, requests
requests.post(
"https://connect.social.wasparks.com/v1/partner/plans",
headers={"Authorization": f"Bearer {os.environ['WASPARKS_KEY']}"},
json={"code": "growth", "name": "Growth",
"limits": {"social_accounts": 10, "posts_per_month": 500, "members": 5, "workspaces": 3}},
)codeis how you refer to the plan from then on: lowercase letters, digits,-and_, unique among your plans. A code already in use returns409 invalid_state.GET /v1/partner/planslists your plans and the platform plans you may assign.PATCH /v1/partner/plans/{code}changes one.- Plans for your clients stay within what your agreement with WaSparks allows.
Orgs
One org per client business.
curl -X POST https://connect.social.wasparks.com/v1/partner/orgs \
-H "Authorization: Bearer $WASPARKS_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "Acme Coffee", "external_ref": "acme-001", "plan_code": "growth", "timezone": "Europe/Amsterdam"}'
const res = await fetch("https://connect.social.wasparks.com/v1/partner/orgs", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.WASPARKS_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({ name: "Acme Coffee", external_ref: "acme-001", plan_code: "growth", timezone: "Europe/Amsterdam" }),
});
const org = await res.json();
import os, requests
r = requests.post(
"https://connect.social.wasparks.com/v1/partner/orgs",
headers={"Authorization": f"Bearer {os.environ['WASPARKS_KEY']}"},
json={"name": "Acme Coffee", "external_ref": "acme-001", "plan_code": "growth", "timezone": "Europe/Amsterdam"},
)
org = r.json()| Field | Notes |
|---|---|
name |
The client's business name. Required. |
plan_code |
One of your plans, or a platform plan you may assign. Required. An unknown code is 400 validation_failed. |
external_ref |
Your own id for the client, unique among your orgs. It becomes the X-Tenant-Id value. A duplicate returns 409 invalid_state. |
timezone |
An IANA time zone such as Europe/Amsterdam. Defaults to UTC. |
Creating an org also creates its default workspace and sends org.created to your partner webhook.
What you see of an org is its id, name, external_ref, status, plan_code, timezone, created_at and two counts, connected_accounts and members. Never its accounts, content or tokens.
Manage orgs with:
GET /v1/partner/orgs(filters:status,external_ref,plan_code) andGET /v1/partner/orgs/{orgId}PATCH /v1/partner/orgs/{orgId}to change the name, plan, timezone orexternal_refPOST /v1/partner/orgs/{orgId}/suspendand…/resume. A suspended org's content calls return403 org_suspended, and its scheduled posts wait.POST /v1/partner/orgs/{orgId}/close. Closing is permanent: content calls return403 org_closedfrom then on.
Each change sends the matching org.* event.
Redirect URIs
Users return to your app after the platform's consent screen, at a redirect_uri you registered. Register once for all your orgs:
POST /v1/partner/redirect-uris
{ "uri": "https://app.example.com/social/connected" }The URI must be https and is matched exactly. GET /v1/partner/redirect-uris lists them and DELETE /v1/partner/redirect-uris/{redirectUriId} removes one. An org can also have its own list at /v1/connect/redirect-uris, which adds to yours. See Connect social accounts.
Org keys, as an alternative to X-Tenant-Id
In operator mode you do not need org keys. If you would rather give your software, or a client, a credential that can only reach one org, mint one:
POST /v1/partner/orgs/{orgId}/api-keys
{ "name": "Acme Coffee production", "permissions": ["accounts:read", "accounts:write", "media:write", "posts:read", "posts:write"] }The response contains the key in plain text once. After that only the key_prefix is shown. Give a key only the permissions the integration needs, and set expires_at if it should not live forever. List a key's metadata with GET /v1/partner/orgs/{orgId}/api-keys; revoke with DELETE /v1/partner/orgs/{orgId}/api-keys/{keyId}. Every key you mint is logged with the partner key that created it.
With an org key, drop X-Tenant-Id: the key already names its org.
Branding and custom domains
The Partner API also has /v1/partner/branding and /v1/partner/domains. They are for white-label use and are described in the API reference.
Next: Billing and usage