> ## Documentation Index
> Fetch the complete documentation index at: https://breadbox-mintlify-7401d007.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Mint a hosted-link session

> Creates a hosted-link session and returns the URL an end-user should
open in their browser to add a new bank connection. The response
carries a one-time-only bearer `token` and a fully-qualified `url`
(scheme + host + `/link/<token>`). The token is **never** echoed back
by `GET /connections/link/{id}` — capture it from this response and
keep the URL alongside it.

- `provider` is optional. Empty means the hosted page presents a picker.
- `expires_in_seconds` is clamped to [0, 3600]. `0` (or missing)
  selects the default of 900s (15 minutes).
- Action is always `link` on this endpoint. Relink (re-authenticating
  an existing connection) is exposed separately via
  `POST /connections/{id}/relink`.

**Requires `full_access` scope.**




## OpenAPI

````yaml https://raw.githubusercontent.com/canalesb93/breadbox/main/openapi.yaml post /api/v1/connections/link
openapi: 3.1.0
info:
  title: Breadbox REST API
  version: 1.0.0
  summary: Self-hosted financial-data REST API for households and AI agents.
  description: >
    Machine-readable contract for the Breadbox REST API. Every `/api/v1/*`
    endpoint

    declared on the production chi router is represented here. The companion
    prose

    document at `docs/api-reference.md` may lag this spec; when in doubt, this
    file

    is canonical.


    ## Authentication


    All `/api/v1/*` endpoints require an API key passed via the `X-API-Key`
    header.

    Keys carry one of two scopes:


    - `read_only` — may call any read endpoint (`GET`).

    - `full_access` — may call read endpoints **and** all write endpoints
      (`POST`, `PATCH`, `PUT`, `DELETE`, plus a handful of `GET`s like `/api-keys`
      and `/users/{user_id}/login` that return sensitive data).

    Endpoints requiring `full_access` are flagged with the phrase **Requires

    `full_access` scope.** in their description. OpenAPI does not natively

    distinguish scopes on a single API-key scheme, so the enforcement boundary
    is

    documented per-operation rather than encoded in the security block.


    ## Amount convention


    Transaction amounts use `NUMERIC(12,2)` and are paired with
    `iso_currency_code`.

    Positive = money out (debits, purchases, fees). Negative = money in
    (credits,

    deposits, refunds). Never sum across `iso_currency_code`.


    ## Identifiers


    Every entity has both a UUID `id` and an 8-character base62 `short_id`. REST

    responses include both. Path parameters that accept `{id}` accept either
    form;

    short IDs are usually preferable for humans.


    ## Pagination


    Cursor pagination is used on transaction-shaped lists. Pass the previous

    response's `next_cursor` as `?cursor=` to fetch the next page. Bounded

    resources (accounts, users, connections, categories) return bare arrays.


    ## Errors


    All error responses share the envelope `{ "error": { "code": "...",

    "message": "..." } }`. Codes are stable contracts in `UPPER_SNAKE_CASE`.
  contact:
    name: Breadbox
    url: https://breadbox.sh
  license:
    name: AGPL-3.0-only
    url: https://www.gnu.org/licenses/agpl-3.0.html
servers:
  - url: https://breadbox.example.com
    description: Self-hosted Breadbox instance (replace host with your deployment).
security:
  - apiKeyAuth: []
tags:
  - name: Health
    description: Liveness and readiness probes. No authentication.
  - name: Version
    description: Server version metadata.
  - name: Auth
    description: Device-code grant and the unauthenticated headless bootstrap probe.
  - name: Accounts
    description: Household bank accounts synced from providers.
  - name: Transactions
    description: Cursor-paginated transactions, counts, summaries, and merchant rollups.
  - name: Comments
    description: Conversation comments attached to a transaction.
  - name: Annotations
    description: >-
      Activity-timeline events for a transaction (category changes, comments,
      tags, system events).
  - name: Tags
    description: Free-form labels applied to transactions.
  - name: Categories
    description: Two-level category tree, import/export, and merges.
  - name: Connections
    description: >-
      Bank-side links (Plaid items, Teller enrollments, CSV-import buckets) and
      the hosted-link page that mints them.
  - name: Sync
    description: Manual sync triggers, sync history, and per-provider health.
  - name: Rules
    description: Categorization rule engine with retroactive apply and preview.
  - name: Account Links
    description: >-
      Dependent-to-primary reconciliation links and transaction match
      management.
  - name: Reports
    description: Agent-submitted reports and the household read/unread state.
  - name: Users
    description: Household members and the login accounts attached to them.
  - name: API Keys
    description: Scoped credentials for REST and MCP clients.
  - name: Settings
    description: Provider credentials and other app-config knobs.
  - name: Counterparties
    description: >-
      The canonical, cross-provider "other side" of a charge (merchants and
      non-merchants), with manual enrichment.
  - name: Workflows
    description: >-
      Scheduled Claude Agent SDK definitions, run history, transcripts, and
      prompt blocks.
  - name: Webhooks
    description: Stored webhook events and on-demand replay.
