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

# Enrich transaction

> Enriches a transaction and returns structured transaction + entity data.



## OpenAPI

````yaml https://api.triqai.com/openapi-public.json post /v1/transactions/enrich
openapi: 3.1.0
info:
  title: Triqai Transaction Enrichment API
  version: 1.4.3
  description: >
    The Triqai API provides transaction enrichment capabilities for financial
    applications.


    ## Authentication


    All API endpoints require an API key in the `X-API-Key` header.


    ## Rate Limiting


    Per-organization limits use a token bucket (RPS) plus a concurrent in-flight
    cap.

    Headers may include:

    - `X-RateLimit-Limit`

    - `X-RateLimit-Remaining`

    - `X-RateLimit-Reset`

    - `X-RateLimit-Scope` (`rps` or `concurrency`)

    - `X-RateLimit-Concurrency-Limit`

    - `X-RateLimit-Concurrency-Remaining`


    `Retry-After` is returned in **seconds** on throttled responses.


    ## Idempotency


    You must supply `Idempotency-Key` (or `X-Idempotency-Key`) for enrichment
    requests so retries preserve billing and persistence identity.

    Keys must match `^[a-zA-Z0-9_-]{1,64}$`.

    Reusing a key returns `409`:

    - `state=completed`: request with this key already finished

    - `state=in_progress`: request with this key is still processing
    (`Retry-After` included)
  contact:
    name: Triqai Contact
    url: https://triqai.com/contact
  license:
    name: Proprietary
    url: https://triqai.com/terms
servers:
  - url: https://api.triqai.com
    description: Production
security:
  - ApiKeyAuth: []
tags:
  - name: Health
  - name: API
  - name: Transactions
  - name: Categories
  - name: Entities
  - name: Issue Reports
paths:
  /v1/transactions/enrich:
    post:
      tags:
        - Transactions
      summary: Enrich transaction
      description: Enriches a transaction and returns structured transaction + entity data.
      operationId: enrichTransaction
      parameters:
        - name: Idempotency-Key
          in: header
          required: true
          description: >-
            Required retry identity. `X-Idempotency-Key` is also accepted and
            must match when both are sent.
          schema:
            type: string
            minLength: 1
            maxLength: 64
            pattern: ^[a-zA-Z0-9_-]{1,64}$
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/EnrichRequest'
            examples:
              expense:
                summary: Basic expense enrichment
                value:
                  title: AMAZON MKTPLACE PMTS AMZN.COM/BILL WA
                  country: US
                  type: expense
              income:
                summary: Basic income enrichment
                value:
                  title: PAYPAL REFUND EBAY INC
                  country: US
                  type: income
              with_prefilled_merchant:
                summary: Pre-fill known merchant to skip AI extraction
                value:
                  title: 'SQ *STARBUCKS #1234 AMSTERDAM'
                  country: NL
                  type: expense
                  options:
                    merchant:
                      name: Starbucks
              with_prefilled_location:
                summary: Pre-fill known location context
                value:
                  title: 'SQ *STARBUCKS #1234 AMSTERDAM'
                  country: NL
                  type: expense
                  options:
                    merchant:
                      name: Starbucks
                    location:
                      cityName: Amsterdam
              with_filters:
                summary: Skip intermediary and location extraction
                value:
                  title: PAYPAL *NETFLIX.COM
                  country: US
                  type: expense
                  options:
                    filters:
                      noIntermediary: true
                      noLocation: true
      responses:
        '200':
          description: Enrichment completed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EnrichSuccessResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '403':
          $ref: '#/components/responses/Forbidden'
        '409':
          $ref: '#/components/responses/DuplicateRequest'
        '422':
          $ref: '#/components/responses/ValidationError'
        '429':
          $ref: '#/components/responses/RateLimited'
        '499':
          $ref: '#/components/responses/ClientDisconnected'
        '500':
          $ref: '#/components/responses/InternalError'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
        '504':
          $ref: '#/components/responses/GatewayTimeout'
