Auth and scopes
How the MCP server authenticates, and which scopes a key needs for which tools.
Two ways in
OAuth 2.1 (connectors). Claude and other connector-style clients discover
the server at /.well-known/oauth-authorization-server, register
dynamically, and send you to an authorisation page where you paste a Postal
API key. The key is exchanged for a one-hour access token with a 30-day
refresh token. The client never holds the key.
Direct header. Clients that let you set headers can send the key on every
request as X-API-Key: <key> or Authorization: Bearer <key>. No token
exchange.
Either way, every tool call becomes REST API calls made with that key, so the key's scopes apply.
The tool list reflects the key's scopes
The server advertises only the tools the connected key can call. A key with
read:tracks alone gives the assistant the track read tools and nothing
else; a key with every scope sees the full catalog, and so does a legacy
all key. The assistant never has to discover a missing scope by calling a
tool and getting an error.
The list follows the key's scopes with a delay of at most five minutes, the lifetime of the server's key cache. Clients cache the tool list themselves too, so after you change a key's scopes start a new conversation or reconnect the connector to see the difference.
The public catalog at /tools is not
filtered: it lists every tool, with the scope each one needs. Hiding is a
convenience for the assistant, not an access control. A call to a tool the
key cannot see is still forwarded to the API and refused there with the
usual scope error.
Scope per tool
| Scope | Tools |
|---|---|
read:tracks | list_tracks, get_track_count, get_track, search_tracks, find_duplicate_tracks, get_track_submissions, get_tag_taxonomy, get_suggested_tags, wait_for_auto_tag |
create:tracks | upload_track_by_url |
update:tracks | update_track_details, update_track_tags, trigger_auto_tag, batch_auto_tag, apply_suggested_tags, upload_artwork, and wait_for_auto_tag with trigger: true |
read:playlists | list_playlists, get_playlist |
create:playlists | create_playlist, add_tracks_to_playlist |
update:playlists | update_playlist, remove_track_from_playlist, reorder_playlist |
read:composers | list_composers, get_composer_count |
read:composer | get_composer |
create:composer | create_composer |
update:composer | update_composer |
delete:composer | delete_composer |
read:analytics | get_dashboard, get_entity_stats, get_top_tracks |
read:briefs | list_briefs, get_brief_submissions |
Suggested key profiles
Read-only assistant. Safe to hand to anyone who should look but not touch:
read:tracks, read:playlists, read:composers, read:composer, read:analytics, read:briefsLibrarian. Can tag, organise and build playlists, but not upload or delete:
read:tracks, update:tracks, read:playlists, create:playlists, update:playlists,
read:composers, read:composer, read:analytics, read:briefsEverything. Every tool works:
read:tracks, create:tracks, update:tracks,
read:playlists, create:playlists, update:playlists,
read:composers, read:composer, create:composer, update:composer, delete:composer,
read:analytics, read:briefsA key created from Settings → Integrations has this full set. Narrow it in Tools → Integration.
Composer scopes
Listing and counting use read:composers; fetching one uses read:composer.
Grant both or the assistant will be able to list composers and then fail to
open any of them.
Credits
search_tracks costs one credit per call from the connected account's
balance, the same as POST /tracks/search. No other tool is
metered.
Revoking access
Revoke or rotate the key in Postal. OAuth tokens minted from it stop working on their next refresh, at most one hour later. The direct-header path stops immediately.