Gmail
GOOGLE WORKSPACE · EMAIL
Connect Gmail to your AI app with per-user OAuth.
Let users connect Gmail and grant the access your app needs. Fabriq manages the provider credentials and exposes tools according to the connected user’s grant and your agent’s scopes.
Connect Gmail with Fabriq Developer
Your user consents at Gmail. The credential lands in a vault your agent cannot read, and the tool list it gets back is the intersection of that user’s grant and the agent’s own scopes.
Provider names are surfaces, not vendors, and the authoritative list is the capabilities endpoint rather than any page including this one — an unknown name returns 400 with the valid list. Fabriq Developer is free to start and needs no provider paperwork. Start free or read the quickstart.
Ship the Gmail integration
Every route, header, field name and error string below is the gateway’s own, and every tool id and scope comes from the generated schema behind the action list further down this page.
Prerequisites
Before the redirect above can do anything, four things have to be in place on the Fabriq side and one or two on the Gmail side.
- A Fabriq Developer app, and its AF_APP_ID and AF_APP_SECRET. They ride on every app-scoped call as X-App-Id and X-App-Secret.
- A Redirect URL saved on the agent’s Connect & webhooks page. It is checked before anything else, so leaving it empty fails every connect with “B2B2C OAuth callback URL not configured” and hides whatever else is wrong.
- An external user id of your own, one per real person, created with POST /api/v1/apps/{app_id}/external-users. The call is idempotent and a 409 means the id already exists.
- Grants on the agent itself. The tool list a user gets back is the intersection of that user’s grant and the agent’s own scopes, so an agent with no overlapping grant sees nothing even after a clean consent.
- A Google account your user can consent with, and a verification posture that matches the scopes you ask for. Google classifies gmail.readonly, gmail.compose and gmail.modify as restricted scopes, which require restricted-scope OAuth app verification; gmail.send is only sensitive, so it needs verification but not the restricted review.
- In a Google Workspace tenant, the app has to be allowed through Admin console API controls, where an admin sets each app to Trusted, Limited, specific Google data, or Blocked and can separately restrict high-risk Gmail scopes.
Connect an account
The gateway provider id is gmail, and this page is /integrations/gmail. Post the initiate, redirect the user to oauth_url, and let them consent at Google. The credential lands in a vault your agent cannot read; your code never sees a Google token.
Both the OAuth flow and the hosted-credential flow return to the same Redirect URL with the same query parameters, so one callback handler covers everything you connect next.
Make one tool call
google_gmail_list_messages is the cheapest honest first call: it is a GET, it takes no required arguments, and it needs only the gmail.readonly scope. The gateway serves it at /api/v1/tools/google/gmail/messages and the tool returns message ids with subject, from, to, date, snippet and body.
If you would rather not ask for a restricted scope at all, send instead: gmail_send takes to, subject and body and needs only gmail.send, the one Gmail scope on this connector that Google treats as sensitive rather than restricted. Note that it is a real send — use an address you own.
Inspect the result
Scope to action, as the connector declares it: gmail.readonly covers google_gmail_list_messages, google_gmail_read_message, google_gmail_list_threads and google_gmail_get_thread. gmail.send covers gmail_send and gmail_reply. gmail.compose covers the draft actions, including google_gmail_send_draft. gmail.modify covers the label, archive, trash and read-state actions.
So a user who granted only gmail.send has a connection in status "connected" and exactly two tools. That is working, not broken.
- tools/list has two gates: the connection has to exist, and the agent’s grants have to intersect the connection’s scopes. Connected with zero tools is a real state, so say “connected but no actions live” rather than showing the integration as on.
- A listed connection is not a working one. The initiate writes the row before the user ever reaches the provider: status “configured” means the row exists and nothing else does, and it yields zero tools. Key every user-facing state off status == "connected".
- Do not infer readiness from granted_scopes being non-empty. Some providers legitimately grant none.
- The callback query parameters — status, tool, connection_id, external_user_id — are not signed. Treat them as a UI hint, resolve the user from your own session, and confirm by re-reading the connections list. The signed channel is the connection.completed webhook.
The payload above shows the shape of a response using the field names the gateway documents. It is illustrative: it was not captured from a live Gmail account, so treat the values as placeholders and read your own response.
Disconnect
Deleting the connection is one app-scoped call, and it is the only way to take Gmail away from an agent without taking the agent down.
- The delete removes the stored credential and the connection row on the Fabriq side, so the user has to authorize again to reconnect.
- Whether the authorization is still listed in the provider’s own connected-apps screen is the provider’s state, not Fabriq’s. If your flow needs the grant gone there too, send the user to the provider and check.
- Drop any cached user token when you disconnect, and on a connection.needs_reauth webhook.
Troubleshooting
- A read-only agent still triggers Google’s restricted-scope review: gmail.readonly is restricted, and so are gmail.compose and gmail.modify. gmail.send is the only scope on this connector that is merely sensitive, so a send-only agent is the one shape that avoids the restricted review. Google says that review uses the App Defense Alliance CASA framework, has to be repeated at least every 12 months, and can take several weeks.
- A user in a managed Google Workspace tenant can be blocked no matter how your app is verified, because the admin controls which apps reach Workspace data and can restrict high-risk Gmail scopes for the whole organizational unit.
- While the Google consent screen is External and its publishing status is still Testing, refresh tokens expire after seven days, which reads in production as an integration that works for a week and then stops.
- Tool ids are vendor-prefixed here. google_gmail_archive_message belongs to gmail, not to a provider called google, so match the first two name segments when you attribute a tool to a provider.
- Consent completed but tools/list comes back empty: diff the authorize URL’s scope= parameter against the connection row’s granted_scopes before blaming the console. The URL tells you what was actually requested, and a scope never requested can never be granted.
- Every connect fails with “B2B2C OAuth callback URL not configured”: the Redirect URL on the agent’s Connect & webhooks page is empty. It is checked first, so it masks every other misconfiguration.
- Calls return 200 and nothing happens: an external-user token was posted to /mcp instead of /mcp/external. Both answer 200, so this one fails silently — pin the route with a test.
- An unknown provider name returns 400 with the list of valid names. Read that error; it is accurate. Provider names are surfaces rather than vendors.
Gmail-side requirements checked against Gmail API OAuth scopes (restricted vs sensitive) (2026-10-29), Restricted scope verification (2026-10-29), Refresh token expiration (2026-10-29), Control which apps access Google Workspace data (2026-10-29).
Connecting Gmail in practice
Almost every Gmail scope an agent needs is on Google’s restricted list, so a third-party server holding those tokens has to pass an annual App Defense Alliance security assessment before general users can connect, and Google says that can take several weeks. Quota is charged in units rather than requests, and messages.send costs 100 against 6,000 units per minute per user, so the practical ceiling is about sixty sends a minute per mailbox.
Scopes that draw scrutiny
https://mail.google.com/Restricted. "Read, compose, send, and permanently delete all your email from Gmail", which is the widest grant Gmail has.https://www.googleapis.com/auth/gmail.readonlyRestricted. Reads all mail and settings, so it pulls in the security assessment even for a read-only agent.https://www.googleapis.com/auth/gmail.modifyRestricted. Read, compose and send without permanent delete, the usual choice for an assistant, and still assessed.https://www.googleapis.com/auth/gmail.settings.sharingRestricted. Manages sensitive mail-sharing settings such as delegation.https://www.googleapis.com/auth/gmail.sendSensitive rather than restricted, so it needs verification but not the annual assessment.
Rate limits
- 6,000 quota units per minute per user per project.
- 1,200,000 quota units per minute per project.
- Per-method cost: messages.send 100, threads.get 40, messages.get 20, drafts.create 10, messages.list 5, labels.list 1.
- 80,000,000 quota units per day per project is the billing threshold.
- 500 recipients per message.
Who has to approve
In Google Workspace an admin sets each app in Admin console API controls to Trusted, Limited, specific Google data, or Blocked, and can restrict a predefined list of high-risk OAuth scopes for Gmail in particular. An app that has not been configured shows up as an "Apps pending review" request, which the admin resolves per organizational unit rather than per user.
Worth knowing
- While the OAuth consent screen is External and its publishing status is still Testing, refresh tokens expire after 7 days, unless the only scopes requested are a subset of name, email and profile.
- Refresh tokens also stop working after six months of non-use, and for Gmail scopes specifically they are revoked when the user changes their account password.
- Brand verification has to be completed before you can even submit the scopes for data-access verification, so the two reviews are sequential.
- The current quota page publishes only per-minute and per-day figures. There is no per-user-per-second number to design against.
Checked against Gmail API scopes (2026-09-29), Gmail API usage limits (2026-09-29), Restricted scope verification (2026-09-29), Refresh token expiration (2026-09-29), Workspace app access control (2026-09-29)
What an agent can do
Each action is granted on its own. An agent allowed to read is not thereby allowed to write, and the scope beside each row is what the acting user must have connected for it to run at all.
Often connected alongside
Put Gmail behind one governed endpoint.
Same permissions, same audit trail, whatever else you connect next.