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

# List Product Attributes

> Returns the attributes you can apply to your products, sorted alphabetically by code. An attribute rides on a product tax code as a trailing component (a rented computer is `TANGIBLE_PERSONAL_PROPERTY._RENTAL`) and can change how a product is taxed. Each attribute carries its `group`; attributes sharing a group may be mutually exclusive. Pass `ptc` to narrow the list to the attributes worth offering on that code. The default page holds up to 1000 attributes — enough to return the whole list in one call today. To page, pass `starting_after` set to the `code` of the last item you received; `has_more` is true while more attributes remain. Each page carries a strong `ETag`; send it back as `If-None-Match` to get `304 Not Modified` when that page has not changed.

See how to use it with code examples [here](/guides/using_products_apis)!


## OpenAPI

````yaml GET /product-attributes
openapi: 3.1.0
info:
  title: Taxwire Public API
  version: 0.1.0
servers: []
security: []
paths:
  /product-attributes:
    get:
      tags:
        - Product Tax codes & Attributes
      summary: List Product Attributes
      description: >-
        Returns the attributes you can apply to your products, sorted
        alphabetically by code. An attribute rides on a product tax code as a
        trailing component (a rented computer is
        `TANGIBLE_PERSONAL_PROPERTY._RENTAL`) and can change how a product is
        taxed. Each attribute carries its `group`; attributes sharing a group
        may be mutually exclusive. Pass `ptc` to narrow the list to the
        attributes worth offering on that code. The default page holds up to
        1000 attributes — enough to return the whole list in one call today. To
        page, pass `starting_after` set to the `code` of the last item you
        received; `has_more` is true while more attributes remain. Each page
        carries a strong `ETag`; send it back as `If-None-Match` to get `304 Not
        Modified` when that page has not changed.
      operationId: list_product_attributes_product_attributes_get
      parameters:
        - name: ptc
          in: query
          required: false
          schema:
            anyOf:
              - type: string
              - type: 'null'
            description: >-
              Narrow the list to the attributes worth offering on this product
              tax code, applying Taxwire's applicability rules. Omit it for the
              whole vocabulary.
            examples:
              - TANGIBLE_PERSONAL_PROPERTY.CLOTHING
            title: Ptc
          description: >-
            Narrow the list to the attributes worth offering on this product tax
            code, applying Taxwire's applicability rules. Omit it for the whole
            vocabulary.
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            maximum: 1000
            minimum: 1
            description: Page size, between 1 and 1000. Defaults to 1000.
            default: 1000
            title: Limit
          description: Page size, between 1 and 1000. Defaults to 1000.
        - name: starting_after
          in: query
          required: false
          schema:
            anyOf:
              - type: string
              - type: 'null'
            description: >-
              Return attributes after this one. Pass the `code` of the last item
              from the previous page to fetch the next page.
            title: Starting After
          description: >-
            Return attributes after this one. Pass the `code` of the last item
            from the previous page to fetch the next page.
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProductAttributesListResponse'
        '304':
          description: Not Modified — the page matches the client's If-None-Match ETag.
        '422':
          description: Validation Error - Invalid input data
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                errors:
                  - status: '422'
                    code: validation_required_field
                    title: Missing quantity
                    detail: Please provide a value for the required quantity field
                    source:
                      pointer: /data/attributes/line_items/0/quantity
        '429':
          description: Rate limit exceeded. Try again later.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                errors:
                  - status: '429'
                    code: rate_limit_error
                    title: Too Many Requests
                    detail: Rate limit exceeded
          headers:
            Retry-After:
              schema:
                type: string
              description: Time in seconds until the rate limit resets
            X-RateLimit-Limit:
              schema:
                type: string
              description: The rate limit ceiling for the given request
            X-RateLimit-Remaining:
              schema:
                type: string
              description: The number of requests remaining in the time window
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                errors:
                  - status: '500'
                    code: system_internal_error
                    title: Internal Error
                    detail: An unexpected error occurred. Our team has been notified.
      security:
        - APIKeyHeader: []
        - HTTPBearer: []
