Gmail Integration API
The Gmail integration enables organizations to send invoices directly via Gmail using OAuth2. The flow uses Google OAuth2 for authorization, Puppeteer for server-side PDF generation from invoice data, and the Gmail API to send the email with the PDF attachment.
Prerequisites
- A Google Cloud project with the Gmail API enabled
- OAuth2 credentials (Client ID & Client Secret) configured on the backend
- The organization must complete the OAuth2 consent flow before sending invoices
Architecture Overview
┌─────────┐ ┌──────────┐ ┌────────────┐ ┌───────────┐
│ Frontend │───▶│ Backend │───▶│ Puppeteer │───▶│ Gmail API │
│ │ │ │ │ (PDF Gen) │ │ (Send) │
└─────────┘ └──────────┘ └────────────┘ └───────────┘
│ ▲
│ ┌──────────────┐ │
└────────▶│ Google OAuth2 │─────────┘
└──────────────┘Endpoints
GET /api/gmail/:orgId/auth-url
Generate the Google OAuth2 authorization URL. Redirect the user to this URL to begin the consent flow.
Path Parameters
| Param | Type | Description |
|---|---|---|
orgId | string | Organization ID |
Response 200 OK
{
"success": true,
"authUrl": "https://accounts.google.com/o/oauth2/v2/auth?client_id=...&redirect_uri=...&scope=https://www.googleapis.com/auth/gmail.send&response_type=code&access_type=offline&prompt=consent"
}Scopes Requested
| Scope | Purpose |
|---|---|
https://www.googleapis.com/auth/gmail.send | Send emails on behalf of the user |
POST /api/gmail/:orgId/callback
Handle the OAuth2 callback after the user grants consent. Exchanges the authorization code for access & refresh tokens, which are securely stored for the organization.
Path Parameters
| Param | Type | Description |
|---|---|---|
orgId | string | Organization ID |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
code | string | Yes | Authorization code from Google |
state | string | No | State parameter for CSRF validation |
{
"code": "4/0AX4XfWh...",
"state": "random-state-string"
}Response 200 OK
{
"success": true,
"message": "Gmail connected successfully",
"email": "hotel@gmail.com"
}Token Storage
Refresh tokens are encrypted at rest and stored in the organization document. Access tokens are refreshed automatically when expired.
GET /api/gmail/:orgId/status
Check whether the organization has a valid Gmail connection.
Path Parameters
| Param | Type | Description |
|---|---|---|
orgId | string | Organization ID |
Response 200 OK
{
"success": true,
"connected": true,
"email": "hotel@gmail.com",
"connectedAt": "2026-01-15T10:30:00.000Z"
}Disconnected State
{
"success": true,
"connected": false,
"email": null,
"connectedAt": null
}POST /api/gmail/:orgId/disconnect
Revoke the Gmail OAuth2 tokens and disconnect the integration for the organization.
Path Parameters
| Param | Type | Description |
|---|---|---|
orgId | string | Organization ID |
Response 200 OK
{
"success": true,
"message": "Gmail disconnected successfully"
}POST /api/gmail/:orgId/:invoiceId/send-invoice
Generate a PDF for the given invoice using Puppeteer and send it as a Gmail attachment to the guest's email address.
Path Parameters
| Param | Type | Description |
|---|---|---|
orgId | string | Organization ID |
invoiceId | string | Invoice ID |
Flow
- Fetch invoice data (line items, guest info, org details)
- Render invoice HTML template server-side
- Generate PDF via Puppeteer (
page.pdf()) - Upload PDF to Azure Blob Storage (temporary)
- Compose email with PDF attachment via Gmail API
- Send email to the guest's registered email address
- Clean up temporary PDF
Response 200 OK
{
"success": true,
"message": "Invoice sent successfully",
"sentTo": "guest@example.com",
"invoiceNumber": "INV-2026-0042"
}Error Scenarios
| Status | Condition |
|---|---|
400 | Invoice not found or missing guest email |
401 | Gmail not connected for this org |
502 | Gmail API or Puppeteer failure |
{
"success": false,
"message": "Gmail is not connected. Please authorize first."
}Integration Lifecycle
| Step | Action | Endpoint |
|---|---|---|
| 1 | Get authorization URL | GET /api/gmail/:orgId/auth-url |
| 2 | User grants consent | (Google OAuth2 consent screen) |
| 3 | Exchange code for tokens | POST /api/gmail/:orgId/callback |
| 4 | Verify connection | GET /api/gmail/:orgId/status |
| 5 | Send invoices | POST /api/gmail/:orgId/:invoiceId/send-invoice |
| 6 | Disconnect (if needed) | POST /api/gmail/:orgId/disconnect |
Error Responses
All endpoints follow the standard error format:
{
"success": false,
"message": "Descriptive error message"
}