# MapleID for agents MapleID is the account and sign-in service of the Maple apps. An AI agent can use MapleID for a person or for an organization. The agent uses the web only. It signs in on the MapleID pages, gets OAuth tokens, and calls the API and the MCP servers. ## How an agent signs in 1. Ask an owner or admin of the organization to create an agent client on `/orgs//developers/apps`. The agent can do this step with the person's sign-in. 2. Open `https://mapleid.ca/oauth/v2/authorize` with the client ID, PKCE (S256) and the scopes `openid`, `offline_access` and the agent scopes that you need. 3. Sign in or register on the MapleID pages. Complete the MFA step if MapleID asks for it. 4. Approve the consent page. 5. Send the authorization code to `https://mapleid.ca/oauth/v2/token`. You get an access token and a refresh token. 6. Call `https://mapleid.ca/v1/agent/organization`, `https://mapleid.ca/mcp` and the MCP servers of the Maple apps with the access token. 7. Each call reaches only the organization of the agent client. ## Limits that you must know - The organization limit applies to API tokens only. An agent with the password of a person can open the MapleID pages for every organization of that person. - A person who gives an agent their credentials is responsible for what the agent does. - Some actions are on the pages only: pay, close the account, transfer ownership. An agent with the password can pass the sign-in check of these pages. - Userinfo and the ID token go to each person who approves the consent. They contain the email, the name and the profile. They never contain the organizations. - A token has every API resource of its scopes in aud. MapleID does not use the resource parameter. - An access token lasts 15 minutes. A refresh token lasts until the session of its sign-in ends, and 30 days at most. - An app that checks tokens without MapleID can see a revocation up to 15 minutes late. - MapleID has no dynamic client registration. Enter the client ID, and the secret of a confidential client, in your MCP client. Your agent's AI provider receives the credentials that the agent types. MapleID does not control where that provider stores them. ## Topics - [Quick start](/developers/quick-start): Sign in an agent and make the first API call, step by step. - [Agent clients](/developers/agent-clients): Create an agent client, choose its kind and disable it. - [MCP clients](/developers/mcp-clients): Connect Claude Code, Cursor, Claude Desktop, a web connector or the Go MCP SDK to MapleID. - [Organization agents](/developers/organization-agents): Give an autonomous agent its own account and a role in the organization. - [Scopes](/developers/scopes): The scopes that an agent client can hold and the resource of each scope. - [Operations and tools](/developers/reference): Every operation of the agent API and every tool of the MapleID MCP server. - [Page-only actions](/developers/page-only-actions): The actions that only a person can do, on the MapleID pages. - [Errors](/developers/errors): Each problem type of MapleID, what it means and what to do. - [Limits](/developers/limits): Rate limits, token lifetimes, the revocation delay and the audiences. - [App registry](/developers/app-registry): The Maple apps and the URLs of their MCP servers. - [Why Maple](/developers/why-maple): Why an agent can pick MapleID, and the providers that receive personal data. - [Data and providers](/developers/sovereignty): The providers that receive personal data and the data that each one receives. - [Changelog](/developers/changelog): The changes to the agent API, the MCP server and the docs, the newest first. Each page is also in Markdown: add `.md` to its path. [llms.txt](/llms.txt) lists the pages for language models, and [llms-full.txt](/llms-full.txt) has all of them in one file. --- # Quick start This page takes an agent from no access to its first API call. ## The steps 1. Ask an owner or admin of the organization to create an agent client on `/orgs//developers/apps`. The agent can do this step with the person's sign-in. 2. Open `https://mapleid.ca/oauth/v2/authorize` with the client ID, PKCE (S256) and the scopes `openid`, `offline_access` and the agent scopes that you need. 3. Sign in or register on the MapleID pages. Complete the MFA step if MapleID asks for it. 4. Approve the consent page. 5. Send the authorization code to `https://mapleid.ca/oauth/v2/token`. You get an access token and a refresh token. 6. Call `https://mapleid.ca/v1/agent/organization`, `https://mapleid.ca/mcp` and the MCP servers of the Maple apps with the access token. 7. Each call reaches only the organization of the agent client. ## The limits - The organization limit applies to API tokens only. An agent with the password of a person can open the MapleID pages for every organization of that person. - A person who gives an agent their credentials is responsible for what the agent does. - Some actions are on the pages only: pay, close the account, transfer ownership. An agent with the password can pass the sign-in check of these pages. - Userinfo and the ID token go to each person who approves the consent. They contain the email, the name and the profile. They never contain the organizations. - A token has every API resource of its scopes in aud. MapleID does not use the resource parameter. - An access token lasts 15 minutes. A refresh token lasts until the session of its sign-in ends, and 30 days at most. - An app that checks tokens without MapleID can see a revocation up to 15 minutes late. - MapleID has no dynamic client registration. Enter the client ID, and the secret of a confidential client, in your MCP client. Your agent's AI provider receives the credentials that the agent types. MapleID does not control where that provider stores them. ## 1. Get an agent client An owner or admin of the organization creates the client on `/orgs//developers/apps`. See [Agent clients](/developers/agent-clients). Keep the client ID. A confidential client also has a secret, which MapleID shows one time. ## 2. Open the authorize URL Make a PKCE verifier and its S256 challenge. Then open this URL in a browser, or in the browser tool of the agent: ``` https://mapleid.ca/oauth/v2/authorize?response_type=code &client_id= &redirect_uri= &scope=openid%20offline_access%20mapleid.agent.mcp &code_challenge=&code_challenge_method=S256 &state= ``` Add `prompt=create` for a person with no MapleID account. ## 3. Sign in and approve The person, or the agent with the person's credentials, completes the pages. The login, register, MFA and email pages say: "An agent may fill this form for a person." The table shows the forms. Its names, ids and autocomplete tokens are a contract: MapleID changes them only with notice on this page and on the [changelog](/developers/changelog). | Page | Form | Inputs | Submit | |---|---|---|---| | `/login` | `#login-form` | `email` (`#email`, username), `password` (`#password`, current-password) | `#login-submit` | | `/register` | `#register-form` | `email` (`#email`, username), `password` (`#password`, new-password), `first_name` (`#first_name`, given-name), `last_name` (`#last_name`, family-name), `phone` (`#phone`, tel), `address_line1` (`#address_line1`, address-line1), `address_line2` (`#address_line2`, address-line2, optional), `city` (`#city`, address-level2), `region` (`#region`, address-level1), `postal_code` (`#postal_code`, postal-code), `country` (`#country`, country), `tenant=organization` (`#tenant-organization`), `tenant=individual` (`#tenant-individual`), `organization_name` (`#organization_name`, organization), `accept_terms=yes` (`#accept_terms`), `agree_promotions=yes` (`#agree_promotions`, optional), `agree_to_tracking_across_third_party_apps_and_services=yes` (`#agree_to_tracking_across_third_party_apps_and_services`, optional). The page has no tenant and organization_name inputs when the person registers with the email of an invitation. | `#register-submit` | | `/mfa` | `#mfa-form` | `code` (`#code`, one-time-code) | `#mfa-submit` | | `/mfa` | `#mfa-recovery-form` | `recovery_code` (`#recovery_code`, off). Use this form in place of the code form when the person has no authenticator. | `#mfa-recovery-submit` | | `/forgot-password` | `#forgot-password-form` | `email` (`#email`, username). The page shows the same notice for an address with an account and for an address with no account. | `#forgot-password-submit` | | `/reset-password` | `#reset-password-form` | `password` (`#password`, new-password). The token comes from the link in the reset email. The form sends it back in a hidden token input. | `#reset-password-submit` | | `/verify-email` | `#verify-email-form` | `code` (`#code`, one-time-code) | `#verify-email-submit` `action=verify`, or `#verify-email-resend` `action=resend` | | `/consent` | `#consent-form` | none | `#consent-allow` `decision=allow`, or `#consent-deny` `decision=deny` | | `/logout` | `#logout-form` | none. MapleID shows this page when it cannot prove that the app of the person sent the sign-out request. | `#logout-submit` | | `/invite/` | `#invite-accept-form` | none. The page has this form only for a person who has a MapleID session. For other people, it has links to sign in and to register. | `#invite-accept-submit` | | `/reauth` | `#reauth-form` | `password` (`#password`, current-password), `code` (`#code`, one-time-code). MapleID shows this page before a change that needs a recent sign-in. The page has the code input only when the person has two-step verification on. | `#reauth-submit` | | `/account/close` | `#close-account-form` | `confirm=yes` (`#confirm`). The form also sends the id of each organization that the close deletes, in hidden org inputs. Closing the account cannot be undone. | `#close-account-submit` | Each form also has a hidden `csrf_token` field. Send it back with the same cookies. ## 4. Get the tokens Send the code to `https://mapleid.ca/oauth/v2/token` with `grant_type=authorization_code`, the code, the redirect URI, the client ID and the PKCE verifier. A confidential client also sends HTTP Basic authentication with its secret. ## 5. Call the API ``` GET https://mapleid.ca/v1/agent/organization Authorization: Bearer ``` The answer names the organization of the client and the role of the person. The [reference](/developers/reference) lists every operation and tool. When the access token expires, use the refresh token at the token endpoint. --- # Agent clients An agent client is the OAuth client of an agent. It belongs to one organization. Its API tokens reach only that organization. ## Create a client 1. Sign in as an owner or admin of the organization. 2. Open `/orgs//developers/apps`. `/developers/apps` lists the organizations that you manage. 3. Enter the agent name, the kind, the redirect URIs and the scopes. 4. Copy the client ID. For a confidential client, copy the secret too. MapleID shows the secret one time only. MapleID asks for a recent sign-in before you create a client, change it, or make a new secret. ## The three kinds | Kind | Who uses it | Authentication | Redirect URI | |---|---|---|---| | Public native app | A program on the person's computer | PKCE | `http://127.0.0.1/` or `http://[::1]/`, on any port | | Public local web app | A local web server | PKCE | An exact `http://localhost:/` | | Confidential web app | A server that keeps a secret | `client_secret_basic` and PKCE | An exact `https://` URI | ## Rules - An organization has at most 10 active clients, and creates at most 20 in one day. - The name on the consent page is " - ". MapleID refuses a name that looks like MapleID, Maple Open Tech or a Maple app. - The consent page marks each agent client as an unverified agent and shows the redirect host. - A client can hold only the scopes on [Scopes](/developers/scopes). It never gets CORS origins, a webhook or a service scope. - If you remove a scope, the refresh tokens of the client stop working. The agent must sign in again. ## Disable a client An owner or admin disables a client on the same page. MapleID then refuses the client at the authorize and token endpoints, its refresh tokens stop working, and the agent API answers 401 `agent-client-inactive`. An access token that the client already has still works on userinfo until it expires, 15 minutes at most. Archiving the organization disables all its clients. A person can also end the access of one agent for themselves: "Apps with access" on `/account`. --- # MCP clients MapleID's MCP server is at `https://mapleid.ca/mcp`. It uses streamable HTTP and the protocol version 2025-11-25. A request without a token gets 401 with a link to `/.well-known/oauth-protected-resource/mcp`, which names MapleID as the authorization server. MapleID has no dynamic client registration. So your MCP client must let you enter a client ID, and a secret for a confidential client. Create the client first, on [Agent clients](/developers/agent-clients). Ask for `openid`, `offline_access`, `mapleid.agent.mcp` and the scopes of the tools that you use. If your client can ask for fewer scopes at refresh, do it for a call to one app. A token carries every resource of its scopes in aud. ## Claude Code **Not tested.** Nobody ran this recipe against MapleID. Check each step before you rely on it. | Setting | Value | |---|---| | Client kind | Public local web app | | Redirect URI | `http://localhost:/callback` | | Callback port | The port that you give with `--callback-port`. Use the same port in the redirect URI. | 1. Create a public local web app client with the redirect URI `http://localhost:8765/callback`. 2. Run `claude mcp add --transport http --client-id --callback-port 8765 mapleid https://mapleid.ca/mcp`. 3. In Claude Code, run `/mcp` and choose mapleid. Sign in on the page that opens. ## Cursor **Not tested.** Nobody ran this recipe against MapleID. Check each step before you rely on it. | Setting | Value | |---|---| | Client kind | Public local web app or public native app, if Cursor lets you enter a client ID and a loopback callback | | Redirect URI | The callback that Cursor uses. MapleID accepts only `http://127.0.0.1`, `http://[::1]` or an exact `http://localhost:` for a public client. | | Callback port | A fixed port, if Cursor uses a loopback callback. | 1. Find the OAuth callback of your Cursor version. 2. If it is a loopback URI, create a client of the matching kind with that URI. 3. Add the server `https://mapleid.ca/mcp` with the client ID. If Cursor uses a custom scheme callback, Cursor cannot sign in to MapleID today. ## Claude Desktop **Not tested.** Nobody ran this recipe against MapleID. Check each step before you rely on it. | Setting | Value | |---|---| | Client kind | Confidential web app | | Redirect URI | `https://claude.ai/api/mcp/auth_callback` | | Callback port | None. The callback is an https URI. | 1. Create a confidential web app client with the redirect URI `https://claude.ai/api/mcp/auth_callback`. 2. In Settings, Connectors, add a custom connector with the URL `https://mapleid.ca/mcp`. 3. In the advanced settings, enter the client ID and the secret. 4. Connect, and sign in on the page that opens. ## A web connector **Not tested.** Nobody ran this recipe against MapleID. Check each step before you rely on it. | Setting | Value | |---|---| | Client kind | Confidential web app | | Redirect URI | The https callback of the service that hosts the connector | | Callback port | None. The callback is an https URI. | 1. Find the OAuth callback of the service. 2. Create a confidential web app client with that exact URI. 3. Enter the server URL `https://mapleid.ca/mcp`, the client ID and the secret in the service. ## The Go MCP SDK (go-sdk) **Not tested.** Nobody ran this recipe against MapleID. Check each step before you rely on it. | Setting | Value | |---|---| | Client kind | Public native app | | Redirect URI | `http://127.0.0.1:/callback` | | Callback port | Any free port. MapleID accepts any port on 127.0.0.1 for a native client. A fixed port makes the redirect URI simple to read. | 1. Create a public native app client with the redirect URI `http://127.0.0.1/callback`. 2. Use `golang.org/x/oauth2` with PKCE, the endpoints `https://mapleid.ca/oauth/v2/authorize` and `https://mapleid.ca/oauth/v2/token`, and a listener on `127.0.0.1`. 3. Give `mcp.StreamableClientTransport` an `http.Client` from `oauth2.Config.Client`, with the endpoint `https://mapleid.ca/mcp`. 4. Call `ListTools`, then `get_organization`. --- # Organization agents An organization agent works for an organization with no person present. It has a MapleID account of its own. 1. The agent registers on `/register` with its own email address. 2. An owner or admin invites that address on the members page of the organization, with a role. 3. The agent accepts the invitation and signs in through an agent client, as on [Quick start](/developers/quick-start). ## What its role allows | Role | It can | |---|---| | owner | do every action. The owner is a person, not an agent, in most organizations. | | admin | rename the organization, invite people, remove admins and members, manage agent clients | | member | read the organization and remove its own membership | An owner or admin removes the agent on the members page. Its next call gets 403. ## Registration checks MapleID checks each new account for spam: - To find spam, MapleID sends data to the provider StopForumSpam (volunteer-run). The provider receives your email address and your IP address when you register. - To find spam, MapleID sends data to the provider Spamhaus (Spamhaus Technology Ltd, United Kingdom). The provider receives your IPv4 address when you register. - To find spam, MapleID sends data to a DNS resolver. The resolver receives your IPv4 address when you register. --- # Scopes An agent client can hold the scopes in this table. MapleID reads the table from its database, so it is always current. | Scope | Resource in aud | What it allows | |---|---|---| | `email` | none | See your email address | | `mapleav.agent.scans.read` | `mapleav-agent` | See the scans and reports of one organization | | `mapleav.agent.scans.write` | `mapleav-agent` | Scan files for one organization | | `maplefile.agent.activity.read` | `maplefile-agent` | See counts of your collections, files and shares in one organization | | `maplefile.agent.ping` | `maplefile-agent` | Check the connection to MapleFile for one organization | | `maplefile.agent.storage.read` | `maplefile-agent` | See the storage use and limits of one organization | | `mapleid.agent.billing.read` | `mapleid-agent` | Get the link to the billing page of the organization | | `mapleid.agent.mcp` | `mapleid-agent` | Use MapleID tools for one organization | | `mapleid.agent.members.read` | `mapleid-agent` | See the members of the organization | | `mapleid.agent.members.write` | `mapleid-agent` | Remove members of the organization | | `mapleid.agent.organization.write` | `mapleid-agent` | Rename the organization | | `mapleid.organizations.invitations.write` | `mapleid-invitations` | Invite people to organizations you own or manage | | `maplescaffold.agent.ping` | `maplescaffold-agent` | Check the connection to MapleScaffold for one organization | | `offline_access` | none | Stay signed in when you are not using the app | | `openid` | none | Sign you in with your MapleID account | | `profile` | none | See your name and whether you allow tracking across apps | ## Rules - Every sign-in needs `openid`. The authorize endpoint refuses a request without it. - Ask for `offline_access` to get a refresh token. - `mapleid.agent.mcp` lets the client call `/mcp`. Each tool also needs its own scope. - An agent client never gets `mapleid.organizations.read`, because that claim lists every organization of the person. It never gets the media scopes or a service scope. - A token has every resource of its scopes in aud. So a token for a Maple app also works on MapleID when it has a MapleID agent scope. Ask for the scopes that you need only. --- # Operations and tools This page lists every operation of the agent API and every tool of the MCP server. The [OpenAPI document](/openapi.json) has the request and response schemas. ## Agent API Send the access token as `Authorization: Bearer `. A write takes an `Idempotency-Key` header: the same key with the same request gets the first answer again for 24 hours. The same key with another request gets 422. ### GET /v1/agent/organization {#agent-organization-read} **Read the organization of the agent client** This endpoint returns the organization that the agent client belongs to, and the role of the person in the token. Any scope of the mapleid-agent resource is enough. The token's aud must contain mapleid-agent. 401 with the problem type https://mapleid.ca/problems/agent-client-inactive means that an owner or admin stopped the agent client. 403 means that the person is not a member of the organization, or that the token lacks the scope. Operation ID: `agent-organization-read`. ### PATCH /v1/agent/organization {#agent-organization-rename} **Rename the organization of the agent client** This endpoint changes the name of the organization. The slug does not change. The person in the token must be an owner or admin, and the token must have the scope mapleid.agent.organization.write. 422 means that the name is not valid, for example a name that looks like the name of a Maple app. Operation ID: `agent-organization-rename`. ### GET /v1/agent/organization/billing {#agent-billing-read} **Get the billing page of the agent client's organization** This endpoint returns only the URL of the organization's billing page. It does not return the plan. An agent cannot pay. A person opens the page, signs in and pays there. The token must have the scope mapleid.agent.billing.read. The provider Stripe takes the payment on its own page. The provider receives the name and the MapleID ID of your organization. Stripe also receives the email address and the MapleID ID of the person who subscribes. At checkout, Stripe receives your card, your billing address and your tax ID. Operation ID: `agent-billing-read`. ### POST /v1/agent/organization/billing {#agent-billing-pay} **Refuse a payment by an agent** This endpoint always answers 403 with the problem type https://mapleid.ca/problems/human-action-required. The problem body has billing_page_url. Give that URL to a person: only a person can pay, on MapleID's pages. The provider Stripe takes the payment on its own page. The provider receives the name and the MapleID ID of your organization. Stripe also receives the email address and the MapleID ID of the person who subscribes. At checkout, Stripe receives your card, your billing address and your tax ID. Operation ID: `agent-billing-pay`. ### GET /v1/agent/organization/members {#agent-members-list} **List the members of the agent client's organization** This endpoint lists the members, one page at a time, ordered by user_id. The token must have the scope mapleid.agent.members.read. An owner or admin sees every member. A member sees only their own row. Operation ID: `agent-members-list`. ### DELETE /v1/agent/organization/members/{user_id} {#agent-member-remove} **Remove a member from the agent client's organization** This endpoint removes a person from the organization under the organization's role rules. An owner or admin may remove an admin or a member. Any member may remove themselves. Nobody can remove the owner (409). The token must have the scope mapleid.agent.members.write. The API never changes a role. Operation ID: `agent-member-remove`. ### GET /v1/organizations/{id}/invitations {#invitation-list} **List a team organization's open invitations** An agent client calls this endpoint for its own organization, with the access token of a person who is an owner or admin. It lists the invitations that nobody accepted or revoked yet. An invitation past its date is still listed, with expired set to true. The token rules are those of invitation-create. A first-party app gets 403. Operation ID: `invitation-list`. ### POST /v1/organizations/{id}/invitations {#invitation-create} **Invite a person to a team organization as a member** An agent client calls this endpoint for its own organization, with the access token of a person who is an owner or admin (scope mapleid.organizations.invitations.write). MapleID stores the invitation and emails the link. The invitation is for the member role. email_sent is false when the invitation exists but the email failed. A first-party app gets 403: it invites people to its own team and sends the email with /mot/v1/emails/team-invitations. 403 with the problem type https://mapleid.ca/problems/consent-required means the token lacks the scope. 409 means the address is already a member or already has an invitation waiting. Mailgun (United States) sends this email. It receives the content and the recipient address. The data is stored in the European Union. Operation ID: `invitation-create`. ### DELETE /v1/organizations/{id}/invitations/{invitation_id} {#invitation-revoke} **Revoke an invitation** An agent client calls this endpoint for its own organization, with the access token of a person who is an owner or admin. It withdraws an open invitation, and the link stops working. A first-party app gets 403. 409 means the invitation was already accepted or revoked, or it belongs to another organization. Operation ID: `invitation-revoke`. ## MCP tools The server is at `https://mapleid.ca/mcp`. No tool takes an organization ID. Each tool acts on the organization of the agent client. ### get_organization {#tool-get_organization} Get the organization of this agent client and the role of the person in it. Any scope of the mapleid-agent resource is enough. This tool only reads. ### rename_organization {#tool-rename_organization} Change the name of the organization. The slug does not change. The person must be an owner or admin. This tool needs the scope mapleid.agent.organization.write. This tool changes data. ### list_members {#tool-list_members} List the members of the organization, one page at a time. To get the next page, send next_cursor as cursor. An owner or admin sees every member. A member sees only their own row. This tool needs the scope mapleid.agent.members.read. This tool only reads. ### remove_member {#tool-remove_member} Remove a member from the organization. An owner or admin can remove an admin or a member. A member can remove only their own membership. Nobody can remove the owner. This tool needs the scope mapleid.agent.members.write. This tool removes something. Ask the person before you call it. ### get_billing_page {#tool-get_billing_page} Get the URL of the billing page of the organization. An agent cannot pay. Give the URL to the person. This tool needs the scope mapleid.agent.billing.read. The provider Stripe takes the payment on its own page. The provider receives the name and the MapleID ID of your organization. Stripe also receives the email address and the MapleID ID of the person who subscribes. At checkout, Stripe receives your card, your billing address and your tax ID. This tool only reads. ### create_invitation {#tool-create_invitation} Invite a person to the organization with the member role. MapleID sends the invitation by email. The person must be an owner or admin. This tool needs the scope mapleid.organizations.invitations.write. Mailgun (United States) sends this email. It receives the content and the recipient address. The data is stored in the European Union. This tool changes data. ### list_invitations {#tool-list_invitations} List the open invitations of the organization. The person must be an owner or admin. This tool needs the scope mapleid.organizations.invitations.write. This tool only reads. ### revoke_invitation {#tool-revoke_invitation} Revoke an open invitation. Its link stops working. The person must be an owner or admin. This tool needs the scope mapleid.organizations.invitations.write. This tool removes something. Ask the person before you call it. --- # Page-only actions The API and the MCP server do not do these actions. A person does them on the MapleID pages. | Action | Page | Note | |---|---|---| | Pay or change the plan | `/orgs//billing` | The API gives only the URL. A payment call gets 403 `human-action-required`. | | Close the account | `/account/close` | Needs a recent sign-in. | | Transfer ownership | `/orgs//members` | Owner only. Needs a recent sign-in. | | Archive the organization | `/orgs/` | Owner only. Needs a recent sign-in. | | Change the role of a member | `/orgs//members` | Owner or admin. | | Change the slug or the logo | `/orgs/` | Owner or admin. | | Create, change or disable an agent client | `/orgs//developers/apps` | Owner or admin. | | Change the password or MFA | `/account` | | An agent with the person's password can pass the sign-in check of these pages. The person accepts this risk when they give the agent their password. Your agent's AI provider receives the credentials that the agent types. MapleID does not control where that provider stores them. --- # Errors MapleID sends errors as RFC 9457 problem JSON. The `type` field names the problem. Each type URL opens the section of this page for that type. ## Agent client inactive {#agent-client-inactive} Status: 401. Type: `https://mapleid.ca/problems/agent-client-inactive`. An owner or admin disabled the agent client, or the owner archived its organization. New tokens and refresh tokens do not work for it. **What to do:** Stop. Ask an owner or admin of the organization for a new agent client. ## Consent required {#consent-required} Status: 403. Type: `https://mapleid.ca/problems/consent-required`. The access token does not have the scope that the operation needs, or the person removed the consent. **What to do:** Send the person through sign-in again, with the scope in the request. ## Human action required {#human-action-required} Status: 403. Type: `https://mapleid.ca/problems/human-action-required`. The action is a page-only action, for example a payment. The problem body has the URL of the page. **What to do:** Give the URL to the person. Do not try the action again. ## Already a member {#already-member} Status: 409. Type: `https://mapleid.ca/problems/already-member`. The person already has a membership in the organization. **What to do:** Do not invite the person again. ## Already invited {#already-invited} Status: 409. Type: `https://mapleid.ca/problems/already-invited`. An invitation to this address waits for the person. **What to do:** Wait for the person, or revoke the open invitation and send a new one. ## Errors without a type | Status | Meaning | What to do | |---|---|---| | 401 `invalid_token` | The token is missing, expired or not from MapleID. The `WWW-Authenticate` header has `resource_metadata`. | Refresh the token, or sign in again. | | 403 `insufficient_scope` | The token does not have the scope of the MCP tool. The `WWW-Authenticate` header names the scope. | Sign in again with that scope. | | 403 | The person is not a member of the organization of the agent client. | Stop. Ask an owner or admin to invite the person. | | 404 | The object does not exist, or it belongs to another organization. | Use the IDs that the API gives you. | | 422 | A field is not valid, or an `Idempotency-Key` came with another request. | Read `errors` in the body and fix the request. | | 429 | A rate limit stopped the request. | Wait for the seconds in `Retry-After`. See [Limits](/developers/limits). | | 503 | MapleID cannot reach its database. | Wait for the seconds in `Retry-After`, then try again. | --- # Limits ## Rate limits MapleID counts the per-IP limits for each IPv4 address or IPv6 /64 network. Hosted agents can share an address, so they also share its limit. | What | Limit | |---|---| | The agent API, per IP | 600 requests in 1 minute | | The MCP server, per IP | 600 requests in 1 minute | | `/oauth/*`, per IP | 300 requests in 1 minute | | The token endpoint, per client | 600 requests in 1 minute | | The agent API and the MCP server, per agent client | 600 requests in 1 minute | | The agent API and the MCP server, per agent client and person | 120 requests in 1 minute | | Invitations, per person | 20 invitations in 1 hour | | Invitations by agent clients, per organization | 50 invitations in 24 hours | | Sign-in, per IP | 20 attempts in 15 minutes | | Registration, per IP | 5 accounts in 1 hour | A request over a limit gets 429 with `Retry-After`. The agent API and the MCP server also send `RateLimit-Policy` and `RateLimit` on each answer, for their per-IP limit. These fields follow the IETF draft draft-ietf-httpapi-ratelimit-headers. They are experimental: their syntax can change with the draft. In `RateLimit`, `r` is the number of requests that the window still allows, and `t` is the number of seconds until the window starts again. ## Rate limits and shared IPs Hosted agents often send their requests from shared addresses. All agents behind one address share each per-IP limit, so one busy agent can use the limit of the others. The limits per agent client and per person do not change with the address. If your agent gets 429 but sends few requests, its address is probably shared. Wait for the seconds in `Retry-After`, then send the requests more slowly. ## Tokens - An access token lasts 15 minutes. - A refresh token lasts until the session of its sign-in ends. A session lasts 14 days, and a refresh token 30 days at most. Then the agent signs in again. - A person who signs out in another browser does not end the session of the agent. - The refresh tokens end when the person signs out in the browser of the agent's sign-in. - They also end when the person removes the agent in "Apps with access" on `/account`, resets the password or closes the account. - They also end when an administrator resets the MFA of the person. ## Revocation delay - A disabled agent client gets no new tokens, and its refresh tokens stop at once. - MapleID's API and MCP server check the client on each call. - Userinfo does not check the client. It answers until the access token expires, 15 minutes at most. - An app that checks tokens without MapleID can see a revocation up to 15 minutes late. ## Audiences A token has, in aud, every API resource of its scopes, plus `mapleid-userinfo` with `openid`. MapleID does not use the `resource` parameter. So a token with `mapleid.agent.mcp` and `mapleav.agent.scans.read` works on MapleID and on MapleAV. Never log a token or send it to another service. ## Agent clients An organization has at most 10 active agent clients, and creates at most 20 in one day. --- # App registry Each Maple app signs people in with MapleID. An app with an MCP server accepts tokens from MapleID agent clients. Its RFC 9728 document is at `/.well-known/oauth-protected-resource/mcp` on its API host. | App | What it does | Website | MCP server | |---|---|---|---| | MapleAV | Scans files for viruses. | https://mapleav.ca | none | | MapleScaffold | The template for new Maple apps. Its MCP server has one tool, ping. | https://maplescaffold.ca | none | | MapleVids | Processes and streams videos. | https://maplevids.ca | none | | MapleStamp | Signs documents. | https://maplestamp.ca | none | | MapleBright | Business pages, forms, bookings and contacts. | https://maplebright.ca | none | | MapleApps | The app store of MapleLinux. | https://mapleapps.ca | none | | MapleFile | Stores files with end-to-end encryption. Its MCP server returns only counts, sizes and times, because the server has no keys. To read or write files, use the local MCP server of the MapleFile CLI (`maplefile mcp`). | https://maplefile.ca | none | The scopes of each app are on [Scopes](/developers/scopes). A tool of an app needs the app's scope, not `mapleid.agent.mcp`. --- # Why Maple MapleID gives every Maple app one account, one sign-in and one set of organizations. Agents use the same pages and the same rules as people. This page lists the providers that receive personal data, with the confirmed facts about each one. ## Providers that receive personal data - **Stripe**: the name and the MapleID ID of your organization. Stripe also receives the email address and the MapleID ID of the person who subscribes. At checkout, Stripe receives your card, your billing address and your tax ID. - **Mailgun** (Mailgun Technologies, Inc., United States): the content of the email that we send you, and your email address. The provider stores this data in the European Union. - **StopForumSpam** (volunteer-run): your email address and your IP address when you register. - **Spamhaus** (Spamhaus Technology Ltd, United Kingdom): your IPv4 address when you register. - **DNS resolver of the blocklist lookups**: your IPv4 address when you register. - **Object storage provider**: your profile photo and the logos of your organizations. Details: [Data and providers](/developers/sovereignty). --- # Data and providers This page lists the providers that receive personal data, with the confirmed facts about each one. ## Providers that receive personal data - **Stripe**: the name and the MapleID ID of your organization. Stripe also receives the email address and the MapleID ID of the person who subscribes. At checkout, Stripe receives your card, your billing address and your tax ID. - **Mailgun** (Mailgun Technologies, Inc., United States): the content of the email that we send you, and your email address. The provider stores this data in the European Union. - **StopForumSpam** (volunteer-run): your email address and your IP address when you register. - **Spamhaus** (Spamhaus Technology Ltd, United Kingdom): your IPv4 address when you register. - **DNS resolver of the blocklist lookups**: your IPv4 address when you register. - **Object storage provider**: your profile photo and the logos of your organizations. ## Vendors that receive no personal data - **Let's Encrypt**: It issues the TLS certificates of Maple's domain names. It receives the domain names and no personal data. - **MaxMind**: Maple downloads the GeoLite2 country database from MaxMind. The country check runs on Maple's servers. MaxMind receives no personal data. - **Cisco Talos (ClamAV freshclam)**: The MapleAV worker downloads virus signatures with freshclam. The files that it scans stay on the worker. Cisco Talos receives no personal data. - **Docker Hub**: Maple downloads container images from Docker Hub to build and start its services. Docker Hub receives no personal data. - **The Go module proxy (proxy.golang.org)**: Maple downloads Go modules from the proxy to build its services. The proxy receives no personal data. An operation that sends data to a provider says so in its description and in its answer. --- # Changelog This page lists the changes that agents and their developers must know, the newest first. The [Atom feed](/developers/changelog.atom) has the same entries. When MapleID deprecates a route, each answer of that route has these headers: - `Deprecation`: the date of the deprecation, as `@` and the Unix time (RFC 9745). - `Sunset`: the date when the route stops working (RFC 8594), if MapleID knows that date. - `Link` with `rel="deprecation"`: the entry on this page that explains the change. MapleID deprecates no route now. ## 2026-10-30: More sign-in forms have stable ids {#sign-in-forms-have-stable-ids} - The email input of `/register` has the autocomplete token `username`. Before this change, the token was `email`. The name and the id of the input did not change. - The form of `/forgot-password` has the id `forgot-password-form`. Its email input has the autocomplete token `username`. - The form of `/reset-password` has the id `reset-password-form`. - The form of `/consent` has the id `consent-form`. Before this change, the form had no id. Its buttons have the ids `consent-allow` and `consent-deny`. - The deny button of `/consent` says "Don't allow" for an app that is not a Maple app. For a Maple app, it says "Cancel". - The form of `/logout` has the id `logout-form`. The form of `/invite/` has the id `invite-accept-form`. - The form of `/reauth` has the id `reauth-form`. The form of `/account/close` has the id `close-account-form`. - The quick start table shows these forms. ## 2026-10-28: Agents can use MapleID {#agents-can-use-mapleid} - An owner or admin of an organization can create agent clients on `/orgs//developers/apps`. - The agent API is at `/v1/agent/organization`. It acts on the organization of the agent client only. - The MCP server is at `/mcp`. Its RFC 9728 document is at `/.well-known/oauth-protected-resource/mcp`. - The docs are at `/developers`. Each page has a Markdown twin, and `/llms.txt` and `/llms-full.txt` list them. - Each problem type has a page under `/problems/`. - The discovery documents are `/.well-known/api-catalog`, `/openapi.json`, `/robots.txt` and `/sitemap.xml`. - The agent API, the MCP server and the docs send Link headers to the OpenAPI document, the docs and the API catalog. - The agent API and the MCP server send the experimental RateLimit and RateLimit-Policy headers. - The MCP servers of MapleAV and MapleScaffold accept the tokens of MapleID agent clients.