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

# Extract an invoice or receipt

> Retrieves one remote document over HTTP or HTTPS, validates the source, extracts an invoice or receipt, persists the completed result, and records one document_extraction usage unit. Product entitlement and configured technical rate limits apply. Direct uploads are not supported.



## OpenAPI

````yaml /openapi/trade-document-v1.yaml post /v1/documents/extract
openapi: 3.1.0
info:
  title: The Wo Trade Document API
  version: 1.0.0
  description: >-
    Public contract for extracting structured data from remote invoices and
    receipts.
servers:
  - url: https://api.thewo.io
    description: Canonical The Wo production API origin.
security:
  - ApiKeyAuth: []
tags:
  - name: Trade Document
    description: Extract structured invoice and receipt data.
paths:
  /v1/documents/extract:
    post:
      tags:
        - Trade Document
      summary: Extract an invoice or receipt
      description: >-
        Retrieves one remote document over HTTP or HTTPS, validates the source,
        extracts an invoice or receipt, persists the completed result, and
        records one document_extraction usage unit. Product entitlement and
        configured technical rate limits apply. Direct uploads are not
        supported.
      operationId: extractTradeDocument
      parameters:
        - name: Idempotency-Key
          in: header
          required: false
          description: >-
            Optional client key for safely retrying the same logical request. A
            key is scoped to the customer, product, and operation. Reusing it
            with a different request returns 409.
          schema:
            type: string
            minLength: 1
            maxLength: 255
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ExtractDocumentRequest'
            examples:
              invoice:
                value:
                  documentUrl: https://example.com/documents/sample-invoice.pdf
                  expectedType: invoice
                  language: en
              receipt:
                value:
                  documentUrl: https://example.com/documents/sample-receipt.jpg
                  expectedType: receipt
                  language: pt
      responses:
        '201':
          description: Extraction completed and usage recorded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExtractDocumentResponse'
              examples:
                invoice:
                  $ref: '#/components/examples/InvoiceResponse'
                receipt:
                  $ref: '#/components/examples/ReceiptResponse'
        '400':
          description: Malformed JSON, invalid request object, or invalid Idempotency-Key.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponse'
              examples:
                invalidPayload:
                  $ref: '#/components/examples/InvalidRequestPayload'
                invalidIdempotencyKey:
                  $ref: '#/components/examples/InvalidIdempotencyKey'
                invalidJson:
                  $ref: '#/components/examples/InvalidJson'
        '401':
          description: API key is missing or invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponse'
              examples:
                missingApiKey:
                  $ref: '#/components/examples/MissingApiKey'
                invalidApiKey:
                  $ref: '#/components/examples/InvalidApiKey'
        '403':
          description: Customer access, product entitlement, or quota access is denied.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponse'
              examples:
                productNotEntitled:
                  $ref: '#/components/examples/ProductNotEntitled'
                quotaAccessDenied:
                  $ref: '#/components/examples/QuotaAccessDenied'
                customerAccessDenied:
                  $ref: '#/components/examples/CustomerAccessDenied'
        '409':
          description: >-
            Idempotency key conflicts with a different request or is in
            progress.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponse'
              examples:
                idempotencyConflict:
                  $ref: '#/components/examples/IdempotencyConflict'
                idempotencyInProgress:
                  $ref: '#/components/examples/IdempotencyInProgress'
        '413':
          description: Retrieved source exceeds configured maximum content size.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponse'
              examples:
                documentTooLarge:
                  $ref: '#/components/examples/DocumentTooLarge'
        '415':
          description: Retrieved content type is not supported.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponse'
              examples:
                unsupportedMedia:
                  $ref: '#/components/examples/UnsupportedMedia'
        '422':
          description: >-
            Request is invalid at application level, source is unsafe, or
            document type is unsupported.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponse'
              examples:
                invalidDocumentRequest:
                  $ref: '#/components/examples/InvalidDocumentRequest'
                sourceRejected:
                  $ref: '#/components/examples/DocumentSourceRejected'
                unsupportedDocument:
                  $ref: '#/components/examples/UnsupportedDocument'
        '429':
          description: Configured technical rate or commercial quota was exceeded.
          headers:
            Retry-After:
              description: >-
                Seconds to wait when the response is rate_limit_exceeded, when
                supplied.
              schema:
                type: integer
                minimum: 1
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponse'
              examples:
                rateLimitExceeded:
                  $ref: '#/components/examples/RateLimitExceeded'
                quotaExceeded:
                  $ref: '#/components/examples/QuotaExceeded'
        '500':
          description: Unexpected internal error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponse'
              examples:
                internalError:
                  $ref: '#/components/examples/InternalError'
        '502':
          description: Extraction failed or output did not match the public contract.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponse'
              examples:
                extractionFailed:
                  $ref: '#/components/examples/ExtractionFailed'
                invalidExtractionOutput:
                  $ref: '#/components/examples/InvalidExtractionOutput'
        '503':
          description: >-
            A required authentication, entitlement, rate limit, idempotency,
            quota, source, extraction, persistence, or usage service is
            unavailable.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponse'
              examples:
                serviceUnavailable:
                  $ref: '#/components/examples/ServiceUnavailable'
                quotaConfirmationFailed:
                  $ref: '#/components/examples/QuotaConfirmationFailed'
                quotaReleaseFailed:
                  $ref: '#/components/examples/QuotaReleaseFailed'
                sourceUnavailable:
                  $ref: '#/components/examples/DocumentSourceUnavailable'
                extractionUnavailable:
                  $ref: '#/components/examples/ExtractionUnavailable'
                persistenceFailed:
                  $ref: '#/components/examples/PersistenceFailed'
                usageRecordingFailed:
                  $ref: '#/components/examples/UsageRecordingFailed'
                rateLimitUnavailable:
                  $ref: '#/components/examples/RateLimitUnavailable'
                idempotencyUnavailable:
                  $ref: '#/components/examples/IdempotencyUnavailable'
                idempotencyReplayUnavailable:
                  $ref: '#/components/examples/IdempotencyReplayUnavailable'
      security:
        - ApiKeyAuth: []
