API template library

Plaid OAuth mock API and live sandbox

A WireMock simulation of Plaid's REST API — covering the bearer-token layer of Plaid's API auth — minting, introspection, and revocation.

Vendor
Plaid
Functionality
OAuth token lifecycle
Spec version
2020-09-14_1.688.6
Endpoints
3
Stubs
4
Protocol
REST
Validation
AI-validated Before publication, an AI agent exercised these endpoints against the real Plaid API through WireMock's recording proxy, and the recorded traffic was used to verify each stub's request and response shapes.

Live sandbox · no signup, no API key

Plaid OAuth

A running WireMock Cloud instance of this template, callable right now from a terminal, a script, or an AI agent.

Base URL
https://1k7l3.wiremockapi.cloud

POST Introspect inactive - /oauth/introspect

curl -s -X POST 'https://1k7l3.wiremockapi.cloud/oauth/introspect' \
  -H 'Content-Type: application/json' \
  -d '{}'

POST Token - /oauth/token

curl -s -X POST 'https://1k7l3.wiremockapi.cloud/oauth/token' \
  -H 'Content-Type: application/json' \
  -d '{}'

POST Introspect - /oauth/introspect

curl -s -X POST 'https://1k7l3.wiremockapi.cloud/oauth/introspect' \
  -H 'Content-Type: application/json' \
  -d '{}'
Method Path Summary
POST /oauth/introspect Get metadata about an OAuth token
POST /oauth/revoke Revoke an OAuth token
POST /oauth/token Create or refresh an OAuth access token

Unauthenticated WireMock Cloud demo sandbox for Plaid — not an official Plaid sandbox, and it returns simulated example data only.

What's inside the OAuth template

Plaid's newer authentication model — bearer tokens instead of a client_id/secret pair in every request body — gets a working token registry here. POST /oauth/token mints a fresh UUID access token on each call, valid for a stated 900 seconds beside a constant refresh token; /oauth/introspect keeps honest books on what the mint route issued, answering active with a full claim set — scope, client_id, subject, audience and issuer pointing at production.plaid.com — for tokens it minted and active false for everything else; and /oauth/revoke genuinely retires a token, flipping its next introspection to inactive. The three routes close the loop most OAuth mocks leave open: state that survives from one call to the next.

  • Token minting — per-call access tokens with expiry and token_type under any grant type
  • Introspection — registry-backed active/inactive verdicts, with full claims on the active side
  • Revocation — a teardown route whose effect is visible on subsequent introspections

Example implementation using plaid-python

plaid-python 43 ships request models for all three routes; point its Configuration at the sandbox and the whole lifecycle runs:

Two printed lines — active True, then False — demonstrate that the mock's registry, not a canned response, is answering. That makes this sandbox suitable for the auth middleware itself: token caches, 401-triggered re-mints, and logout paths that must observe a revocation actually landing.

Note the enum: grant_type travels as OAuthGrantType, which accepts client_credentials, refresh_token, and the token-exchange URN. The mock mints on any of them, so both the first-issue and refresh branches of your token manager run against one stub.

import plaid
from plaid.api import plaid_api
from plaid.model.o_auth_token_request import OAuthTokenRequest
from plaid.model.o_auth_grant_type import OAuthGrantType
from plaid.model.o_auth_introspect_request import OAuthIntrospectRequest
from plaid.model.o_auth_revoke_request import OAuthRevokeRequest

configuration = plaid.Configuration(
    host="https://1k7l3.wiremockapi.cloud",
    # required by the client, ignored by the mock
    api_key={"clientId": "any-value", "secret": "any-value"},
)
client = plaid_api.PlaidApi(plaid.ApiClient(configuration))

minted = client.oauth_token(
    OAuthTokenRequest(grant_type=OAuthGrantType("client_credentials"))
)
token = minted.access_token

check = client.oauth_introspect(OAuthIntrospectRequest(token=token))
print("active:", check.active)

client.oauth_revoke(OAuthRevokeRequest(token=token))

recheck = client.oauth_introspect(OAuthIntrospectRequest(token=token))
print("after revoke:", recheck.active)

Frequently asked questions

They come from different layers. The active flag is computed against the registry — it tracks what was minted and what was revoked — while exp and iat are canonical fixture values frozen at an instant years past. A validator that trusts the flag sees correct lifecycle behavior; one that recomputes expiry from the claims will reject every token, which is worth knowing before pointing strict JWT middleware at this instance.

Only as an input. Every mint returns the same refresh_token value, and presenting it to /oauth/introspect yields inactive — the registry tracks access tokens alone. A refresh-grant call to the token route works and mints a fresh access token, so rotation flows run; what you can't do is inspect or revoke the refresh credential itself.

None — the token route requires only a well-formed request, and the claims in later introspections are fixtures rather than an echo of who asked. As always with a shared instance, that leniency cuts both ways: it removes setup friction, and it means a production secret pasted into a test config here is a secret disclosed.

Different layers of the API: an OAuth bearer token authenticates your application to Plaid, while access-sandbox tokens name individual linked Items inside your account. The Item side has its own rotation story — invalidate-and-replace — modeled in the Items & Webhooks template, and the two lifecycles are independent in production just as they are across these sandboxes.

Vendor names identify APIs represented by WireMock template sources. This page does not imply vendor endorsement, certification, partnership, or official integration status.