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

# Connect a mailbox

> `{kind: "forwarding"}`: a new address `<token>@INBOUND_MAIL_DOMAIN` to forward deals to (a Gmail filter, an Outlook rule), and an inbound secret for providers that post mail themselves. `{kind: "gmail", auth: "delegation", address}`: a mailbox in a Workspace domain that authorized the platform's service account (scope gmail.readonly); access is checked and the watch started now. `{kind: "gmail", auth: "oauth", address}`: returns `authorize_url`; the mailbox is connected when Google returns. Needs the `email_intake` module.



## OpenAPI

````yaml /openapi.json post /v1/mailboxes
openapi: 3.1.0
info:
  title: parser_backend
  summary: >-
    MCA packet parsing with GPT-6 Luna (OpenRouter), verified ledgers and
    underwriting metrics
  description: >

    MCA document parsing: merchant packets in (upload or email), verified
    bank-statement ledgers, ISO

    applications and underwriting metrics out.


    **How a packet is read**


    1. *Intake* - files validated by content (PDF, PNG, JPEG), PDF
    safety-parsed, images converted to PDF;
       email attachments extracted from every MIME part.
    2. *Split* - each PDF is split into documents (bank statement, merchant
    application, tax return, ...) by
       per-page classification and statement boundaries.
    3. *Read* - a statement with a text layer is read by the **layout engine**:
    tables rebuilt from the text
       layer's geometry become the ledger JSON, with no model call. Pages without a text layer, and any statement
       whose layout read does not pass the gate, are rendered at 300 DPI and read by **GPT-6 Luna** through
       OpenRouter with a strict JSON schema at full image resolution (Luna's answer is the OCR): one owned page per
       call, neighbours as context, fanned out in parallel; the same answer categorizes every row. An image-read
       ledger is accepted only when a second, independent image read agrees on every amount, date and balance.
    4. *Gate* - a ledger is **verified** only when it reconciles to the cent
       (`opening + credits - debits = closing`), reproduces the bank's printed totals and keeps every running
       balance chain. If it still fails after the image read it is returned as `review_required`, never as data.
    5. *Categorize* - a category and counterparty per row: revenue, MCA funding
    / payment, loan, NSF, overdraft,
       returned item, transfers, payroll, taxes, ... or unknown. Image reads return them with the OCR; a
       layout-engine ledger goes to GPT-6 Luna once as JSON (rows grouped by description, with counts, amounts and
       dates). Deterministic rules cross-check every row.
    6. *Aggregate* - accounts and statement months (missing months flagged); MCA
    and loan positions decided by
       GPT-6 Luna over the packet's possible financing streams and checked against the rows (cadence
       cross-checks); monthly summaries, and the withhold, EBITDA and revenue math.
    7. *Packet* - the files are one submission (`result.submission_packet`): its
    typed documents in order, which
       ones the decision rests on and why the others are excluded (duplicates, failed or unreconciled reads,
       unclassified documents, another business's statement), the merchant's details with their sources,
       month-by-month coverage, whether the statements are one unbroken history, the balance chain across
       statements, undisclosed accounts and cross-document fraud signals.

    Every Luna call is metered (prompt, cached, completion and reasoning tokens;
    provider-reported cost) and

    every answer is replay-cached: a re-sent document or window costs nothing.


    **Integrating**


    * *Authentication*: `Authorization: Bearer <credential>` (or `X-API-Key`) on
    every `/v1` route. The credential
      is an API key (`pk_live_...`, created with `POST /v1/api-keys`, scoped to permissions) or a WorkOS AuthKit
      access token (a person, with the permissions of their role). Each belongs to one tenant; jobs, caches,
      webhooks and settings are tenant-scoped. Errors are `{"error": {"code", "message", "request_id"}}`.
    * *Submit*: `POST /v1/parse` (multipart) or `POST /v1/intake/email` (raw
    MIME). The answer is `202` with a
      `job_id` and `status_url`, or the finished job when `wait` seconds suffice. Send an `Idempotency-Key` to
      make a retry return the same job.
    * *Get the result*: register a webhook once (`POST /v1/webhooks`) and
    receive `job.completed`,
      `job.review_required` or `job.failed` when each job ends, signed with the endpoint's secret; then fetch
      `GET /v1/jobs/{job_id}`. Or poll that route (`?wait=` long-polls). Every job ends in one of those three
      states, and its event is stored with it: a job that runs past `JOB_TIMEOUT_SECONDS`, or that the service
      stopped during too many runs, fails with its `job.failed` event.
    * *Status*: `completed` - every check passed; `review_required` - the result
    is usable but
      `review_reasons` name what a person should look at; `failed` - nothing could be processed (`error`).
  version: 0.1.0
servers:
  - url: https://api.parser-app.com
security: []
tags:
  - name: parse
    description: Submit documents for parsing
  - name: email
    description: Submit a raw email; its attachments are parsed as one packet
  - name: jobs
    description: Poll jobs and read results
  - name: underwriting
    description: Withhold, EBITDA and capacity calculator
  - name: webhooks
    description: Signed job events pushed to your endpoint, retried until delivered
  - name: usage
    description: Token usage, cost and service metrics
  - name: identity
    description: 'Who is calling: tenant, permissions, modules'
  - name: tenant
    description: This tenant's settings
  - name: api-keys
    description: 'Scoped API keys: create, rotate, revoke'
  - name: mailboxes
    description: Forwarding addresses and Gmail mailboxes, and each message's outcome
  - name: emails
    description: 'Every inbound email tracked: its thread, raw .eml, tags and erasure'
  - name: integrations
    description: Connections to the tenant's CRM and other systems, fed by job events
  - name: audit
    description: Every change made in the tenant
  - name: platform
    description: Tenants across the platform (platform:admin)
  - name: health
    description: Liveness and readiness
paths:
  /v1/mailboxes:
    post:
      tags:
        - mailboxes
      summary: Connect a mailbox
      description: >-
        `{kind: "forwarding"}`: a new address `<token>@INBOUND_MAIL_DOMAIN` to
        forward deals to (a Gmail filter, an Outlook rule), and an inbound
        secret for providers that post mail themselves. `{kind: "gmail", auth:
        "delegation", address}`: a mailbox in a Workspace domain that authorized
        the platform's service account (scope gmail.readonly); access is checked
        and the watch started now. `{kind: "gmail", auth: "oauth", address}`:
        returns `authorize_url`; the mailbox is connected when Google returns.
        Needs the `email_intake` module.
      operationId: create_mailbox_v1_mailboxes_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MailboxCreate'
        required: true
      responses:
        '201':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MailboxCreated'
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
          description: Forbidden
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
          description: Not Found
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
      security:
        - APIKeyHeader: []
        - HTTPBearer: []
components:
  schemas:
    MailboxCreate:
      properties:
        kind:
          type: string
          enum:
            - forwarding
            - gmail
            - imap
            - m365
          title: Kind
        auth:
          anyOf:
            - type: string
              enum:
                - delegation
                - oauth
            - type: 'null'
          title: Auth
          description: >-
            gmail only: delegation (the funder's Workspace authorized our
            service account) or oauth (a mailbox of the platform's own
            Workspace)
        address:
          anyOf:
            - type: string
              maxLength: 320
            - type: 'null'
          title: Address
          description: 'gmail, imap, m365: the mailbox''s address'
        imap:
          anyOf:
            - $ref: '#/components/schemas/ImapAccess'
            - type: 'null'
          description: 'imap only: the server and login'
        organization:
          anyOf:
            - type: string
              maxLength: 200
            - type: 'null'
          title: Organization
          description: 'm365 only: the funder''s Microsoft tenant id or domain'
        label:
          type: string
          maxLength: 200
          minLength: 1
          title: Label
          description: >-
            gmail only: only messages with this label (INBOX, or one a filter
            applies)
          default: INBOX
        settings:
          $ref: '#/components/schemas/MailboxSettings'
      additionalProperties: false
      type: object
      required:
        - kind
      title: MailboxCreate
    MailboxCreated:
      properties:
        mailbox:
          $ref: '#/components/schemas/MailboxOut'
        inbound_secret:
          anyOf:
            - type: string
            - type: 'null'
          title: Inbound Secret
          description: >-
            forwarding: the secret a mail provider signs POST /v1/intake/email
            with (X-Mailbox-ID); shown only now
        authorize_url:
          anyOf:
            - type: string
            - type: 'null'
          title: Authorize Url
          description: 'gmail oauth: open it to grant read access'
      additionalProperties: false
      type: object
      required:
        - mailbox
      title: MailboxCreated
    ErrorResponse:
      properties:
        error:
          $ref: '#/components/schemas/ErrorBody'
      additionalProperties: false
      type: object
      required:
        - error
      title: ErrorResponse
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: '#/components/schemas/ValidationError'
          type: array
          title: Detail
      type: object
      title: HTTPValidationError
    ImapAccess:
      properties:
        host:
          type: string
          maxLength: 255
          minLength: 1
          title: Host
        port:
          type: integer
          maximum: 65535
          minimum: 1
          title: Port
          default: 993
        username:
          type: string
          maxLength: 320
          minLength: 1
          title: Username
        password:
          type: string
          maxLength: 1000
          minLength: 1
          title: Password
          description: Write-only; sealed under the master key
        ssl:
          type: boolean
          title: Ssl
          default: true
        folder:
          type: string
          maxLength: 200
          minLength: 1
          title: Folder
          default: INBOX
      additionalProperties: false
      type: object
      required:
        - host
        - username
        - password
      title: ImapAccess
    MailboxSettings:
      properties:
        auto_parse:
          type: boolean
          title: Auto Parse
          description: 'Off: messages are recorded, no job is started'
          default: true
        internal_domains:
          items:
            type: string
          type: array
          maxItems: 50
          title: Internal Domains
          description: This mailbox's staff domains, besides the tenant's
        allowed_sender_domains:
          items:
            type: string
          type: array
          maxItems: 50
          title: Allowed Sender Domains
          description: >-
            forwarding only: take mail forwarded from these domains (and their
            subdomains) only, judged by the envelope sender: the mail system
            that forwards to the address, e.g. funder.com for a Gmail filter or
            Outlook rule of deals@funder.com. Other mail is ignored
            (sender_not_allowed). Empty: any sender
        store_raw_email:
          type: boolean
          title: Store Raw Email
          description: >-
            Keep each message's raw .eml (`GET /v1/emails/{email_id}/raw`). Off:
            only its envelope is tracked. Never kept for mail refused or from a
            sender not allowed
          default: true
        default_tags:
          items:
            type: string
            description: 'Trimmed and lowercased, then 1-64 of a-z 0-9 _ : -'
            examples:
              - client:acme
          type: array
          maxItems: 20
          title: Default Tags
          description: Tags every email this mailbox receives starts with, e.g. client:acme
      additionalProperties: false
      type: object
      title: MailboxSettings
    MailboxOut:
      properties:
        id:
          type: string
          title: Id
        kind:
          type: string
          title: Kind
        auth:
          anyOf:
            - type: string
            - type: 'null'
          title: Auth
        address:
          type: string
          title: Address
        label:
          type: string
          title: Label
        status:
          type: string
          enum:
            - pending
            - active
            - paused
            - reauth_required
            - disconnected
          title: Status
        settings:
          $ref: '#/components/schemas/MailboxSettings'
        watch_expires_at:
          anyOf:
            - type: string
              format: date-time
            - type: 'null'
          title: Watch Expires At
        last_sync_at:
          anyOf:
            - type: string
              format: date-time
            - type: 'null'
          title: Last Sync At
        last_error:
          anyOf:
            - type: string
            - type: 'null'
          title: Last Error
        created_at:
          type: string
          format: date-time
          title: Created At
      additionalProperties: false
      type: object
      required:
        - id
        - kind
        - auth
        - address
        - label
        - status
        - settings
        - watch_expires_at
        - last_sync_at
        - last_error
        - created_at
      title: MailboxOut
    ErrorBody:
      properties:
        code:
          type: string
          title: Code
          description: unauthenticated, forbidden, not_found, conflict, limit_reached, ...
        message:
          type: string
          title: Message
        request_id:
          type: string
          title: Request Id
          description: Also in the X-Request-ID response header
      additionalProperties: false
      type: object
      required:
        - code
        - message
        - request_id
      title: ErrorBody
    ValidationError:
      properties:
        loc:
          items:
            anyOf:
              - type: string
              - type: integer
          type: array
          title: Location
        msg:
          type: string
          title: Message
        type:
          type: string
          title: Error Type
        input:
          title: Input
        ctx:
          type: object
          title: Context
      type: object
      required:
        - loc
        - msg
        - type
      title: ValidationError
  securitySchemes:
    APIKeyHeader:
      type: apiKey
      description: API key
      in: header
      name: X-API-Key
    HTTPBearer:
      type: http
      description: API key or AuthKit access token
      scheme: bearer

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.