> ## Documentation Index
> Fetch the complete documentation index at: https://docs.truv.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Building with AI

> Connect Claude Code, Codex, or Cursor to Truv docs via MCP for accurate API integrations

Connect your AI coding tool to Truv's MCP server. It searches the docs and retrieves full page content on demand, so you get correct auth headers, status enums, and webhook handlers without pasting context manually.

***

## Connect the MCP server

The Truv MCP server runs at `https://docs.truv.com/mcp`. It exposes two tools: **search** across all documentation and **retrieve** the full content of any page by path.

<Tabs>
  <Tab title="Claude Code">
    ```bash theme={null}
    claude mcp add --transport http truv-api https://docs.truv.com/mcp
    ```
  </Tab>

  <Tab title="Codex">
    Add to `~/.codex/config.toml`:

    ```toml theme={null}
    [mcp_servers.truv-api]
    url = "https://docs.truv.com/mcp"
    ```
  </Tab>

  <Tab title="Cursor">
    Add to `~/.cursor/mcp.json`:

    ```json theme={null}
    {
      "mcpServers": {
        "truv-api": {
          "url": "https://docs.truv.com/mcp"
        }
      }
    }
    ```
  </Tab>
</Tabs>

Test it by starting a new chat and asking: *"What headers does the Truv API use for authentication?"*

***

## Context files