components:
  schemas:
    ExtractDocumentRequest:
      type: object
      additionalProperties: false
      required:
        - documentUrl
      properties:
        documentUrl:
          type: string
          minLength: 1
          format: uri
          description: Absolute HTTP or HTTPS URL retrievable by The Wo.
          example: https://example.com/documents/sample-invoice.pdf
        expectedType:
          type: string
          enum:
            - invoice
            - receipt
          description: >-
            Optional expected type hint. Does not force the detected response
            type.
        language:
          type: string
          enum:
            - en
            - pt
            - es
          description: >-
            Optional supported source-language hint. It does not localize the
            canonical response vocabulary.
    ExtractDocumentResponse:
      type: object
      additionalProperties: false
      required:
        - id
        - status
        - documentType
        - extracted
        - missingFields
        - riskFlags
        - confidence
        - usage
        - createdAt
      properties:
        id:
          type: string
        status:
          const: completed
        documentType:
          type: string
          enum:
            - invoice
            - receipt
        extracted:
          oneOf:
            - $ref: '#/components/schemas/InvoiceExtraction'
            - $ref: '#/components/schemas/ReceiptExtraction'
        missingFields:
          type: array
          items:
            $ref: '#/components/schemas/MissingField'
        riskFlags:
          type: array
          items:
            $ref: '#/components/schemas/RiskFlag'
        confidence:
          type: number
          minimum: 0
          maximum: 1
        usage:
          type: object
          additionalProperties: false
          required:
            - operation
            - units
          properties:
            operation:
              const: document_extraction
            units:
              const: 1
        createdAt:
          type: string
          format: date-time
    ApiErrorResponse:
      type: object
      additionalProperties: false
      required:
        - error
      properties:
        error:
          type: object
          additionalProperties: false
          required:
            - code
            - message
            - requestId
          properties:
            code:
              type: string
            message:
              type: string
            requestId:
              type: string
            details:
              type: object
              additionalProperties:
                oneOf:
                  - type: string
                  - type: number
                  - type: boolean
                  - type: 'null'
    InvoiceExtraction:
      type: object
      additionalProperties: false
      required:
        - supplier
        - items
      properties:
        documentNumber:
          type: string
        issuedAt:
          type: string
          format: date
        supplier:
          $ref: '#/components/schemas/Party'
        buyer:
          $ref: '#/components/schemas/Party'
        subtotal:
          $ref: '#/components/schemas/Money'
        tax:
          $ref: '#/components/schemas/Money'
        total:
          $ref: '#/components/schemas/Money'
        items:
          type: array
          items:
            $ref: '#/components/schemas/LineItem'
    ReceiptExtraction:
      type: object
      additionalProperties: false
      required:
        - merchant
        - items
      properties:
        merchant:
          $ref: '#/components/schemas/Party'
        purchasedAt:
          type: string
          format: date
        subtotal:
          $ref: '#/components/schemas/Money'
        tax:
          $ref: '#/components/schemas/Money'
        total:
          $ref: '#/components/schemas/Money'
        items:
          type: array
          items:
            $ref: '#/components/schemas/LineItem'
    MissingField:
      type: string
      enum:
        - document_number
        - issued_at
        - supplier_name
        - supplier_tax_identifier
        - buyer_name
        - buyer_tax_identifier
        - merchant_name
        - merchant_tax_identifier
        - purchased_at
        - subtotal
        - tax
        - total
        - line_items
    RiskFlag:
      type: string
      enum:
        - document_type_mismatch
        - low_confidence_critical_field
        - inconsistent_totals
        - unreadable_section
        - incomplete_line_items
    Party:
      type: object
      additionalProperties: false
      properties:
        name:
          type: string
        taxIdentifier:
          type: string
    Money:
      type: object
      additionalProperties: false
      required:
        - minorUnits
        - currency
      properties:
        minorUnits:
          type: integer
        currency:
          type: string
          pattern: ^[A-Z]{3}$
    LineItem:
      type: object
      additionalProperties: false
      required:
        - description
      properties:
        description:
          type: string
        quantity:
          type: number
        unitPrice:
          $ref: '#/components/schemas/Money'
        lineTotal:
          $ref: '#/components/schemas/Money'
  examples:
    InvoiceResponse:
      value:
        id: trade_document_example_01
        status: completed
        documentType: invoice
        extracted:
          documentNumber: INV-2026-104
          issuedAt: '2026-10-19'
          supplier:
            name: Example Paper Goods
            taxIdentifier: SUP-104
          buyer:
            name: Northstar Workshop
          total:
            minorUnits: 245000
            currency: USD
          items:
            - description: Workshop materials
              quantity: 2
              unitPrice:
                minorUnits: 1000
                currency: USD
              lineTotal:
                minorUnits: 2000
                currency: USD
        missingFields:
          - buyer_tax_identifier
        riskFlags:
          - inconsistent_totals
        confidence: 0.93
        usage:
          operation: document_extraction
          units: 1
        createdAt: '2026-10-20T12:00:00.000Z'
    ReceiptResponse:
      value:
        id: trade_document_example_02
        status: completed
        documentType: receipt
        extracted:
          merchant:
            name: Example Market
            taxIdentifier: MER-204
          purchasedAt: '2026-10-19'
          subtotal:
            minorUnits: 5000
            currency: BRL
          total:
            minorUnits: 5000
            currency: BRL
          items:
            - description: Coffee
              quantity: 1.5
        missingFields:
          - tax
        riskFlags:
          - low_confidence_critical_field
        confidence: 0.72
        usage:
          operation: document_extraction
          units: 1
        createdAt: '2026-10-20T12:05:00.000Z'
    InvalidRequestPayload:
      value:
        error:
          code: invalid_request_payload
          message: Request body does not match the document extraction contract.
          requestId: req_123
    InvalidIdempotencyKey:
      value:
        error:
          code: invalid_idempotency_key
          message: Idempotency-Key must contain a single nonblank value.
          requestId: req_123
    InvalidJson:
      value:
        error:
          code: invalid_json
          message: Request body contains invalid JSON.
          requestId: req_123
    MissingApiKey:
      value:
        error:
          code: missing_api_key
          message: The x-api-key header is required.
          requestId: req_123
    InvalidApiKey:
      value:
        error:
          code: invalid_api_key
          message: The provided API key is invalid.
          requestId: req_123
    ProductNotEntitled:
      value:
        error:
          code: product_not_entitled
          message: The customer is not entitled to extract Trade Documents.
          requestId: req_123
    QuotaAccessDenied:
      value:
        error:
          code: quota_access_denied
          message: The customer cannot use the requested extraction quota.
          requestId: req_123
    CustomerAccessDenied:
      value:
        error:
          code: customer_access_denied
          message: Customer access is denied.
          requestId: req_123
    IdempotencyConflict:
      value:
        error:
          code: idempotency_conflict
          message: Idempotency key was used with a different request.
          requestId: req_123
    IdempotencyInProgress:
      value:
        error:
          code: idempotency_in_progress
          message: The idempotent request is still processing.
          requestId: req_123
    DocumentTooLarge:
      value:
        error:
          code: document_too_large
          message: The document exceeds the supported size limit.
          requestId: req_123
    UnsupportedMedia:
      value:
        error:
          code: unsupported_document_media
          message: The document media type is not supported.
          requestId: req_123
    InvalidDocumentRequest:
      value:
        error:
          code: invalid_document_request
          message: The document extraction request is invalid.
          requestId: req_123
    DocumentSourceRejected:
      value:
        error:
          code: document_source_rejected
          message: The document source is not allowed.
          requestId: req_123
    UnsupportedDocument:
      value:
        error:
          code: unsupported_document
          message: The document is not a supported invoice or receipt.
          requestId: req_123
    RateLimitExceeded:
      value:
        error:
          code: rate_limit_exceeded
          message: Too many requests.
          requestId: req_123
    QuotaExceeded:
      value:
        error:
          code: quota_exceeded
          message: Monthly operation quota has been exceeded.
          requestId: req_123
          details:
            operation: document_extraction
            requestedUnits: 1
    InternalError:
      value:
        error:
          code: internal_error
          message: An unexpected error occurred.
          requestId: req_123
    ExtractionFailed:
      value:
        error:
          code: extraction_failed
          message: The document could not be extracted.
          requestId: req_123
    InvalidExtractionOutput:
      value:
        error:
          code: invalid_extraction_output
          message: The extraction provider returned an invalid result.
          requestId: req_123
    ServiceUnavailable:
      value:
        error:
          code: api_key_authentication_unavailable
          message: The required service is temporarily unavailable.
          requestId: req_123
    QuotaConfirmationFailed:
      value:
        error:
          code: quota_confirmation_failed
          message: Extraction usage was recorded but quota confirmation failed.
          requestId: req_123
    QuotaReleaseFailed:
      value:
        error:
          code: quota_release_failed
          message: The extraction reservation could not be released.
          requestId: req_123
    DocumentSourceUnavailable:
      value:
        error:
          code: document_source_unavailable
          message: The document source could not be reached.
          requestId: req_123
    ExtractionUnavailable:
      value:
        error:
          code: extraction_unavailable
          message: Document extraction is temporarily unavailable.
          requestId: req_123
    PersistenceFailed:
      value:
        error:
          code: trade_document_persistence_failed
          message: The extraction result could not be stored.
          requestId: req_123
    UsageRecordingFailed:
      value:
        error:
          code: usage_recording_failed
          message: Extraction usage could not be recorded.
          requestId: req_123
    RateLimitUnavailable:
      value:
        error:
          code: rate_limit_unavailable
          message: Rate-limit evaluation is temporarily unavailable.
          requestId: req_123
    IdempotencyUnavailable:
      value:
        error:
          code: idempotency_unavailable
          message: Idempotency protection is temporarily unavailable.
          requestId: req_123
    IdempotencyReplayUnavailable:
      value:
        error:
          code: idempotency_replay_unavailable
          message: The original idempotent result cannot be restored.
          requestId: req_123
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key

````

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