mcp.peeve.ai/{workspaceId}/u/{contactId}.
The token
A grant token looks likepv_grant_ followed by high-entropy random data. It is
bound to a specific (workspace, contact) pair, and is passed as a bearer
credential.
- it starts with
pv_grant_; - it matches a grant on this workspace;
- that grant is bound to this contact;
- it has not been revoked;
- it has not expired.
401 — the endpoint never tells a caller which
condition failed, or whether the grant exists.
Because the token is bound to both the workspace and the contact in the URL, a
valid token for one contact cannot be used against another contact’s endpoint,
and a token from another workspace matches nothing.
Issuing a grant
Grants are issued from the dashboard, on the contact’s detail page. The token is shown once; hand it to that user through a channel you already trust for credentials.Revoking a grant
Revoke from the same contact detail page. Revocation takes effect on the next request — validation is a single indexed lookup with no cache in front of it, so there is no propagation delay. An expiry may also be set, and is checked on every request. Peeve stamps a last-used timestamp on each successful call, so you can see which grants are actually in use before you revoke.GET — discovery card
Requires the bearer token, like the POST.Errors
Identical to the workspace endpoint, with one addition.
On
GET, an auth failure is a plain 401 { "error": "unauthorized" }; the
JSON-RPC framing above applies to POST.
A malformed workspace or contact UUID returns 404.
Rate limits
Bucketed per workspace and per contact — the identity the grant is bound to. The token itself never goes in a limiter bucket, because it is a secret. Ceilings follow your plan. This matters more here than on the workspace endpoint: a grant is a long-lived token in a third-party assistant, and a looping client would otherwise query your data indefinitely.Auditing
Every call is recorded against the contact, so the trail attributes eachtools/call to the specific revocable credential rather than to “someone with
the URL”. The record carries the capability key, the method and the outcome —
never the arguments.
This is the main practical reason to prefer per-user grants over the
workspace endpoint when you can: the workspace endpoint tells you that a tool
was called, and per-user grants tell you whose assistant called it.