components:
  schemas:
    EnrichRequest:
      type: object
      required:
        - title
        - country
        - type
      properties:
        title:
          type: string
          minLength: 1
          maxLength: 256
          description: Raw transaction description from the bank statement.
        country:
          type: string
          pattern: ^[A-Za-z]{2}$
          description: >
            ISO 3166-1 alpha-2 country code (e.g., US, GB, DE).

            Both upper and lowercase are accepted; the API normalizes to
            uppercase.
        type:
          $ref: '#/components/schemas/TransactionType'
        options:
          $ref: '#/components/schemas/EnrichRequestOptions'
    EnrichSuccessResponse:
      type: object
      required:
        - success
        - partial
        - data
        - meta
      properties:
        success:
          type: boolean
          enum:
            - true
        partial:
          type: boolean
        data:
          $ref: '#/components/schemas/EnrichmentData'
        meta:
          $ref: '#/components/schemas/EnrichMeta'
    TransactionType:
      type: string
      enum:
        - expense
        - income
    EnrichRequestOptions:
      type: object
      description: >
        Optional enrichment controls. Use `filters` to skip specific entity
        types,

        or pre-fill known entity data to improve accuracy and reduce latency.


        **Mutual exclusivity:** a filter flag (e.g. `noMerchant`) cannot be
        combined with

        pre-filled data for the same entity type.
      properties:
        filters:
          $ref: '#/components/schemas/EnrichmentFilterOptions'
        merchant:
          $ref: '#/components/schemas/PrefilledMerchant'
        location:
          $ref: '#/components/schemas/PrefilledLocation'
        intermediaries:
          type: array
          description: Up to 5 pre-filled intermediary entries.
          maxItems: 5
          items:
            $ref: '#/components/schemas/PrefilledIntermediary'
      allOf:
        - if:
            required:
              - filters
            properties:
              filters:
                type: object
                required:
                  - noMerchant
                properties:
                  noMerchant:
                    const: true
          then:
            not:
              required:
                - merchant
              properties:
                merchant:
                  type: object
                  anyOf:
                    - required:
                        - id
                    - required:
                        - name
                    - required:
                        - domain
        - if:
            required:
              - filters
            properties:
              filters:
                type: object
                required:
                  - noIntermediary
                properties:
                  noIntermediary:
                    const: true
          then:
            not:
              required:
                - intermediaries
              properties:
                intermediaries:
                  type: array
                  minItems: 1
        - if:
            required:
              - filters
            properties:
              filters:
                type: object
                required:
                  - noLocation
                properties:
                  noLocation:
                    const: true
          then:
            not:
              required:
                - location
              properties:
                location:
                  type: object
                  anyOf:
                    - required:
                        - cityName
                    - required:
                        - physicalLocation
                    - required:
                        - coordinates
                    - required:
                        - streetName
                    - required:
                        - storeNumber
    EnrichmentData:
      type: object
      required:
        - transaction
        - entities
      properties:
        transaction:
          $ref: '#/components/schemas/TransactionData'
        entities:
          type: array
          items:
            $ref: '#/components/schemas/EntityResult'
    EnrichMeta:
      allOf:
        - $ref: '#/components/schemas/ResponseMeta'
        - type: object
          required:
            - categoryVersion
          properties:
            categoryVersion:
              type: string
            transactionId:
              type: string
              format: uuid
              description: >-
                Stable transaction row ID for this enrichment request (when
                persisted).
            errors:
              type: array
              items:
                $ref: '#/components/schemas/EnrichmentErrorCode'
    ErrorResponse:
      type: object
      required:
        - success
        - error
        - meta
      properties:
        success:
          type: boolean
          enum:
            - false
        error:
          $ref: '#/components/schemas/ErrorObject'
        meta:
          $ref: '#/components/schemas/ResponseMeta'
    DuplicateRequestErrorResponse:
      type: object
      required:
        - success
        - error
      properties:
        success:
          type: boolean
          enum:
            - false
        error:
          type: object
          required:
            - code
            - message
            - details
          properties:
            code:
              type: string
              enum:
                - DUPLICATE_REQUEST
            message:
              type: string
            details:
              type: object
              required:
                - requestId
              properties:
                requestId:
                  type: string
                state:
                  type: string
                  enum:
                    - in_progress
                    - completed
                retryAfterSeconds:
                  type: integer
                  minimum: 1
    ClientDisconnectedErrorResponse:
      type: object
      required:
        - success
        - error
      properties:
        success:
          type: boolean
          enum:
            - false
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              enum:
                - CLIENT_DISCONNECTED
            message:
              type: string
    EnrichmentFilterOptions:
      type: object
      description: Disable extraction of specific entity types from the transaction title.
      properties:
        noMerchant:
          type: boolean
          description: When `true`, merchant extraction is skipped entirely.
        noIntermediary:
          type: boolean
          description: When `true`, intermediary (payment processor) extraction is skipped.
        noLocation:
          type: boolean
          description: When `true`, location extraction is skipped.
    PrefilledMerchant:
      type: object
      description: >
        Supply known merchant data to bypass or augment merchant extraction.

        When `id` is provided, the merchant is resolved by primary key (returns
        422 if not found).

        `name` and `domain` perform best-effort lookups and fall through
        gracefully.
      properties:
        id:
          type: string
          format: uuid
          description: Existing Triqai merchant UUID.
        name:
          type: string
          description: Merchant display name for lookup.
        domain:
          type: string
          description: Merchant domain (e.g. `starbucks.com`).
    PrefilledLocation:
      type: object
      description: >
        Supply known location context to improve enrichment accuracy.

        When `coordinates` are provided and `cityName` is not set, the API
        resolves them to a

        place name via reverse-geocoding and uses it as a location hint for AI
        title dissection.
      properties:
        cityName:
          type: string
          description: City name where the transaction occurred.
        physicalLocation:
          type: boolean
          description: Whether the transaction happened at a physical location.
        coordinates:
          type: object
          description: >
            GPS coordinates of the transaction. When provided without
            `cityName`, coordinates are

            reverse-geocoded to resolve a place name. If no location is detected
            from transaction

            title text, the reverse-geocoded place becomes the fallback
            location.
          required:
            - lat
            - lng
          properties:
            lat:
              type: number
              minimum: -90
              maximum: 90
            lng:
              type: number
              minimum: -180
              maximum: 180
        streetName:
          type: string
          description: Street name of the transaction location.
        storeNumber:
          type: string
          description: Store or branch number.
    PrefilledIntermediary:
      type: object
      description: >
        Supply known intermediary (payment processor) data.

        When `id` is provided, the intermediary is resolved by primary key
        (returns 422 if not found).

        `name` and `domain` perform best-effort lookups.
      properties:
        id:
          type: string
          format: uuid
          description: Existing Triqai intermediary UUID.
        name:
          type: string
          description: Intermediary display name for lookup.
        domain:
          type: string
          description: Intermediary domain (e.g. `paypal.com`).
      anyOf:
        - required:
            - id
        - required:
            - name
        - required:
            - domain
    TransactionData:
      type: object
      required:
        - category
        - confidence
      properties:
        category:
          $ref: '#/components/schemas/CategoryStructure'
        confidence:
          $ref: '#/components/schemas/ConfidenceWithReasons'
    EntityResult:
      type: object
      required:
        - type
        - role
        - confidence
        - data
      properties:
        type:
          type: string
          enum:
            - merchant
            - location
            - intermediary
            - person
        role:
          type: string
        confidence:
          $ref: '#/components/schemas/ConfidenceWithReasons'
        data:
          oneOf:
            - $ref: '#/components/schemas/MerchantEntityData'
            - $ref: '#/components/schemas/LocationData'
            - $ref: '#/components/schemas/IntermediaryData'
            - $ref: '#/components/schemas/PersonData'
    ResponseMeta:
      type: object
      required:
        - generatedAt
        - requestId
        - version
      properties:
        generatedAt:
          type: string
          format: date-time
        requestId:
          type: string
        version:
          type: string
      additionalProperties: true
    EnrichmentErrorCode:
      type: string
      enum:
        - location_timeout
        - merchant_scrape_failed
        - processor_lookup_failed
        - rate_limited
        - internal_error
        - title_dissection_failed
    ErrorObject:
      type: object
      required:
        - code
        - message
      properties:
        code:
          type: string
        message:
          type: string
        details:
          $ref: '#/components/schemas/ErrorDetails'
    CategoryStructure:
      type: object
      required:
        - primary
        - secondary
        - tertiary
        - confidence
      properties:
        primary:
          $ref: '#/components/schemas/Category'
        secondary:
          oneOf:
            - $ref: '#/components/schemas/Category'
            - type: 'null'
        tertiary:
          oneOf:
            - $ref: '#/components/schemas/Category'
            - type: 'null'
        confidence:
          $ref: '#/components/schemas/ConfidenceWithReasons'
    ConfidenceWithReasons:
      type: object
      required:
        - value
        - reasons
      properties:
        value:
          type: integer
          minimum: 0
          maximum: 100
        reasons:
          type: array
          items:
            type: string
    MerchantEntityData:
      type: object
      required:
        - id
        - name
        - alias
        - icon
        - color
        - website
        - domain
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
        alias:
          type: array
          items:
            type: string
        keywords:
          type: array
          description: Search keywords associated with this merchant. May be absent.
          items:
            type: string
        icon:
          oneOf:
            - type: string
              format: uri
            - type: 'null'
        description:
          type: string
          description: Brief description of the merchant. May be absent.
        color:
          oneOf:
            - type: string
            - type: 'null'
        website:
          oneOf:
            - type: string
              format: uri
            - type: 'null'
        domain:
          oneOf:
            - type: string
            - type: 'null'
    LocationData:
      type: object
      required:
        - id
        - name
        - formatted
        - phoneNumber
        - structured
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
          description: Location display name (store/branch name).
        formatted:
          type: string
          description: Human-readable formatted address string.
        phoneNumber:
          oneOf:
            - type: string
            - type: 'null'
          description: Phone number if available.
        website:
          oneOf:
            - type: string
              format: uri
            - type: 'null'
          description: Location-specific website URL. May be absent.
        priceRange:
          oneOf:
            - type: string
            - type: 'null'
          description: Price range indicator (e.g. "$", "$$"). May be absent.
        rating:
          oneOf:
            - $ref: '#/components/schemas/LocationRating'
            - type: 'null'
          description: User rating data from external sources. May be absent.
        structured:
          $ref: '#/components/schemas/StructuredAddress'
    IntermediaryData:
      type: object
      required:
        - id
        - name
        - icon
        - description
        - color
        - website
        - domain
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
        icon:
          oneOf:
            - type: string
              format: uri
            - type: 'null'
        description:
          oneOf:
            - type: string
            - type: 'null'
        color:
          oneOf:
            - type: string
            - type: 'null'
        website:
          oneOf:
            - type: string
              format: uri
            - type: 'null'
        domain:
          oneOf:
            - type: string
            - type: 'null'
    PersonData:
      type: object
      required:
        - displayName
      properties:
        displayName:
          type: string
    ErrorDetails:
      type: object
      properties:
        fieldErrors:
          type: object
          additionalProperties:
            type: array
            items:
              type: string
      additionalProperties: true
    Category:
      type: object
      required:
        - name
        - code
      properties:
        name:
          type: string
        code:
          $ref: '#/components/schemas/CategoryCode'
    LocationRating:
      type: object
      required:
        - average
        - count
        - source
      properties:
        average:
          type: number
        count:
          type: integer
        source:
          type: string
    StructuredAddress:
      type: object
      required:
        - street
        - city
        - state
        - postalCode
        - country
        - countryName
        - coordinates
        - timezone
      properties:
        street:
          type: string
        city:
          type: string
        state:
          type: string
        postalCode:
          type: string
        country:
          type: string
        countryName:
          type: string
        coordinates:
          $ref: '#/components/schemas/Coordinates'
        timezone:
          type: string
    CategoryCode:
      type: object
      required:
        - mcc
        - sic
        - naics
      properties:
        mcc:
          type: integer
        sic:
          type: integer
        naics:
          type: integer
    Coordinates:
      type: object
      required:
        - latitude
        - longitude
      properties:
        latitude:
          type: number
          format: double
        longitude:
          type: number
          format: double
  responses:
    Unauthorized:
      description: Authentication failed or missing credentials
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            error:
              code: authentication_error
              message: API key is required
            meta:
              generatedAt: '2026-02-16T00:00:00Z'
              requestId: f353ca91-4fc5-49f2-9b9e-304f83d11914
              version: 1.1.2
    InsufficientCredits:
      description: Insufficient credits
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            error:
              code: insufficient_credits
              message: Insufficient credits
            meta:
              generatedAt: '2026-02-16T00:00:00Z'
              requestId: f353ca91-4fc5-49f2-9b9e-304f83d11914
              version: 1.1.2
    Forbidden:
      description: Authenticated but not authorized
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            error:
              code: authorization_error
              message: Access denied
            meta:
              generatedAt: '2026-02-16T00:00:00Z'
              requestId: f353ca91-4fc5-49f2-9b9e-304f83d11914
              version: 1.1.2
    DuplicateRequest:
      description: Duplicate idempotent request (completed or in-progress)
      headers:
        Retry-After:
          schema:
            type: integer
          description: Present when `details.state=in_progress`; value is in seconds.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/DuplicateRequestErrorResponse'
    ValidationError:
      description: Request validation failed
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            error:
              code: validation_error
              message: Validation failed
              details:
                fieldErrors:
                  title:
                    - Title is required
            meta:
              generatedAt: '2026-02-16T00:00:00Z'
              requestId: f353ca91-4fc5-49f2-9b9e-304f83d11914
              version: 1.1.2
    RateLimited:
      description: Rate limit exceeded
      headers:
        X-RateLimit-Limit:
          schema:
            type: integer
          description: Requests per second (sustained rate)
        X-RateLimit-Remaining:
          schema:
            type: integer
          description: Current token-bucket capacity available
        X-RateLimit-Reset:
          schema:
            type: string
            format: date-time
          description: Timestamp when token bucket refills
        X-RateLimit-Scope:
          schema:
            type: string
            enum:
              - rps
              - concurrency
          description: Active limiting dimension
        X-RateLimit-Concurrency-Limit:
          schema:
            type: integer
          description: Max concurrent requests for the org
        X-RateLimit-Concurrency-Remaining:
          schema:
            type: integer
          description: Remaining concurrent request slots
        Retry-After:
          schema:
            type: integer
          description: Seconds until retry is allowed
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            error:
              code: rate_limited
              message: Rate limit exceeded
            meta:
              generatedAt: '2026-02-16T00:00:00Z'
              requestId: f353ca91-4fc5-49f2-9b9e-304f83d11914
              version: 1.1.2
    ClientDisconnected:
      description: Client closed request before completion
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ClientDisconnectedErrorResponse'
    InternalError:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    ServiceUnavailable:
      description: Service temporarily unavailable
      headers:
        Retry-After:
          schema:
            type: integer
          description: Seconds until retry is allowed
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    GatewayTimeout:
      description: Upstream timeout
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
      description: Public API key

````