https://invoice.horizonpay.co/mcp needs a Bearer credential. There are two kinds:
- OAuth (recommended). The client signs you in and you approve it. Claude, ChatGPT, Claude Code and Cursor do this on their own. You only give them the URL.
- An API key, for clients that let you set headers.
OAuth
You don’t need to configure anything. This section is for people building an MCP client, or curious about what happens when you connect.Discovery
A client starts with nothing but the server URL:-
It calls
/mcpwithout a token and gets401with aWWW-Authenticateheader: -
It fetches
resource_metadata(RFC 9728). That names the authorization server,https://invoice.horizonpay.co. -
It fetches
/.well-known/oauth-authorization-server(RFC 8414) to find the endpoints below. -
It identifies itself in one of two ways:
- Client ID Metadata Document. Its
client_idis anhttps://URL serving its own metadata. The consent screen shows its domain as verified. - Dynamic registration (RFC 7591). It posts its metadata to
/oauth/registerand gets aclient_id. The consent screen marks it Unverified app and shows where you’ll be sent back to.
- Client ID Metadata Document. Its
-
It sends you to
/oauth/authorizewith a PKCEcode_challenge(S256only). You sign in, if needed, and approve. -
It exchanges the code at
/oauth/tokenwith thecode_verifier, and gets an access token and a refresh token. -
It calls
/mcpwithAuthorization: Bearer inv_oat_....
Endpoints
- Grant types:
authorization_codeandrefresh_token. - Client authentication at the token endpoint:
none(public clients, protected by PKCE),client_secret_basicorclient_secret_post. - Redirect URIs: any
https://URL,http://on127.0.0.1,[::1]orlocalhost(any port), or a private-use scheme likecom.example.app:/callback. They’re matched exactly, except the loopback port. - The redirect back carries
iss(RFC 9207).
Permissions
The consent screen groups scopes by risk:webhooks:manage and products:write are never offered to an MCP client.
A scope also grants what it needs to work. For example, invoices:write adds business:read, clients:read and invoices:read, and invoices:send adds invoices:read. The consent screen shows this next to each scope.
Tokens
- If a used refresh token is presented again, Invoice-AI assumes it was stolen and revokes every token from that sign-in. You connect again.
- A refresh can keep or narrow the scopes, never widen them.
- Tokens are bound to an audience (RFC 8707). A token issued for
/mcpis rejected by/api/v1, and a token for/api/v1is rejected by/mcp.
Revoke access
Disconnect an app in Settings → AI assistants. Its tokens stop working on the next request. Its past calls stay in Settings → Activity.Use an API key
For clients that let you set headers, send an API key as a Bearer token:OAuth for the REST API
App developers can use the same authorization server to call the REST API on a user’s behalf. Sendresource=https://invoice.horizonpay.co/api/v1 on the authorize and token requests, and ask for the scopes you need. All 11 scopes can be requested. The resource metadata is at https://invoice.horizonpay.co/.well-known/oauth-protected-resource/api/v1.