Skip to main content
Connect to https://api.apostra.com/mcp/v3 with interactive OAuth or call https://api.apostra.com/api/v3 with an API key or an M2M application. The credential determines the home account, reachable accounts, and permissions; the URL does not select Buyer or Seller behavior.
  • Use MCP OAuth for interactive clients and human-authorized work. Its access tokens are bound to the MCP resource and are rejected by HTTP API routes.
  • Use HTTP API OAuth for a developer tool a person signs in to, such as a command-line tool or a local script. The person approves it in the browser, chooses one account, and the token works on /api/v3 only, for that account (see OAuth on the HTTP API).
  • Use a user API key for simple headless automation, stored in a secret manager and sent as Authorization: Bearer YOUR_API_KEY. A key acts as its owner and is bound to the organization selected when it was created.
  • Use an M2M application when your deployed backend requires the OAuth client_credentials flow. Request the token endpoint and resource indicator returned when you create the M2M application. Send the resulting token as a bearer credential to the HTTP API. MCP endpoints refuse M2M tokens; connect an MCP client with OAuth or an API key.
  • Grant only the permissions the integration needs. A visible tool may still refuse a write when the credential lacks the required permission.

Which credential each MCP endpoint accepts

An MCP OAuth token works only on the endpoint it was issued for (see OAuth resource binding). A Seller that sells through an ad platform also takes that platform’s credentials (see OAuth on a Seller endpoint). The sign-in session of the Apostra web app works in the web app and on the HTTP API. Every endpoint in the table refuses it with 401, however it is sent. The web app’s own tool calls to /mcp/<toolName> accept it only as the sign-in cookie the web app sets, and refuse it as a header. An agent that signs itself up through Agent Registration can use that credential on /mcp/v3 and on the HTTP API. Every other MCP endpoint, including /mcp, refuses it with 401. To reach another MCP endpoint, connect to it with OAuth or an API key.

Which credential each HTTP API route accepts

An HTTP API OAuth token is refused with 401 on every MCP endpoint and on every REST route outside /api/v3, and an MCP OAuth token is refused with 401 on /api/v3. Neither kind can stand in for the other. Most HTTP operations require one permission for every request. Accepting Terms, choosing payment terms, acting on the plan (plan, offerResponse, renewal) or changing the payer details (payer) with save_billing, and requesting or confirming payment authority with request_payment_authority and confirm_payment_authority all require interchange:write. The OpenAPI security entry for save_billing declares the minimum interchange:read permission, and x-interchange-invocation-permissions records a request-specific rule that an earlier request shape used; every request body the HTTP API accepts now is a write. Only a direct administrator of the organization can accept its Terms; Apostra staff never accept them on a customer’s behalf, even with a staff elevation. terms.canAccept on the billing read tells a caller whether it can accept them. The plan declarations need a direct administrator of the organization, or a Scope3 staff member holding an active staff elevation for it. A plan only records a request: a direct administrator of the billing organization must approve it on the Apostra site before it is accepted, and only a direct administrator may ask for it. A read-only mutation is rejected before a billing service runs.

Payment-authority status access

Reading payment-authority status is a read-scoped operation: call get with kind: "billing" and read paymentAuthority.status and paymentAuthority.expiresAt. A human caller must still be an account admin. A user API key, WorkOS M2M credential, or organization API key may make the same check with interchange:read when the credential is bound to the effective organization. The status fields report the latest handoff’s state and expiry. They do not return card details or the capture-link URL. Advertiser-scoped credentials cannot read it. When a child account inherits billing from a parent, a person must be a direct admin of that parent; a credential bound to the child is rejected at the parent boundary. This read access does not widen mutation access. Accepting Terms or requesting or confirming payment authority still requires interchange:write, the same credential-to-organization match, and the existing account safeguards. Call get_status after authentication to list the accounts you can reach and verify the readiness of the one you name. Send that accountId on every call; see Name the account on every call. Every authenticated Buyer and Seller Account can connect; individual operations still require the appropriate permissions and resource access. For an API key or M2M credential that can reach more than one account, name the account with accountId in the request. Apostra rejects an account outside the credential’s scope. accountId selects the account only; it does not grant access. The X-SCOPE3-CUSTOMER-ID header still works for now but is deprecated; see Name the account on every call. An agent should direct a person to Settings → API Access to create a user API key. It cannot retrieve an existing secret, and a long-lived credential must not pass through chat. Existing organization-owned keys remain supported during migration; they are not the default for a new integration.

Approving an MCP client

When an MCP client starts OAuth, Apostra signs you in and then asks you to approve or deny that client. This happens every time a client authorizes, including when you are already signed in. The screen shows:
  • the name the client registered (or that it gave none),
  • the address it returns you to after you decide,
  • the MCP resource it is asking to access, and
  • the account you are signed in as.
