Docs
API 2026-05-27.dahlia Dashboard

Build with AI agents

MCP sign-in with OAuth

Use with AI

Sign in from an AI client, choose what it may do, revoke it.

With OAuth, an AI client reaches Fluveo MCP with no key. You add the server's address to the client. The first time the client calls it, the client opens the Dashboard in your browser. You sign in, pick what the client may do in one store, and click Allow access. The client then holds a short-lived token that it renews on its own.

Each consent makes one connection. A connection belongs to one person, one store and one client, holds the permissions that person chose, and works in test mode only. It lasts until someone revokes it or one of the events under What ends a connection happens.

OAuth or an agent key#

Both ways give an agent the same reach. The API applies the same agent rules to both: the operations an agent may never run, the writes that wait for a person's approval, and the store's Allow AI agent access switch.

OAuthAgent key
Best forA client a person runs and watches, such as Claude Code, Cursor, Codex or VS CodeAn agent that runs with no person at hand, or a client that cannot sign in with OAuth
Set upAdd the address. The client asks you to sign in the first time.Make a restricted test key for an AI agent, then put it in an environment variable
What the client storesA token that lasts 10 minutes and a refresh tokenThe key
Who picks the permissionsThe person who consents, on the consent pageThe person who makes the key
End itRevoke in ConnectionsRevoke in Connections, or expire the key

MCP authentication covers agent keys. Connect a client shows both ways for each client.

Sign in from a client#

  1. Add the server without a key#

    Add Fluveo MCP to your client with its address only, and no Authorization header. Connect a client has the command or file for each client.

  2. Start the sign-in#

    Ask the client to connect, for example with /mcp in Claude Code. The client opens the Dashboard's consent page in your browser. If you are signed out, the Dashboard asks you to sign in first, then returns to the consent page.

  3. Check who is asking#

    Read the card Who is asking. App is the name the client gave. Address is the client's domain, or Not given. Returns to is where your browser goes after you decide. Deny the request if any of them is not the client you just started.

  4. Check the store and the mode#

    Store names the store the client will reach. When you hold a suitable role in more than one store, pick another store there and the page loads again for it. Mode always shows Test mode.

  5. Choose what it may do#

    Under What it may do, the table starts with the permissions the client asked for, or with Read on every resource when it asked for none. Choose None or Read for each resource, and Write where the table offers it, as for a restricted key. Read only gives Read on every resource. Payments also gives Write on Charges and Refunds, Customers, Products, Prices, Payment Links and Checkout Sessions. Any other choice shows Custom. Give Read on Account so the agent can call get_account_info.

  6. Allow or deny#

    Click Allow access. Your browser goes back to the client, which finishes the sign-in on its own. Click Deny to refuse. The client then gets access_denied and no connection is made.

The authorization request lasts 10 minutes, including time spent signing in. After it expires, start again from the client.

Who may connect a client#

An owner, an admin or a developer of the store may consent. A viewer sees Your role can’t connect AI clients and cannot allow access. The person who consents owns the connection. If that person leaves the team or becomes a viewer, the connection ends.

A person may hold connections from at most 50 different clients on one store. Connecting the same client to the same store again replaces the earlier connection, so you never hold two for one client.

What the client gets#

  • An access token that lasts 10 minutes. The client sends it as Authorization: Bearer <access token> on every request to the server.
  • A refresh token. The client trades it for a new access token and a new refresh token when the access token runs out. Each refresh token works once. Unused, it expires after 30 days. Refresh tokens can be renewed for at most 90 days from the code exchange. After that, the client asks you to sign in again.
  • The permissions you chose. The token answer lists them in scope, as <resource>:<access> words such as customer:write. The server and the API check each request against the connection's permissions, never against the words in the token.

tools/list shows only the tools the connection's permissions allow. When a client calls a tool anyway that needs a permission the connection lacks, the server answers 403 with insufficient_scope and names the permission. Connect again and allow that permission on the consent page.

A connection with Write on a resource may change it, within the same agent rules an agent key follows. A write that needs approval answers approval_required with a link, and runs only after a person approves it in the Dashboard. Agent approvals shows that flow. Creating or confirming a PaymentIntent, or creating a payout, is refused even with Write.

See and revoke a connection#

Open Settings > Developers > AI agents in test mode. Connections lists the store's agent keys first, then each app connected with OAuth. An app's row shows:

  • The client's name, with the OAuth badge.
  • The client's domain as plain text, or No domain.
  • Connected by and the e-mail of the person who consented.
  • When the connection was made and when it was last used.
  • How many resources it may read and write. Click it to list each resource and its access.

To end one connection:

  1. Click Revoke on the app's row. The Revoke app access panel names the client.
  2. Click Revoke access. The Dashboard shows "App access revoked. The app can no longer call Fluveo for this store." and the row leaves the list.

