> ## 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.

# Ingest latest rental invoice

> Fetch only the current month's rental invoice from Gmail and upload it to S3.

<Note>
  This endpoint is also triggered automatically by an EventBridge rule every weekday at 8:30 AM UTC. When invoked by EventBridge, it processes all registered users rather than a single authenticated user.
</Note>

## Authentication

All requests to this endpoint must include a valid JWT in the `Authorization` header.

```
Authorization: Bearer <token>
```

## Path parameters

<ParamField path="type" type="string" required>
  The invoice type. Must be `rental` for this endpoint.
</ParamField>

## What this endpoint does

This endpoint checks whether a rental invoice for the current calendar month already exists in DynamoDB. If not, it connects to the user's Gmail account and searches for the latest rental invoice email for the current month and year. If found, the PDF attachment is downloaded and uploaded to S3.

The Gmail account must be connected before calling this endpoint. See [Store Gmail tokens](/api-reference/auth/store-gmail-tokens).

## Response

<ResponseField name="message" type="string">
  A human-readable confirmation message describing the outcome:

  * `"Invoice for <month>/<year> found and ingested successfully!"` — invoice was fetched and uploaded (HTTP `201`).
  * `"Invoice for <month>/<year> has already been processed."` — invoice already exists (HTTP `200`).
  * `"Rental invoice for <month>/<year> has not been dispatched yet."` — no matching email found in inbox (HTTP `204`).
</ResponseField>

<ResponseField name="code" type="number">
  HTTP status code. `201` when a new invoice is ingested, `200` when already processed, `204` when not yet available.
</ResponseField>

<ResponseField name="data" type="null">
  Always `null` for this endpoint.
</ResponseField>

## Error responses

| Status | Error code              | Description                                                          |
| ------ | ----------------------- | -------------------------------------------------------------------- |
| `400`  | `INVALID_JSON`          | The request body is not valid JSON.                                  |
| `400`  | `MISSING_FIELDS`        | A required key is missing from the request.                          |
| `401`  | `INVALID_CREDENTIALS`   | The `Authorization` header is missing or the OAuth token is invalid. |
| `401`  | `TOKEN_EXPIRED`         | The JWT has expired.                                                 |
| `502`  | `DEPENDENCY_FAILURE`    | The Gmail API or a downstream service returned an error.             |
| `500`  | `INTERNAL_SERVER_ERROR` | An unexpected server-side error occurred.                            |

Error responses follow this structure:

```json theme={null}
{
  "error": {
    "code": "DEPENDENCY_FAILURE",
    "message": "Gmail API error"
  }
}
```

<RequestExample>
  ```bash cURL theme={null}
  curl --request POST \
    --url https://api.paypulse.io/v1/invoices/rental/ingest/latest \
    --header 'Authorization: Bearer <token>'
  ```
</RequestExample>

<ResponseExample>
  ```json 201 theme={null}
  {
    "message": "Invoice for 3/2025 found and ingested successfully!",
    "code": 201,
    "data": null
  }
  ```

  ```json 200 (already processed) theme={null}
  {
    "message": "Invoice for 3/2025 has already been processed.",
    "code": 200,
    "data": null
  }
  ```

  ```json 204 theme={null}
  {
    "message": "Rental invoice for 3/2025 has not been dispatched yet.",
    "code": 204,
    "data": null
  }
  ```

  ```json 502 theme={null}
  {
    "error": {
      "code": "DEPENDENCY_FAILURE",
      "message": "Gmail API error"
    }
  }
  ```
</ResponseExample>
