Pairing
Pairing is how an extension gets a TablePro token without the user copying one by hand. The extension opens atablepro://integrations/pair deep link, the user approves scopes and connections in TablePro, and the extension exchanges a one-time code for the token over localhost HTTP.
The flow is PKCE-style: the extension generates a verifier, hashes it into a challenge, and TablePro releases the token only to the caller that presents the verifier. An app that intercepts the redirect cannot exchange the code.
Sequence

The pairing approval sheet
Extension steps
1. Generate a verifier and challenge
2. Open the pair deep link
Opentablepro://integrations/pair?client=...&challenge=...&redirect=...&scopes=.... Parameters are documented in the URL scheme reference.
3. Receive the code and exchange it
TablePro opens yourredirect URL with a one-time code. For raycast:// redirects the code arrives as ?context={"code":"<uuid>"} (Raycast’s launch-context convention); for any other scheme it is a flat ?code=<uuid> query parameter. An error parameter instead of a code means the user denied the request; stop and show the description.
Read the MCP port from ~/Library/Application Support/TablePro/mcp-handshake.json, then:
4. Store the token
Store the token in the macOS Keychain. In Raycast, write it to a password preference, which is Keychain-backed. Do not keep it inLocalStorage or plain files.
What TablePro does on approval
The approval sheet shows the client name, a scope picker (defaults to the requested scope, downgradeable), a connections multi-select (defaults to all unlessconnection-ids was provided), and an expiry picker (defaults to never). The query parameters are a request, not a grant.
On approve, TablePro:
- Revokes any existing active token with the same client name. An extension that pairs again must replace its stored token; the old one stops working the moment the user approves.
- Mints the token and holds the plaintext in memory as a pending exchange keyed by a UUID code, valid for 5 minutes. Only the SHA-256 hash plus salt reaches
mcp-tokens.json. - Opens the
redirectURL with the code.
Security properties
Errors
A failed exchange is recorded in the activity log under the
auth category with outcome denied.
If the user clicks Deny, TablePro opens the redirect URL with error=denied and error_description=user_denied, wrapped in the context JSON for raycast:// redirects and appended as flat query parameters otherwise.
Implementing pairing in another extension
The flow is not Raycast-specific. Any client that can receive a callback can use it:- Generate a verifier and challenge.
- Open
tablepro://integrations/pair?...with a callback URL the OS can route back to you. - Read the MCP port from the handshake file.
- POST
{ code, code_verifier }to/v1/integrations/exchange. - Store the returned token in the Keychain.
http://127.0.0.1:<port>/callback as the redirect.
