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/v3only, 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_credentialsflow. 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: callget 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.
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 advertiseshttps://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. NeitheraccountId 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 returns401 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 returns404. - 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_metadatapoints 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 withsk_is checked with Apostra’s identity provider first; if that check can’t complete, the request is refused with503instead 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.