Truv publishes two static context files following the [llms.txt standard](https://llmstxt.org). Use these to seed `CLAUDE.md` / `AGENTS.md`, paste into a prompt, or as a fallback when MCP isn't available.

| File                                                   | Size     | Use case                                                                           |
| ------------------------------------------------------ | -------- | ---------------------------------------------------------------------------------- |
| [`llms.txt`](https://docs.truv.com/llms.txt)           | \~3.5 KB | Structured overview with links to docs sections                                    |
| [`llms-full.txt`](https://docs.truv.com/llms-full.txt) | \~18 KB  | Everything inlined: auth, endpoints, schemas, enums, webhooks, sandbox credentials |

<Accordion title="What's in llms-full.txt">
  * Authentication pattern (headers, base URL, SDK init)
  * All products and when to use each integration method
  * Complete integration code for Embedded Orders and User Token flows
  * Connection lifecycle with every status and error state
  * Webhook event types with example payloads and signature verification
  * Field-level data reference for Income & Employment, Employment, and Assets reports
  * Every enum value: job types, pay frequencies, deposit types, account types, income units
  * All API endpoints grouped by resource
  * Sandbox test credentials for every scenario
</Accordion>

### Seed your rules file

Drop this into `CLAUDE.md`, `AGENTS.md`, or `.cursorrules` so your AI tool follows Truv conventions without re-deriving them each time:

```md theme={null}
# Truv API conventions
- Base URL: https://prod.truv.com/v1/ (credentials select sandbox vs production)
- Auth headers: X-Access-Client-Id and X-Access-Secret (never Authorization: Bearer)
- Money amounts are decimal strings, e.g. "50000.00"
- Products: income, employment, assets, deposit_switch, pll

## Bridge (frontend)
- Embedded Orders: initialize TruvBridge with isOrder: true
- User Token flows (e.g. Deposit Switch): initialize WITHOUT isOrder
- Callbacks: onSuccess, onLoad, onEvent, onClose
- Errors surface in onEvent with type=ERROR and an ErrorData payload — there is no onError callback

## Statuses
- Task lifecycle: new → login → mfa → parse → full_parse → done
- Income/employment emit full_parse (base data) before done; assets (VOA) emit done only
- Error statuses: login_error, mfa_error, account_locked, unavailable

## Webhooks
- Verify the X-WEBHOOK-SIGN header: HMAC-SHA256 of the raw request body, format v1={hash}
- Respond with 2xx within 10 seconds; dedupe on webhook_id

## Enums (report output)
- pay_frequency: M, SM, W, BW, A, SA, C
- income_unit: YEARLY, MONTHLY, WEEKLY, DAILY, HOURLY
- job_type: F, P, S, D, C, V
- account_type: C, S — deposit_type: E, P, A
- Deposit Switch INPUT (deposit_details) uses words instead: account_type checking/savings, deposit_type entire/percent/amount
```

***

## Reference repos

Clone these repos and point your AI tool at the source for working reference implementations.

* [**demo-apps**](https://github.com/truvhq/demo-apps): Full-stack demo apps covering Embedded Orders, Hosted Orders, Document Processing, and more
* [**quickstart**](https://github.com/truvhq/quickstart): Minimal end-to-end integration in Node.js, Python, Ruby, Go, and C#
* [**demo-ios**](https://github.com/truvhq/demo-ios) / [**demo-android**](https://github.com/truvhq/demo-android) / [**demo-react-native**](https://github.com/truvhq/demo-react-native) / [**demo-flutter**](https://github.com/truvhq/demo-flutter): Mobile SDK samples

***

## What AI commonly gets wrong

| What AI guesses                                               | Correct value                                                                                                                                                                   |
| ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Authorization: Bearer {token}`                               | `X-Access-Client-Id` and `X-Access-Secret` headers                                                                                                                              |
| Status: `complete`, `success`, `finished`                     | `done` (task statuses: `new`, `login`, `mfa`, `parse`, `full_parse`, `done`)                                                                                                    |
| Product: `voie`, `voe`, `voa`                                 | `income`, `employment`, `assets`                                                                                                                                                |
| `TruvBridge.init({ bridgeToken })` for orders                 | Must include `isOrder: true`                                                                                                                                                    |
| Separate sandbox URL                                          | Same URL: `https://prod.truv.com/v1/`, credentials determine environment                                                                                                        |
| Webhook signature: raw HMAC                                   | Format: `v1={hmac_sha256_hex}` in `X-WEBHOOK-SIGN` header                                                                                                                       |
| Income amounts as numbers                                     | Strings: `"50000.00"`                                                                                                                                                           |
| Pay frequency: `biweekly`, `monthly`                          | Codes: `BW`, `M`, `SM`, `W`                                                                                                                                                     |
| Deposit Switch input uses report codes (`C`/`S`, `E`/`P`/`A`) | Input `deposit_details` uses words: `account_type` is `checking`/`savings`, `deposit_type` is `entire`/`percent`/`amount`. Only the report output uses the single-letter codes. |
| Fetch the report when status is `done`                        | Income and employment fire `full_parse` (base data) before `done`; assets (VOA) only fire `done`                                                                                |

***

## Prompting tips

Copy these prompts directly or adapt for your use case.

<AccordionGroup>
  <Accordion title="Create an Embedded Orders integration">
    ```
    Build a server endpoint that creates a Truv Embedded Order for income and employment
    verification. Use the Truv API with X-Access-Client-Id and X-Access-Secret headers.
    Return the bridge_token to the frontend. Then build a frontend that initializes
    TruvBridge with isOrder: true and handles onSuccess, onClose, and onEvent callbacks
    (errors surface in onEvent with type=ERROR and an ErrorData payload -- there is no onError callback).
    ```
  </Accordion>

  <Accordion title="Set up webhook handling">
    ```
    Create a webhook endpoint for Truv that:
    1. Verifies the X-WEBHOOK-SIGN header using HMAC-SHA256 with my API secret (format: v1={hash})
    2. Handles task-status-updated events - fetch the income report when status is "done"
    3. Handles error statuses: login_error, mfa_error, account_locked, unavailable
    4. Uses webhook_id for idempotency
    5. Responds within 10 seconds
    ```
  </Accordion>

  <Accordion title="Add Deposit Switch">
    ```
    Build a Deposit Switch integration using Truv's User Token flow (NOT Embedded Orders).
    Create a bridge token with product_type "deposit_switch" and include the target bank
    account details (account_number, routing_number, bank_name, account_type, deposit_type).
    Initialize TruvBridge WITHOUT the isOrder flag.
    ```
  </Accordion>

  <Accordion title="Poll for a report without webhooks">
    ```
    Build a server-side poller that fetches a Truv income report via
    GET /v1/links/{link_id}/income/report/ using X-Access-Client-Id and
    X-Access-Secret headers. Poll until the link status is full_parse or done;
    stop on error, no_data, or unavailable. Respect the documented rate limit.
    ```
  </Accordion>

  <Accordion title="Refresh an existing connection">
    ```
    Trigger a Truv data refresh for an existing link without re-prompting the user.
    Create a refresh task at POST /v1/refresh/tasks/ for the stored access_token,
    then handle the task-status-updated webhook the same way as the initial run.
    ```
  </Accordion>

  <Accordion title="Parse income report data">
    ```
    Write a function that takes a Truv income verification report and extracts:
    - Current employer name, job title, start_date, is_active status, and pay_frequency
    - Most recent pay statement: gross_pay, net_pay, pay_date, gross_pay_ytd
    - Annual income breakdown by year from annual_income_summary
    - All bank accounts (bank_accounts) with routing_number and deposit_type
    Use the exact field names from the Truv API docs.
    ```
  </Accordion>
</AccordionGroup>

***

## Next steps

<CardGroup cols={2}>
  <Card title="Quickstart" icon="bolt" href="/developers/quickstart">
    Create your first verification in minutes
  </Card>

  <Card title="Embedded Orders" icon="code" href="/developers/integration/embedded-orders/overview">
    Full integration walkthrough
  </Card>

  <Card title="Testing & Sandbox" icon="flask" href="/developers/testing/test-credentials">
    Test credentials and sandbox environment
  </Card>

  <Card title="API Reference" icon="book" href="/api-reference">
    Complete endpoint documentation
  </Card>
</CardGroup>
