openapi: 3.0.3
info:
  title: Folio API
  version: 1.0.0
  description: 'Structured API access to US intellectual property data.



    Folio provides a single, consistent REST API over US IP data:

    USPTO trademarks, historical trademark and patent assignments, and

    TTAB proceedings.


    All responses are JSON. All authenticated endpoints require an `X-API-Key`

    header. Search endpoints use consistent `limit` / `offset` pagination and

    return `total` where it can be computed cheaply.


    Data freshness for USPTO-derived endpoints is reported via the

    `data_freshness` response field (the latest `transaction_date` observed in

    the trademark corpus) and, when the freshness probe itself fails, via the

    `X-Data-Freshness-Stale: true` response header.

    '
  contact:
    name: Folio Support
    url: https://folioapi.com
  license:
    name: Proprietary
servers:
  - url: https://folioapi.com
    description: Production
tags:
  - name: Health
    description: Service liveness.
  - name: Trademarks
    description: USPTO trademark search, detail, and prosecution history.
  - name: Historical Assignments
    description: USPTO bulk assignment records for trademarks and patents.
  - name: TTAB
    description: Trademark Trial and Appeal Board proceedings.
security:
  - apiKeyAuth: []
paths:
  /v1/health:
    get:
      tags:
        - Health
      summary: Health check
      description: Returns service status. Public — no API key required.
      operationId: getHealth
      security: []
      responses:
        '200':
          description: Service is healthy.
          content:
            application/json:
              schema:
                type: object
                required:
                  - status
                properties:
                  status:
                    type: string
                    enum:
                      - ok
  /v1/trademarks/search:
    get:
      tags:
        - Trademarks
      summary: Search USPTO trademarks
      description: 'Search the USPTO trademark corpus by owner, mark text, serial
        number,

        or combinations thereof. At least one of `owner_name`,

        `owner_name_exact`, `mark_name`, or `serial_number` is required.

        '
      operationId: searchTrademarks
      parameters:
        - name: owner_name
          in: query
          description: Trademark owner (party) name. Substring match (slow on large
            corpora; use for exploratory lookups).
          schema:
            type: string
            maxLength: 500
        - name: owner_name_exact
          in: query
          description: 'Trademark owner name for precise entity lookup. The input
            is

            normalized (lowercased, punctuation stripped, legal suffixes

            removed — `Inc`, `Corp`, `LLC`, etc.) and then matched exactly

            against the indexed normalized column. Equivalent legal-entity

            forms (`Acme Inc` / `Acme Corp` / `ACME`) collapse to the same

            match. Mutually exclusive with `owner_name`.

            '
          schema:
            type: string
            maxLength: 500
        - name: mark_name
          in: query
          description: Mark text. Substring match.
          schema:
            type: string
            maxLength: 500
        - name: serial_number
          in: query
          description: Exact USPTO serial number.
          schema:
            type: string
            maxLength: 500
        - name: intl_class
          in: query
          description: International classification code filter (e.g. `009`).
          schema:
            type: string
        - name: filing_date_from
          in: query
          description: Earliest filing date (YYYY-MM-DD or YYYYMMDD).
          schema:
            type: string
        - name: filing_date_to
          in: query
          description: Latest filing date (YYYY-MM-DD or YYYYMMDD).
          schema:
            type: string
        - name: status_alive_only
          in: query
          description: If `true`, restrict to live trademarks.
          schema:
            type: boolean
        - $ref: '#/components/parameters/Limit100'
        - $ref: '#/components/parameters/Offset'
      responses:
        '200':
          description: Matching trademarks.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TrademarkSearchResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/trademarks/{serial_number}:
    get:
      tags:
        - Trademarks
      summary: Get a trademark by serial number
      description: Full trademark record including owners, classifications, statements,
        and prosecution history.
      operationId: getTrademark
      parameters:
        - $ref: '#/components/parameters/SerialNumberPath'
      responses:
        '200':
          description: Trademark detail.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TrademarkDetail'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/trademarks/{serial_number}/events:
    get:
      tags:
        - Trademarks
      summary: Trademark prosecution history
      description: Paginated prosecution history events for a single trademark.
      operationId: getTrademarkEvents
      parameters:
        - $ref: '#/components/parameters/SerialNumberPath'
        - $ref: '#/components/parameters/Limit100'
        - $ref: '#/components/parameters/Offset'
      responses:
        '200':
          description: Prosecution history events.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TrademarkEventsResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/trademarks/historical/assignments:
    get:
      tags:
        - Historical Assignments
      summary: Search historical trademark assignments
      description: 'USPTO trademark assignment records from bulk files. At least one
        of

        `serial_number`, `party_name`, or `conv_group` is required.

        '
      operationId: searchTrademarkAssignments
      parameters:
        - name: serial_number
          in: query
          description: USPTO trademark serial number.
          schema:
            type: string
            maxLength: 500
        - name: party_name
          in: query
          description: Assignor or assignee name. Substring match.
          schema:
            type: string
            maxLength: 500
        - name: conv_group
          in: query
          description: Conveyance group filter.
          schema:
            type: string
            maxLength: 500
        - name: date_from
          in: query
          description: Earliest record date (YYYY-MM-DD or YYYYMMDD).
          schema:
            type: string
        - name: date_to
          in: query
          description: Latest record date (YYYY-MM-DD or YYYYMMDD).
          schema:
            type: string
        - $ref: '#/components/parameters/Limit100'
        - $ref: '#/components/parameters/Offset'
      responses:
        '200':
          description: Matching trademark assignments.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TMAssignmentSearchResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/patents/historical/assignments:
    get:
      tags:
        - Historical Assignments
      summary: Search historical patent assignments
      description: 'USPTO patent assignment records from bulk files. At least one
        of

        `patent_number`, `application_number`, or `party_name` is required.

        '
      operationId: searchPatentAssignments
      parameters:
        - name: patent_number
          in: query
          description: US patent number.
          schema:
            type: string
            maxLength: 500
        - name: application_number
          in: query
          description: US patent application number.
          schema:
            type: string
            maxLength: 500
        - name: party_name
          in: query
          description: Assignor or assignee name. Substring match.
          schema:
            type: string
            maxLength: 500
        - name: convey_type
          in: query
          description: Conveyance type filter.
          schema:
            type: string
            maxLength: 500
        - name: date_from
          in: query
          description: Earliest record date (YYYY-MM-DD or YYYYMMDD).
          schema:
            type: string
        - name: date_to
          in: query
          description: Latest record date (YYYY-MM-DD or YYYYMMDD).
          schema:
            type: string
        - $ref: '#/components/parameters/Limit100'
        - $ref: '#/components/parameters/Offset'
      responses:
        '200':
          description: Matching patent assignments.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PatAssignmentSearchResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/ttab/proceedings:
    get:
      tags:
        - TTAB
      summary: Search TTAB proceedings
      description: 'Search Trademark Trial and Appeal Board proceedings by serial
        number,

        party name, or proceeding number. At least one of `serial_number`,

        `party_name`, `party_name_exact`, or `proceeding_number` is required.

        '
      operationId: searchTTABProceedings
      parameters:
        - name: serial_number
          in: query
          description: USPTO trademark serial number referenced by the proceeding.
          schema:
            type: string
            maxLength: 500
        - name: party_name
          in: query
          description: TTAB party name. Substring match (slow on large corpora).
          schema:
            type: string
            maxLength: 500
        - name: party_name_exact
          in: query
          description: 'TTAB party name for precise entity lookup. Normalized

            (lowercased, punctuation stripped, legal suffixes removed)

            and matched exactly against the indexed normalized column.

            Mutually exclusive with `party_name`.

            '
          schema:
            type: string
            maxLength: 500
        - name: proceeding_number
          in: query
          description: Exact TTAB proceeding number.
          schema:
            type: string
            maxLength: 500
        - $ref: '#/components/parameters/Limit100'
        - $ref: '#/components/parameters/Offset'
      responses:
        '200':
          description: Matching TTAB proceedings.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TTABSearchResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/ttab/proceedings/{proceeding_number}:
    get:
      tags:
        - TTAB
      summary: Get a TTAB proceeding
      description: Full TTAB proceeding record including parties.
      operationId: getTTABProceeding
      parameters:
        - name: proceeding_number
          in: path
          required: true
          description: TTAB proceeding number.
          schema:
            type: string
      responses:
        '200':
          description: TTAB proceeding detail.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TTABDetail'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
