> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/azfar-imtiaz/PayPulse-Cloud/llms.txt
> Use this file to discover all available pages before exploring further.

# iOS integration

> How the PayPulse iOS app integrates with Google Sign-In for Gmail OAuth 2.0.

Gmail authorization in PayPulse is initiated entirely on the iOS device. The backend never participates in the OAuth authorization code exchange — it only receives the resulting tokens.

## Google Sign-In SDK

The iOS app uses the [Google Sign-In SDK for iOS](https://developers.google.com/identity/sign-in/ios). The SDK handles:

* Presenting the native Google consent screen.
* Managing the OAuth authorization code exchange with Google's servers.
* Returning an access token, optional refresh token, and token metadata to the app.

The app is configured with an **iOS client ID** from Google Cloud Console. Because this is a native mobile client, it is classified as a **public OAuth client** — no client secret is required or used.

<Note>
  iOS OAuth credentials (client ID) are separate from server-side OAuth credentials. The iOS client ID is stored in AWS Secrets Manager under `Google-OAuth-Client-ID` and is read by Lambda functions when they need to refresh tokens. No client secret exists for the iOS client; Google's token endpoint accepts refresh requests from public clients without one.
</Note>

## Native iOS OAuth flow

<Steps>
  <Step title="User initiates Gmail connection">
    The user taps the "Connect Gmail" button in the PayPulse app. The app calls `GIDSignIn.sharedInstance.signIn(...)` with the `gmail.readonly` scope.
  </Step>

  <Step title="Google consent screen">
    The Google Sign-In SDK opens a secure in-app browser session (ASWebAuthenticationSession) displaying Google's consent screen. The user reviews the requested permissions and approves.
  </Step>

  <Step title="Tokens returned to the app">
    Google's servers exchange the authorization code for tokens and return them to the SDK. The app receives an `access_token`, a `refresh_token` (on first authorization), `expires_in`, and the granted `scope`.
  </Step>

  <Step title="Tokens sent to backend">
    The app immediately sends the tokens to the backend via the store-tokens endpoint.
  </Step>
</Steps>

## The `/v1/auth/gmail-tokens` endpoint

The iOS app posts token data to this endpoint immediately after the user grants consent. The request must include a valid PayPulse JWT in the `Authorization` header.

**Method**: `POST`\
**Path**: `/v1/auth/gmail-tokens`\
**Authentication**: Bearer JWT (from PayPulse login)

### Request body

```json request body theme={null}
{
  "access_token": "ya29.a0AfB_...",
  "refresh_token": "1//0gABC...",
  "expires_in": 3600,
  "scope": [
    "https://www.googleapis.com/auth/gmail.readonly",
    "https://www.googleapis.com/auth/userinfo.email",
    "https://www.googleapis.com/auth/userinfo.profile"
  ],
  "email": "user@gmail.com"
}
```

| Field           | Type      | Required | Description                                              |
| --------------- | --------- | -------- | -------------------------------------------------------- |
| `access_token`  | string    | Yes      | Short-lived OAuth access token from Google Sign-In       |
| `refresh_token` | string    | No       | Long-lived refresh token; present on first authorization |
| `expires_in`    | integer   | No       | Token lifetime in seconds (defaults to `3600`)           |
| `scope`         | string\[] | No       | Array of granted OAuth scopes                            |
| `email`         | string    | No       | User's Google email address                              |

The endpoint also accepts `application/x-www-form-urlencoded` bodies for compatibility.

### Response

```json success response (201) theme={null}
{
  "message": "Gmail OAuth tokens stored successfully!",
  "data": {
    "google_email": "user@gmail.com",
    "scope": "https://www.googleapis.com/auth/gmail.readonly ...",
    "account_switch": false,
    "message": "First Gmail connection"
  }
}
```

The `account_switch` field is `true` when the user connects a different Google account than the one previously stored. The iOS app can use this to display a warning.

## Gmail connection status in user profile

The `GET /v1/user/me` endpoint returns a `gmail_account_connected` boolean field that reflects whether the user has OAuth tokens stored in Secrets Manager:

```json user profile response theme={null}
{
  "message": "User profile retrieved successfully",
  "data": {
    "name": "Jane Smith",
    "email": "jane@example.com",
    "created_on": "2024-11-01T10:00:00Z",
    "gmail_account_connected": true
  }
}
```

The iOS app uses `gmail_account_connected` to decide whether to show the "Connect Gmail" button or the connected Gmail address. The check is performed by looking up the secret `gmail/user/{user_id}` in Secrets Manager — if it exists, the account is considered connected.