components:
  schemas:
    ProductAttributesListResponse:
      properties:
        object:
          type: string
          title: Object
          default: list
        url:
          type: string
          title: Url
          default: /product-attributes
        has_more:
          type: boolean
          title: Has More
          description: More results available
          examples:
            - true
            - false
        data:
          items:
            $ref: '#/components/schemas/ProductAttributeItem'
          type: array
          title: Data
          description: A page of the attributes you can assign to your products.
      type: object
      required:
        - has_more
      title: ProductAttributesListResponse
      description: List envelope for GET /product-attributes, cursor-paged by code.
    ErrorResponse:
      properties:
        errors:
          items:
            $ref: '#/components/schemas/Error'
          type: array
          title: Errors
      type: object
      required:
        - errors
      title: ErrorResponse
      description: Standardized JSON:API error response model.
    ProductAttributeItem:
      properties:
        code:
          type: string
          title: Code
          description: >-
            The attribute code. Attributes attach to a product tax code as
            trailing components, so a rented computer is
            `TANGIBLE_PERSONAL_PROPERTY._RENTAL`.
          examples:
            - _RENTAL
            - _B2B
        name:
          type: string
          title: Name
          description: The attribute's name, as it should be shown on screen.
          examples:
            - Rental
        description:
          type: string
          title: Description
          description: A short, human-readable summary of what the attribute means.
          examples:
            - The product is rented to the buyer rather than sold.
        group:
          $ref: '#/components/schemas/ProductAttributeGroupItem'
          description: >-
            The group this attribute belongs to. Every attribute belongs to
            exactly one; attributes sharing a group `key` may be mutually
            exclusive.
        ptcs:
          items:
            type: string
          type: array
          title: Ptcs
          description: >-
            The product tax codes the attribute applies to, as single labels
            rather than full paths — `AUTOMOBILES` covers
            `MOTOR_VEHICLES.AUTOMOBILES`. An empty list means every product.
            This is an advisory include-hint; for the authoritative set of
            attributes that apply to a specific code, call this endpoint with
            `?ptc=`.
          examples:
            - - TANGIBLE_PERSONAL_PROPERTY
              - DIGITAL_PROPERTY
      additionalProperties: false
      type: object
      required:
        - code
        - name
        - description
        - group
        - ptcs
      title: ProductAttributeItem
      description: Something true of a product that can change how it is taxed.
    Error:
      properties:
        status:
          type: string
          title: Status
        code:
          type: string
          title: Code
        title:
          type: string
          title: Title
        detail:
          type: string
          title: Detail
        source:
          anyOf:
            - $ref: '#/components/schemas/ErrorSource'
            - type: 'null'
        meta:
          anyOf:
            - additionalProperties: true
              type: object
            - type: 'null'
          title: Meta
      type: object
      required:
        - status
        - code
        - title
        - detail
      title: Error
      description: Individual JSON:API error object.
    ProductAttributeGroupItem:
      properties:
        key:
          type: string
          title: Key
          description: >-
            Identifies the group. Attributes in the same group share this key —
            bucket by it to apply `mutually_exclusive`.
          examples:
            - vehicle_title
        name:
          type: string
          title: Name
          description: The group's name, as it should be shown on screen.
          examples:
            - Motor vehicle title
        mutually_exclusive:
          type: boolean
          title: Mutually Exclusive
          description: >-
            When true, a product may carry at most one attribute from this group
            — a vehicle has exactly one title. When false, any combination of
            the group's attributes may be applied to a product.
          examples:
            - true
      additionalProperties: false
      type: object
      required:
        - key
        - name
        - mutually_exclusive
      title: ProductAttributeGroupItem
      description: |-
        The question a set of attributes answers, nested on each of its members.

        Attributes that share a ``key`` belong to the same group. When
        ``mutually_exclusive`` is true, a product may carry at most one of them.
    ErrorSource:
      properties:
        pointer:
          anyOf:
            - type: string
            - type: 'null'
          title: Pointer
      type: object
      title: ErrorSource
      description: Identifies the source of the error, e.g., via a JSON Pointer.
  securitySchemes:
    APIKeyHeader:
      type: apiKey
      in: header
      name: X-API-Key
    HTTPBearer:
      type: http
      scheme: bearer

````

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