Exchange Code for Tokens
Server-to-server call. Exchange the authorization code (with your PKCE code_verifier) for an access token and a refresh token, or use grant_type refresh_token to get a new access token. Access tokens last 1 hour and refresh tokens 30 days; every refresh rotates the refresh token. Send the access token as a Bearer token to the Panda IDX MCP servers.
/api/oauth/tokenAuthentication
no credentialsPublic clients send client_id and code_verifier only. Confidential clients (token_endpoint_auth_method client_secret_post) also send client_secret in the body or as HTTP Basic credentials. The body can be JSON or application/x-www-form-urlencoded.
Query Parameters
grant_typestringauthorization_code or refresh_token.
authorization_codeauthorization_coderefresh_tokenclient_idstringThe client_id from POST /register or your Client ID Metadata Document URL.
codestringThe authorization code from the callback. Required for grant_type authorization_code.
redirect_uristringThe same redirect_uri used in the authorize step.
code_verifierstringThe PKCE verifier whose SHA-256 you sent as code_challenge. Required for public clients.
refresh_tokenstringRequired for grant_type refresh_token.
resourcestringMust be the Panda IDX MCP server.
https://api.pandaidx.com/mcpclient_secretstringOnly for confidential clients registered with client_secret_post.
Responses
application/jsonaccess_tokenstringBearer token for the MCP servers. Valid for expires_in seconds.
refresh_tokenstringUse it with grant_type refresh_token. Valid for 30 days and rotated on every use.
token_typestringAlways Bearer.
expires_innumberAccess token lifetime in seconds (3600).
scopestringThe granted scopes, space separated.
Errors
400invalid_request, invalid_grant (expired, reused or mismatched code, failed PKCE), invalid_target (resource is not the MCP server)401invalid_client: client authentication failedComplete the authorization flow
Use this endpoint after the user returns to your redirect_uri with an authorization code. Send the exchange from your backend or your local connector, never from a public web page. The body carries the code, the PKCE code_verifier you generated before the authorize step, your client_id and the MCP resource. Use the same redirect_uri as in the authorization step.
Store and refresh tokens safely
Access tokens last one hour and refresh tokens 30 days. Every refresh returns a new refresh token and invalidates the old one, so save the new value each time. Keep tokens and any client_secret out of public repositories, analytics events and browser URLs. If the user disconnects the connector in Dashboard → Apps, or you call the revoke endpoint, the tokens stop working immediately.
Where tokens work
Panda IDX OAuth tokens are accepted by the MCP servers at https://api.pandaidx.com/mcp and https://api.pandaidx.com/mcp/builder. The REST endpoints of the Site API do not use OAuth: they take the site's public key in the key query parameter.
curl --request POST \--url "https://app.pandaidx.com/api/oauth/token" \--header "Content-Type: application/json" \--data-raw '{"grant_type": "authorization_code","code": "{{auth_code}}","client_id": "{{client_id}}","redirect_uri": "{{redirect_uri}}","code_verifier": "{{code_verifier}}","resource": "https://api.pandaidx.com/mcp"}'
{"access_token": "pnd_example_access_token","refresh_token": "pnd_example_refresh_token","token_type": "Bearer","expires_in": 3600,"scope": "profile listings contacts"}