AthenaHQ Attributes API

The Attributes API from AthenaHQ — 5 operation(s) for attributes.

Operations 5

GET /api/v1/attributes List Attributes #
POST /api/v1/attributes/cumulative Cumulative Attribute Metrics #
POST /api/v1/attributes/competitors Competitor Attribute Metrics #
POST /api/v1/attributes/time-series Attribute Time Series #
POST /api/v1/attributes/observations Attribute Observations #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/athenahq-ai:athenahq-ai-attributes-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

athenahq-ai-attributes-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: AthenaHQ Attributes API
  description: AthenaHQ API provides programmatic access to manage your websites and prompts for AI-powered content optimization.
  version: 1.0.0
  contact:
    email: support@athenahq.ai
servers:
- url: https://api.athenahq.ai
  description: Production server
security:
- apiKey: []
tags:
- name: Attributes
paths:
  /api/v1/attributes:
    get:
      tags:
      - Attributes
      summary: List Attributes
      description: Returns the direction-neutral brand-perception attributes tracked for a website. Use positive to select the positive or negative observation series; it defaults to true. Use this to discover attribute ids, then POST /api/v1/attributes/cumulative for prevalence, or POST /api/v1/attributes/time-series for one attribute's trend. Attributes the customer has removed are not returned.
      operationId: listAttributes
      security:
      - apiKey: []
      parameters:
      - name: website_id
        in: query
        description: The ID of the website to retrieve attributes for
        required: true
        schema:
          type: string
          format: uuid
      - name: positive
        in: query
        required: false
        description: Observation direction to select. Defaults to the positive series.
        schema:
          type: boolean
          default: true
      responses:
        '200':
          description: Successful response with list of attributes
          content:
            application/json:
              schema:
                type: object
                properties:
                  attributes:
                    type: array
                    items:
                      $ref: '#/components/schemas/Attribute'
                required:
                - attributes
              example:
                attributes:
                - id: 3fa85f64-5717-4562-b3fc-2c963f66afa6
                  name: Affordable
                  positive: true
                - id: 9c858901-8a57-4791-81fe-4c455b099bc9
                  name: Slow Support
                  positive: false
        '400':
          description: Bad request - Invalid parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized - Invalid or missing API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: Forbidden - API key cannot access this website
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /api/v1/attributes/cumulative:
    post:
      tags:
      - Attributes
      summary: Cumulative Attribute Metrics
      description: 'Returns directional prevalence for each direction-neutral brand-perception attribute. The optional top-level `positive` request field selects positive or negative observations and defaults to true. `total_responses` is the denominator: sampled, successfully analyzed responses in the date range that mention the brand. An analyzed response with no supported attribute claim remains in the denominator. Attributes nobody mentioned are returned with response_count 0 rather than omitted.'
      operationId: getCumulativeAttributeMetrics
      security:
      - apiKey: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CumulativeAttributeMetricsRequest'
      responses:
        '200':
          description: Successful response with attribute metrics
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/AttributeMetric'
                required:
                - data
              example:
                data:
                - attribute_id: 3fa85f64-5717-4562-b3fc-2c963f66afa6
                  attribute_name: Affordable
                  positive: true
                  response_count: 12
                  total_responses: 40
                  percentage: 30
                - attribute_id: 9c858901-8a57-4791-81fe-4c455b099bc9
                  attribute_name: Slow Support
                  positive: false
                  response_count: 0
                  total_responses: 40
                  percentage: 0
        '400':
          description: Bad request - Invalid parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized - Invalid or missing API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: Forbidden - API key cannot access this website
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Not found - Website or attribute does not exist
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /api/v1/attributes/competitors:
    post:
      tags:
      - Attributes
      summary: Competitor Attribute Metrics
      description: 'Returns directional attribute prevalence per tracked competitor. The optional top-level `positive` request field selects positive or negative observations and defaults to true. `total_responses` is per-competitor: sampled, successfully analyzed responses in the date range that mention that competitor. Returns one row per competitor per attribute; narrow with filters.competitor_ids. Competitors with no responses in the date range are omitted.'
      operationId: getCompetitorAttributeMetrics
      security:
      - apiKey: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AttributeMetricsRequest'
      responses:
        '200':
          description: Successful response with per-competitor attribute metrics
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/CompetitorAttributeMetric'
                required:
                - data
              example:
                data:
                - competitor_id: 1f2e3d4c-5b6a-4798-8a9b-0c1d2e3f4a5b
                  competitor_name: Globex
                  attribute_id: 3fa85f64-5717-4562-b3fc-2c963f66afa6
                  attribute_name: Affordable
                  positive: true
                  response_count: 5
                  total_responses: 20
                  percentage: 25
        '400':
          description: Bad request - Invalid parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized - Invalid or missing API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: Forbidden - API key cannot access this website
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Not found - Website or attribute does not exist
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /api/v1/attributes/time-series:
    post:
      tags:
      - Attributes
      summary: Attribute Time Series
      description: Returns the daily directional trend for one attribute, brand and competitors side by side. Requires an attribute_id. The optional top-level `positive` request field selects positive or negative observations and defaults to true. Days with no data are returned as zeros. Denominators are per-side sampled, successfully analyzed responses that mention the entity. Competitor figures aggregate all tracked competitors unless filters.competitor_ids narrows them.
      operationId: getAttributeTimeSeries
      security:
      - apiKey: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AttributeTimeSeriesRequest'
      responses:
        '200':
          description: Successful response with the daily series
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/AttributeTimeSeriesEntry'
                required:
                - data
              example:
                data:
                - date: '2026-07-15'
                  brand_count: 1
                  brand_total: 2
                  brand_percentage: 50
                  competitor_count: 0
                  competitor_total: 0
                  competitor_percentage: 0
        '400':
          description: Bad request - Invalid parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized - Invalid or missing API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: Forbidden - API key cannot access this website
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Not found - Website or attribute does not exist
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /api/v1/attributes/observations:
    post:
      tags:
      - Attributes
      summary: Attribute Observations
      description: 'Returns individual brand trait observations: each row is one statement an AI response made about one entity (your brand or a competitor) for one attribute, with the supporting response excerpt as `text_span`. `score` runs from -1 to 1 and its sign always matches `positive`; its magnitude (0.1 to 1.0) is how strongly the wording praises or criticizes. `score` is `null` when the observation was not scored, because it was extracted before scoring existed or has no valid value. If you only need the direction, use `score ?? (positive ? 1 : -1)`. Omit `positive` for both directions. `sort: "intensity"` (the default) returns the strongest observations first with unscored ones last; `sort: "recent"` returns the newest first. A page can hold fewer than `page_size` rows when an excerpt is no longer available, so use `has_more` to decide whether to fetch the next page. Also available as the MCP tool `get_attribute_observations`.'
      operationId: getAttributeObservations
      security:
      - apiKey: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AttributeObservationsRequest'
      responses:
        '200':
          description: Successful response with a page of observations
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/AttributeObservation'
                  page_num:
                    type: integer
                    description: Zero-indexed page number returned.
                  page_size:
                    type: integer
                    description: Maximum rows per page.
                  has_more:
                    type: boolean
                    description: '`true` if another page is available.'
                required:
                - data
                - page_num
                - page_size
                - has_more
              example:
                data:
                - observation_id: 0b7c3f7e-2d4a-4c1e-9f3b-6a2e8d1c4b5a
                  response_id: 7d9e1a2b-3c4d-4e5f-8a6b-9c0d1e2f3a4b
                  entity_id: 123e4567-e89b-12d3-a456-426614174000
                  entity_name: Acme
                  is_website: true
                  attribute_id: 3fa85f64-5717-4562-b3fc-2c963f66afa6
                  attribute_name: Affordable
                  positive: true
                  score: 0.9
                  text_span: Acme is by far the most affordable option for small teams.
                  model: chatgpt
                  created_at: '2026-09-14T08:21:05Z'
                - observation_id: 5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b
                  response_id: 1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d
                  entity_id: 1f2e3d4c-5b6a-4798-8a9b-0c1d2e3f4a5b
                  entity_name: Globex
                  is_website: false
                  attribute_id: 3fa85f64-5717-4562-b3fc-2c963f66afa6
                  attribute_name: Affordable
                  positive: false
                  score: null
                  text_span: Globex is priced above most alternatives.
                  model: perplexity
                  created_at: '2026-08-02T17:44:39Z'
                page_num: 0
                page_size: 40
                has_more: false
        '400':
          description: Bad request - Invalid parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized - Invalid or missing API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: Forbidden - API key cannot access this website
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Not found - Website does not exist
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    AttributeTimeSeriesEntry:
      type: object
      properties:
        date:
          type: string
          format: date
        brand_count:
          type: integer
        brand_total:
          type: integer
        brand_percentage:
          type: number
        competitor_count:
          type: integer
        competitor_total:
          type: integer
        competitor_percentage:
          type: number
      required:
      - date
      - brand_count
      - brand_total
      - brand_percentage
      - competitor_count
      - competitor_total
      - competitor_percentage
    AttributeObservation:
      type: object
      description: 'One brand trait observation: what one AI response said about one entity for one attribute.'
      properties:
        observation_id:
          type: string
          format: uuid
        response_id:
          type: string
          format: uuid
          description: The AI response the excerpt comes from.
        entity_id:
          type: string
          format: uuid
          description: 'The entity described: your `website_id` for your brand, otherwise a competitor id.'
        entity_name:
          type: string
          example: Acme
        is_website:
          type: boolean
          description: '`true` when the entity is your brand.'
        attribute_id:
          type: string
          format: uuid
        attribute_name:
          type: string
          example: Affordable
        positive:
          type: boolean
          description: Whether this observation praises (`true`) or criticizes (`false`) the entity on this attribute.
        score:
          type:
          - number
          - 'null'
          minimum: -1
          maximum: 1
          description: 'Signed strength from -1 to 1. The sign always matches `positive`; the magnitude (0.1 to 1.0) is how strongly the wording praises or criticizes. `null` when the observation was not scored, because it was extracted before scoring existed or has no valid value. For direction only, use `score ?? (positive ? 1 : -1)`.'
          example: 0.9
        text_span:
          type: string
          description: The excerpt of the response that supports the observation.
        model:
          type: string
          description: AI model that generated the response, as on /api/v1/responses.
          example: chatgpt
        created_at:
          type: string
          format: date-time
          description: ISO 8601 timestamp in UTC, to the second.
          example: '2026-09-14T08:21:05Z'
      required:
      - observation_id
      - response_id
      - entity_id
      - entity_name
      - is_website
      - attribute_id
      - attribute_name
      - positive
      - score
      - text_span
      - model
      - created_at
    Error:
      type: object
      description: Error response object
      required:
      - error
      properties:
        error:
          type: string
          description: Error message describing what went wrong
          example: Unauthorized
    PromptScheduleSelection:
      description: Select one streaming schedule. Use the selection returned by GET /api/v1/prompt-schedules. Default includes all pre-cutover history and ad hoc runs; archived schedules retain results. The retired manual token is accepted as an alias of default. This field takes one schedule; a list returns 400.
      default: default
      oneOf:
      - type: string
        enum:
        - default
        - manual
      - type: string
        format: uuid
    AttributeTimeSeriesRequest:
      type: object
      properties:
        website_id:
          type: string
          format: uuid
        attribute_id:
          type: string
          format: uuid
          description: The attribute to chart. Obtain ids from GET /api/v1/attributes.
        positive:
          type: boolean
          default: true
          description: Observation direction to select.
        filters:
          $ref: '#/components/schemas/ApiFilters'
      required:
      - website_id
      - attribute_id
      - filters
    CumulativeAttributeMetricsRequest:
      type: object
      properties:
        website_id:
          type: string
          format: uuid
        positive:
          type: boolean
          default: true
          description: Observation direction to select.
        filters:
          $ref: '#/components/schemas/ApiFiltersNoCompetitors'
      required:
      - website_id
      - filters
    CompetitorAttributeMetric:
      type: object
      properties:
        competitor_id:
          type: string
          format: uuid
        competitor_name:
          type: string
          example: Globex
        attribute_id:
          type: string
          format: uuid
        attribute_name:
          type: string
          example: Affordable
        positive:
          type: boolean
        response_count:
          type: integer
        total_responses:
          type: integer
          description: Analyzed responses for THIS competitor — each competitor has its own denominator.
        percentage:
          type: number
      required:
      - competitor_id
      - competitor_name
      - attribute_id
      - attribute_name
      - positive
      - response_count
      - total_responses
      - percentage
    AttributeObservationsRequest:
      type: object
      properties:
        website_id:
          type: string
          format: uuid
        filters:
          $ref: '#/components/schemas/ApiFiltersNoCompetitors'
        entity_ids:
          type: array
          maxItems: 100
          description: 'Entities to return observations for: the `website_id` for your brand, or competitor ids from `GET /api/v1/competitors`. Omit for every entity.'
          items:
            type: string
            format: uuid
        attribute_ids:
          type: array
          maxItems: 100
          description: Attributes to return observations for, from `GET /api/v1/attributes`. Omit for every active attribute.
          items:
            type: string
            format: uuid
        positive:
          type: boolean
          description: '`true` for favorable observations only, `false` for critical ones only. Omit for both directions.'
        sort:
          type: string
          enum:
          - intensity
          - recent
          default: intensity
          description: '`intensity`: strongest first, unscored last, then newest. `recent`: newest first.'
        page_num:
          type: integer
          minimum: 0
          default: 0
          description: Zero-indexed page number.
        page_size:
          type: integer
          minimum: 1
          maximum: 100
          default: 40
          description: Rows per page.
      required:
      - website_id
      - filters
    Attribute:
      type: object
      description: A brand-perception attribute (keyword) Athena extracts from AI model responses, such as 'Affordable' or 'Slow Support'.
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
          example: Affordable
        positive:
          type: boolean
          description: 'Whether the attribute reads as favourable. This describes the keyword itself, not any individual mention of it: ''Slow Support'' is always positive=false, however a given response used it.'
      required:
      - id
      - name
      - positive
    ApiFilters:
      type: object
      description: Filters for querying responses and metrics. Pass location filters in the JSON body as `filters.location_ids`.
      required:
      - start_date
      properties:
        schedule_id:
          $ref: '#/components/schemas/PromptScheduleSelection'
        start_date:
          type: string
          format: date-time
          description: Filter start date (UTC)
          example: '2024-01-01T00:00:00.000Z'
        end_date:
          type: string
          format: date-time
          description: Filter end date (UTC)
          example: '2024-12-31T23:59:59.999Z'
        models:
          type: array
          description: Filter by AI models
          items:
            type: string
            enum:
            - chatgpt
            - perplexity
            - gemini
            - google_ai_overview
            - copilot
            - claude
            - ai_mode
            - grok
            - deepseek
            - meta_ai
            - mistral
          example:
          - chatgpt
          - perplexity
        prompt_ids:
          type: array
          description: Filter by specific prompt IDs
          items:
            type: string
            format: uuid
        competitor_ids:
          type: array
          description: Filter by specific competitor IDs
          items:
            type: string
            format: uuid
        location_ids:
          type: array
          description: Filter by location IDs. Pass this in the JSON body as `filters.location_ids`, even when filtering by a single location. Use IDs returned by `GET /api/v1/locations`.
          items:
            type: string
            format: uuid
          example:
          - 123e4567-e89b-12d3-a456-426614174111
        prompt_status:
          type: string
          enum:
          - active
          - paused
          description: Filter by prompt status
        prompt_type:
          type: string
          enum:
          - branded
          - non_branded
          description: Filter by prompt type
    AttributeMetricsRequest:
      type: object
      properties:
        website_id:
          type: string
          format: uuid
        positive:
          type: boolean
          default: true
          description: Observation direction to select.
        filters:
          $ref: '#/components/schemas/ApiFilters'
      required:
      - website_id
      - filters
    ApiFiltersNoCompetitors:
      type: object
      description: 'The shared filters without competitor_ids, for the brand trait endpoints that do not take it: /api/v1/attributes/cumulative is brand-only, and /api/v1/attributes/observations selects entities with `entity_ids`. Sending competitor_ids is rejected. Use /api/v1/attributes/competitors for per-competitor metrics.'
      required:
      - start_date
      properties:
        schedule_id:
          $ref: '#/components/schemas/PromptScheduleSelection'
        start_date:
          type: string
          format: date-time
          description: Filter start date (UTC)
          example: '2024-01-01T00:00:00.000Z'
        end_date:
          type: string
          format: date-time
          description: Filter end date (UTC)
          example: '2024-12-31T23:59:59.999Z'
        models:
          type: array
          description: Filter by AI models
          items:
            type: string
            enum:
            - chatgpt
            - perplexity
            - gemini
            - google_ai_overview
            - copilot
            - claude
            - ai_mode
            - grok
            - deepseek
            - meta_ai
            - mistral
          example:
          - chatgpt
          - perplexity
        prompt_ids:
          type: array
          description: Filter by specific prompt IDs
          items:
            type: string
            format: uuid
        location_ids:
          type: array
          description: Filter by location IDs. Pass this in the JSON body as `filters.location_ids`, even when filtering by a single location. Use IDs returned by `GET /api/v1/locations`.
          items:
            type: string
            format: uuid
          example:
          - 123e4567-e89b-12d3-a456-426614174111
        prompt_status:
          type: string
          enum:
          - active
          - paused
          description: Filter by prompt status
        prompt_type:
          type: string
          enum:
          - branded
          - non_branded
          description: Filter by prompt type
      additionalProperties: false
    AttributeMetric:
      type: object
      properties:
        attribute_id:
          type: string
          format: uuid
        attribute_name:
          type: string
          example: Affordable
        positive:
          type: boolean
        response_count:
          type: integer
          description: Number of analyzed responses that mention this attribute.
        total_responses:
          type: integer
          description: Analyzed responses in the date range — the denominator.
        percentage:
          type: number
          description: response_count / total_responses, as a percentage.
      required:
      - attribute_id
      - attribute_name
      - positive
      - response_count
      - total_responses
      - percentage
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: x-api-key
      description: API key for authentication. You can create one [here](https://app.athenahq.ai/organization?tab=api).