paths:
  /api/v1/connections/link:
    post:
      tags:
        - Connections
      summary: Mint a hosted-link session
      description: |
        Creates a hosted-link session and returns the URL an end-user should
        open in their browser to add a new bank connection. The response
        carries a one-time-only bearer `token` and a fully-qualified `url`
        (scheme + host + `/link/<token>`). The token is **never** echoed back
        by `GET /connections/link/{id}` — capture it from this response and
        keep the URL alongside it.

        - `provider` is optional. Empty means the hosted page presents a picker.
        - `expires_in_seconds` is clamped to [0, 3600]. `0` (or missing)
          selects the default of 900s (15 minutes).
        - Action is always `link` on this endpoint. Relink (re-authenticating
          an existing connection) is exposed separately via
          `POST /connections/{id}/relink`.

        **Requires `full_access` scope.**
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateHostedLinkRequest'
      responses:
        '201':
          description: Hosted-link session created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateHostedLinkResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/NotFound'
components:
  schemas:
    CreateHostedLinkRequest:
      type: object
      required:
        - user_id
      properties:
        user_id:
          type: string
          description: UUID or short_id of the household user the link is for.
        provider:
          type: string
          description: |
            Optional. Empty / omitted lets the hosted page display a picker.
          enum:
            - ''
            - plaid
            - teller
        single_use:
          type: boolean
          default: false
          description: When true, the session burns after the first successful link.
        redirect_url:
          type: string
          description: Optional URL the hosted page redirects to after completion.
        label:
          type: string
          description: Optional human-readable label for the agent's audit timeline.
        expires_in_seconds:
          type: integer
          minimum: 0
          maximum: 3600
          description: |
            TTL in seconds. `0` (or omitted) selects the default of 900 (15
            minutes). Values above 3600 are rejected.
    CreateHostedLinkResponse:
      allOf:
        - $ref: '#/components/schemas/HostedLinkSession'
        - type: object
          required:
            - token
            - url
          properties:
            token:
              type: string
              description: |
                Plaintext bearer token. Returned **exactly once** at session
                creation; never echoed back by `GET /connections/link/{id}`.
            url:
              type: string
              format: uri
              description: |
                Fully-qualified URL the end-user should open. Built from the
                request scheme + host + `/link/<token>`.
    HostedLinkSession:
      type: object
      description: |
        A hosted-link session is the agent-facing record of a "share this URL
        with the user so they can connect a bank in their browser" flow.
        Returned by `GET /connections/link/{id}` and (extended with `token`
        and `url`) by `POST /connections/link`.
      properties:
        id:
          type: string
        short_id:
          type: string
        user_id:
          type: string
        provider:
          type: string
          description: |
            `"plaid"`, `"teller"`, or empty string. Empty means the hosted page
            shows a picker so the user chooses a provider.
          enum:
            - ''
            - plaid
            - teller
        action:
          type: string
          enum:
            - link
            - relink
        connection_id:
          type: string
          description: >-
            Present only for `action: "relink"` — the connection being
            re-authenticated.
        single_use:
          type: boolean
        redirect_url:
          type: string
          description: Optional URL the hosted page redirects to after completion.
        label:
          type: string
          description: Optional human-readable label shown in the agent's audit timeline.
        status:
          type: string
          enum:
            - pending
            - active
            - completed
            - failed
            - expired
            - consumed
        error_code:
          type: string
          description: 'Present only on `status: "failed"`.'
        error_message:
          type: string
          description: 'Present only on `status: "failed"`.'
        result_connection_ids:
          type: array
          items:
            type: string
          description: |
            UUIDs of the bank connections the user added during the session.
            Always present; empty array until at least one connection has been
            recorded.
        expires_at:
          type: string
          format: date-time
        started_at:
          type: string
          format: date-time
          nullable: true
          description: >-
            Stamped when the hosted page first transitions the session to
            `active`.
        completed_at:
          type: string
          format: date-time
          nullable: true
          description: Stamped when the session reaches `completed` or `failed`.
        created_at:
          type: string
          format: date-time
    ErrorEnvelope:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              description: Stable UPPER_SNAKE_CASE error code.
            message:
              type: string
  responses:
    BadRequest:
      description: Invalid input.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
    NotFound:
      description: Resource not found.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
  securitySchemes:
    apiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
      description: |
        Breadbox API key with format `bb_<base62>`. Carries either `read_only`
        or `full_access` scope. Write endpoints (and a handful of sensitive
        reads — `/api-keys`, `/users/{user_id}/login`) require `full_access`;
        endpoints that require it are flagged in their description.

````