API surface. Platforms create and update merchant accounts over REST (Platforms that run shipping for many businesses need to create those businesses, let their people sign in with the identity provider they already use, and decide what each person may do. The spec keeps three concerns apart, so that any of them can change without touching the others:/v1/accounts,GET /v1/account). Identity providers, memberships, invitations, roles, API keys and account suspension are administered over GraphQL Interface.
An identity can hold memberships in many accounts. An account can trust several identity providers. Swapping a merchant from Google to Okta changes one
identity_provider, and no membership, role or shipment changes.
1. Account
Endpoints
2. Identity providers (SSO)
type may also be saml where the implementer offers it (capability accounts.saml). Everything downstream is the same, because a SAML assertion is mapped to the same identity shape.
GraphQL: identityProviders, identityProvider, createIdentityProvider, updateIdentityProvider, deleteIdentityProvider, verifyDomainIdentityProvider (GraphQL Interface mutation), and testIdentityProvider (GraphQL Interface mutation), which returns a sign-in URL for testing the configuration.
3. Memberships and roles
identityis the(issuer, subject)pair. It is never an email alone, because emails change and get reused.emailis informational.sourceisinvitation,jit,scim,idp_group, orapi.statusisinvited,active,suspended, orremoved.
Custom roles:
createRole (GraphQL Interface mutation) with { name, scopes[] }.
Endpoints:
4. API keys
createApiKey (GraphQL Interface mutation) returns secret once. Other endpoints: apiKeys (GraphQL Interface query), apiKey, updateApiKey (name, scopes, allowed_ips), rollApiKey (GraphQL Interface mutation) ({ expire_previous_in }), and deleteApiKey (GraphQL Interface mutation). system_metadata.created_by on every object references the key or membership that created it.
5. Seamless platform SSO (token exchange)
A platform whose users are already signed in, through the platform’s own IdP, should not make them sign in again to ship. The platform exchanges the user’s ID token for a scoped access token to one merchant account, using OAuth 2.0 Token Exchange (RFC 8693):- The platform’s IdP must be registered as an
identity_provideron the platform account. Child accounts inherit trust from their parent unless they configure their own. - The issued token’s scopes are the intersection of the requested scopes, the membership’s role, and the client app’s allowed scopes. It is never wider than any of them.
- Tokens last at most 1 hour and are not refreshable. The platform repeats the exchange.
- Each action is attributed to the person’s membership, not to the platform’s app. Audit trails name real people.
6. Events
account.created, account.updated, account.requirements_updated, account.suspended, account.closed, identity_provider.created, identity_provider.updated, identity_provider.domain_verified, membership.created, membership.updated, membership.removed, invitation.accepted, api_key.created, api_key.rolled, api_key.deleted. Platforms receive their children’s account events on their own endpoints.