components:
  securitySchemes:
    apiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
      description: 'API key, prefixed `fo_live_…`. Obtain from the pricing page on

        <https://folioapi.com>.

        '
  parameters:
    Limit50:
      name: limit
      in: query
      description: Maximum number of results to return (server-clamped to 50).
      schema:
        type: integer
        minimum: 0
        maximum: 50
        default: 50
    Limit100:
      name: limit
      in: query
      description: Maximum number of results to return (server-clamped to 100).
      schema:
        type: integer
        minimum: 0
        maximum: 100
        default: 50
    Offset:
      name: offset
      in: query
      description: Number of results to skip.
      schema:
        type: integer
        minimum: 0
        default: 0
    SerialNumberPath:
      name: serial_number
      in: path
      required: true
      description: USPTO trademark serial number.
      schema:
        type: string
  headers:
    RetryAfter:
      description: Seconds to wait before retrying.
      schema:
        type: integer
        minimum: 0
    DataFreshnessStale:
      description: Present and `true` when the freshness probe itself failed and the
        reported `data_freshness` value may be stale.
      schema:
        type: string
        enum:
          - 'true'
  responses:
    BadRequest:
      description: Invalid request parameters.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unauthorized:
      description: Missing or invalid API key.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    NotFound:
      description: Resource not found.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    RateLimited:
      description: Rate limit exceeded (per-second or per-day).
      headers:
        Retry-After:
          $ref: '#/components/headers/RetryAfter'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    InternalError:
      description: Unexpected server error.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  schemas:
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: string
          description: Human-readable error message.
    Pagination:
      type: object
      required:
        - limit
        - offset
      properties:
        total:
          type: integer
          nullable: true
          description: Total matching rows when cheaply computable; omitted otherwise.
        limit:
          type: integer
          minimum: 0
        offset:
          type: integer
          minimum: 0
    TrademarkSummary:
      type: object
      required:
        - serial_number
        - owners
        - classifications
      description: 'Summary of a USPTO trademark. Date fields are YYYYMMDD strings
        as

        stored in the USPTO bulk corpus (not ISO 8601).

        '
      properties:
        serial_number:
          type: string
        mark_text:
          type: string
          nullable: true
        status_code:
          type: string
          nullable: true
        filing_date:
          type: string
          nullable: true
          description: YYYYMMDD
        transaction_date:
          type: string
          nullable: true
          description: YYYYMMDD
        owners:
          type: array
          nullable: true
          items:
            type: string
        classifications:
          type: array
          nullable: true
          items:
            type: string
        goods_services:
          type: array
          items:
            type: string
    TrademarkOwner:
      type: object
      properties:
        party_name:
          type: string
          nullable: true
        owner_address:
          type: string
          nullable: true
        city:
          type: string
          nullable: true
        state:
          type: string
          nullable: true
        country:
          type: string
          nullable: true
        entity_type:
          type: string
          nullable: true
    TrademarkClass:
      type: object
      required:
        - intl_class
      properties:
        intl_class:
          type: string
        us_class:
          type: string
          nullable: true
        status_code:
          type: string
          nullable: true
        first_use_date:
          type: string
          nullable: true
          description: YYYYMMDD
        first_use_commerce:
          type: string
          nullable: true
          description: YYYYMMDD
    TrademarkStatement:
      type: object
      properties:
        type_code:
          type: string
          nullable: true
        text:
          type: string
          nullable: true
    TrademarkEvent:
      type: object
      properties:
        event_date:
          type: string
          nullable: true
          description: YYYYMMDD
        event_code:
          type: string
          nullable: true
        description:
          type: string
          nullable: true
    TrademarkSearchResponse:
      allOf:
        - $ref: '#/components/schemas/Pagination'
        - type: object
          required:
            - results
          properties:
            results:
              type: array
              items:
                $ref: '#/components/schemas/TrademarkSummary'
            data_freshness:
              type: string
              description: Latest `transaction_date` observed in the trademark corpus
                (YYYY-MM-DD).
    TrademarkDetail:
      type: object
      description: 'Full USPTO trademark record. Date fields are YYYYMMDD strings
        as

        stored in the USPTO bulk corpus (not ISO 8601).

        '
      required:
        - serial_number
        - amended_principal
        - amended_supplemental
        - international_reg
        - owners
        - classifications
      properties:
        serial_number:
          type: string
        mark_text:
          type: string
          nullable: true
        status_code:
          type: string
          nullable: true
        filing_date:
          type: string
          nullable: true
          description: YYYYMMDD
        registration_number:
          type: string
          nullable: true
        registration_date:
          type: string
          nullable: true
          description: YYYYMMDD
        transaction_date:
          type: string
          nullable: true
          description: YYYYMMDD
        mark_drawing_code:
          type: string
          nullable: true
        attorney_name:
          type: string
          nullable: true
        renewal_date:
          type: string
          nullable: true
          description: YYYYMMDD
        cancellation_code:
          type: string
          nullable: true
        cancellation_date:
          type: string
          nullable: true
          description: YYYYMMDD
        publication_date:
          type: string
          nullable: true
          description: YYYYMMDD
        amended_principal:
          type: boolean
        amended_supplemental:
          type: boolean
        international_reg:
          type: boolean
        owners:
          type: array
          nullable: true
          items:
            $ref: '#/components/schemas/TrademarkOwner'
        classifications:
          type: array
          nullable: true
          items:
            $ref: '#/components/schemas/TrademarkClass'
        statements:
          type: array
          items:
            $ref: '#/components/schemas/TrademarkStatement'
        events:
          type: array
          items:
            $ref: '#/components/schemas/TrademarkEvent'
        data_freshness:
          type: string
    TrademarkEventsResponse:
      allOf:
        - $ref: '#/components/schemas/Pagination'
        - type: object
          required:
            - serial_number
            - events
          properties:
            serial_number:
              type: string
            latest_transaction_date:
              type: string
              description: MAX(transaction_date) for this serial — per-record freshness.
                YYYYMMDD.
            events:
              type: array
              items:
                $ref: '#/components/schemas/TrademarkEvent'
            data_freshness:
              type: string
    AssignmentParty:
      type: object
      required:
        - party_name
      properties:
        party_name:
          type: string
        address:
          type: string
          nullable: true
        city:
          type: string
          nullable: true
        state:
          type: string
          nullable: true
        country:
          type: string
          nullable: true
    TMAssignment:
      type: object
      required:
        - reel_frame
      properties:
        reel_frame:
          type: string
        record_date:
          type: string
          nullable: true
          description: ISO date or raw USPTO string
        conveyances:
          type: array
          items:
            type: string
        assignors:
          type: array
          items:
            $ref: '#/components/schemas/AssignmentParty'
        assignees:
          type: array
          items:
            $ref: '#/components/schemas/AssignmentParty'
        serial_numbers:
          type: array
          items:
            type: string
    TMAssignmentSearchResponse:
      allOf:
        - $ref: '#/components/schemas/Pagination'
        - type: object
          required:
            - results
          properties:
            results:
              type: array
              items:
                $ref: '#/components/schemas/TMAssignment'
            coverage_note:
              type: string
    PatAssignment:
      type: object
      required:
        - reel_frame
      properties:
        reel_frame:
          type: string
        record_date:
          type: string
          nullable: true
          description: ISO date or raw USPTO string
        convey_type:
          type: string
          nullable: true
        assignors:
          type: array
          items:
            $ref: '#/components/schemas/AssignmentParty'
        assignees:
          type: array
          items:
            $ref: '#/components/schemas/AssignmentParty'
        patent_numbers:
          type: array
          items:
            type: string
        application_numbers:
          type: array
          items:
            type: string
    PatAssignmentSearchResponse:
      allOf:
        - $ref: '#/components/schemas/Pagination'
        - type: object
          required:
            - results
          properties:
            results:
              type: array
              items:
                $ref: '#/components/schemas/PatAssignment'
            coverage_note:
              type: string
    TTABParty:
      type: object
      properties:
        role_code:
          type: string
          nullable: true
        party_name:
          type: string
          nullable: true
        serial_number:
          type: string
          nullable: true
        mark_text:
          type: string
          nullable: true
    TTABProceeding:
      type: object
      description: 'TTAB proceeding summary. Date fields are YYYYMMDD strings from
        the

        USPTO TTAB bulk corpus (not ISO 8601).

        '
      required:
        - proceeding_number
      properties:
        proceeding_number:
          type: string
        transaction_date:
          type: string
          nullable: true
          description: YYYYMMDD
        type_code:
          type: string
          nullable: true
        filing_date:
          type: string
          nullable: true
          description: YYYYMMDD
        status_code:
          type: string
          nullable: true
        parties:
          type: array
          items:
            $ref: '#/components/schemas/TTABParty'
    TTABSearchResponse:
      allOf:
        - $ref: '#/components/schemas/Pagination'
        - type: object
          required:
            - results
          properties:
            results:
              type: array
              items:
                $ref: '#/components/schemas/TTABProceeding'
            data_freshness:
              type: string
    TTABDetail:
      type: object
      description: 'Full TTAB proceeding record. Date fields are YYYYMMDD strings
        from

        the USPTO TTAB bulk corpus (not ISO 8601).

        '
      required:
        - proceeding_number
        - parties
      properties:
        proceeding_number:
          type: string
        transaction_date:
          type: string
          nullable: true
          description: YYYYMMDD
        type_code:
          type: string
          nullable: true
        filing_date:
          type: string
          nullable: true
          description: YYYYMMDD
        status_code:
          type: string
          nullable: true
        parties:
          type: array
          items:
            $ref: '#/components/schemas/TTABParty'
        data_freshness:
          type: string