Within 3 seconds the client's next request gets 401 invalid_token, and its refresh token stops working. To use the client again, someone must connect it again. Your agent keys and other apps keep working.

An owner or an admin sees and may revoke every connection of the store. A developer sees only their own connections and may revoke them.

To stop every agent of the store at once, keys and apps alike, turn off Allow AI agent access, as MCP security shows. While it is off, the API refuses every call an OAuth connection makes with 403.

What ends a connection#

  • Someone revokes it in Connections.
  • The same person connects the same client to the same store again. The new connection replaces the old one.
  • The person who consented is removed from the team or made a viewer.
  • Fluveo completes a revocation requested by the client or triggered by token reuse.

When Fluveo detects reuse of a rotated refresh token or a stored exchanged code, it stops further refreshes and requests revocation of the connection. A client's request to revoke its refresh token does the same. If revocation cannot be completed, an access token may work until it expires, at most 10 minutes. Revoke the app in Connections if access remains.

An ended connection never comes back. A token signed before the end stops working within 3 seconds.

How a client signs in#

Most clients run these steps on their own. They matter when you build a client, or test the flow with an HTTP client. Fluveo follows the MCP authorization flow: OAuth 2.1 with the authorization code, PKCE with S256, and the resource indicator.

  1. Find the authorization server#

    The Fluveo MCP server is not available in production yet.

  2. Read the authorization server's metadata#

    Read /.well-known/oauth-authorization-server on the issuer. It names authorization_endpoint, token_endpoint, registration_endpoint and revocation_endpoint, with code_challenge_methods_supported: ["S256"] and client_id_metadata_document_supported: true.

  3. Identify the client#

    Use the https:// address of a client ID metadata document as client_id, or register at registration_endpoint and use the dcr_... id it answers. Fluveo takes public clients only, with no secret. A redirect URI is an https:// address, a loopback address on 127.0.0.1, [::1] or localhost with any port, or a cursor: address.

    POST /oauth/register
    Content-Type: application/json
    
    {"client_name": "My agent", "redirect_uris": ["http://127.0.0.1:8976/callback"]}
  4. The Fluveo MCP server is not available in production yet.

  5. Trade the code for tokens#

    The Fluveo MCP server is not available in production yet.

  6. Call the server#

    The Fluveo MCP server is not available in production yet.

  7. Refresh before the token runs out#

    Post grant_type=refresh_token with refresh_token and client_id to token_endpoint. The answer has the same shape, with a new refresh token. Keep only the newest one. Sending an older one again stops further refreshes and requests revocation of the connection.

  8. Sign out#

    Post token (the refresh token) and client_id to revocation_endpoint. A refresh token of that client stops further refreshes and requests revocation of the connection. The endpoint answers 200 with an empty body, even for an unknown token. A service outage answers 503 temporarily_unavailable. Retry that request.

Errors#

On the consent page:

What the page showsWhyWhat to do
AI clients connect in test modeThe Dashboard is in live mode.Click Switch to test mode.
Your role can’t connect AI clientsYou are a viewer in this store.Pick a store where you are an owner, admin or developer, or ask an owner for the developer role.
This request doesn’t existThe link is wrong or incomplete.Start again from the client.
This request is closedSomeone already decided it, or 10 minutes passed.Start again from the client.
"Pick at least one permission, or deny the request."Every resource is set to None.Choose at least one permission, or click Deny.
"You gave access to too many AI clients on this store."You hold connections from 50 clients on this store.Revoke one in Connections, then try again.

From the MCP server:

AnswerWhyWhat to do
401 invalid_tokenThe access token expired, the connection was revoked or ended, or the token was made for another server.Let the client refresh. When the connection ended, connect the client again.
403 insufficient_scopeThe tool needs a permission the connection lacks. WWW-Authenticate names it in scope.Connect again and allow that permission.
503 service_unavailableThe server could not check the token right now. The answer carries Retry-After: 1.Send the request again after a second. Nothing ran.

From the authorization server, as error in the redirect or in the JSON answer:

errorWhy
access_deniedThe person clicked Deny.
invalid_requestA parameter is missing, repeated or malformed, such as no code_challenge or a method other than S256. An unknown client_id or an unregistered redirect_uri gets a 400 answer and no redirect.
invalid_targetresource is missing, or is not The Fluveo MCP server is not available in production yet..
invalid_scopeA scope word is not <resource>:read or <resource>:write, or there are more than 40.
invalid_grantThe code or refresh token is unknown, used, expired, of another client, or its PKCE verifier is wrong, or the connection ended. Start the sign-in again.
temporarily_unavailableFluveo could not check the connection. Nothing changed. Try again.

Next#