Approve only a connection you just started yourself. The client chooses its own name, so check the return address before you approve. Approve issues the authorization code and returns you to the client. Deny returns you to the client with the OAuth error access_denied and issues nothing. An approved client acts as you, with your permissions, until you disconnect it from Connected apps.

OAuth resource binding

OAuth discovery for v3 advertises https://api.apostra.com/mcp/v3 as the exact protected resource. MCP clients carry that URI through authorization, token exchange, and refresh. Apostra issues dedicated MCP access and refresh credentials for that resource; a v3 interactive credential is rejected on another MCP endpoint or on the HTTP API. Do not reuse an MCP access token for /api/v3/tools/*. To sign in to the HTTP API with OAuth, use its own resource. The protected-resource metadata document is available at https://api.apostra.com/.well-known/oauth-protected-resource/mcp/v3. Clients should follow the resource_metadata URL in the server’s WWW-Authenticate challenge instead of constructing it themselves.

OAuth on the HTTP API

https://api.apostra.com/api/v3 is a protected resource of its own, separate from the MCP endpoints. A tool a person signs in to uses it to call the HTTP API without an API key. Its metadata is at https://api.apostra.com/.well-known/oauth-protected-resource/api/v3. It names https://api.apostra.com/api/v3 as the resource, lists the three scopes below, and a 401 from /api/v3 points to it in WWW-Authenticate. Start the sign-in with resource=https://api.apostra.com/api/v3 and the same PKCE flow as any other agent, plus: The scopes are a ceiling. interchange:read allows reads, interchange:write allows writes, and interchange:admin allows administrative operations. A tool that needs more than the token carries is refused with 403. The person’s own role in the account applies on top, so a token never does more than the person could.

What the person approves

The approval screen shows the access the tool asks for and a list of the accounts the person belongs to. The person chooses exactly one account. Approve stays unavailable until one is chosen, and Apostra checks the choice against the person’s membership again before it issues anything. The token is bound to that account for its whole life. Neither accountId nor the deprecated X-SCOPE3-CUSTOMER-ID header can move it to another account: a request that names a different account is refused with 403. A person who belongs to no active account cannot approve an HTTP API sign-in.

Tokens

The token response has the usual fields (access_token, refresh_token, token_type, expires_in, scope) and one more, account_id: the account the token is bound to. Access tokens last 1 hour and refresh tokens 30 days, and a refresh token rotates on every use, exactly as for MCP sign-in. A refresh keeps the same account and scopes. Send the resource on every exchange and refresh; a different resource is refused with invalid_target.

When the token stops working

The token lasts as long as the person who approved it belongs to the account it is bound to. Apostra checks that on every request. If they leave the account, or the account is deactivated, the token returns 401 and a refresh returns invalid_grant. Another account the person belongs to is never a fallback. The person can also disconnect the tool from Connected apps, or the tool can revoke it at POST /auth/revoke. An HTTP API token cannot run Sales Agent validation, because that run would act as the person outside the account and scopes the token is limited to.

The Apostra command-line client

The Apostra command-line tool signs in with a first-party client, described in Agent sign-in. The command and the SDK helpers that use it ship separately from this API; the API accepts the sign-in described here today.

OAuth on a Seller endpoint

A buyer’s MCP client can sign in with OAuth on a hosted Seller’s platform-managed endpoint, https://api.apostra.com/seller/{platformId}/mcp. Each Seller endpoint is its own protected resource. Its metadata, at https://api.apostra.com/.well-known/oauth-protected-resource/seller/{platformId}/mcp, names that exact endpoint as the resource, and the client carries it through authorization, token exchange, and refresh. The credential acts as the person who approved it, in their Apostra buyer account. A credential issued for one Seller endpoint works only on that endpoint. It is rejected on another Seller’s endpoint, on /mcp and /mcp/v3, and on the HTTP API. A credential issued for /mcp or /mcp/v3 is rejected on every Seller endpoint. Connect each Seller you buy from separately.
  • Apostra authorizes a Seller endpoint only while that Seller advertises as an agent and is not archived. Authorization for an unknown or archived Seller is refused with 400 VALIDATION_ERROR, and the Seller’s metadata URL returns 404.
  • A Seller that sells through an ad platform, such as Meta, Google, or Snap, takes that platform’s credentials instead of an Apostra sign-in. When the platform uses OAuth, the endpoint’s resource_metadata points at the platform’s authorization server. An Apostra API key also works there. Any other credential Apostra issued, such as a token for another endpoint, is checked by Apostra and refused. It is never passed on to the ad platform. A key that starts with sk_ is checked with Apostra’s identity provider first; if that check can’t complete, the request is refused with 503 instead of being passed on.
  • OAuth is not available on a Seller’s own domain (/adcp/mcp). Use an API key there.

Full authentication reference

Review OAuth, user API keys, M2M applications, permissions, and stable v2 versioning behavior in the canonical authentication guide.