{
  "openapi": "3.0.3",
  "info": {
    "title": "Perception REST API",
    "description": "Narrative intelligence for the digital asset industry. Access cited media coverage, podcasts, company disclosures, regulatory filings, earnings calls, public conversations, sentiment, trends, and entity intelligence.",
    "version": "1.0.0",
    "contact": {
      "name": "Perception",
      "url": "https://perception.to",
      "email": "hello@perception.to"
    },
    "termsOfService": "https://perception.to/terms"
  },
  "x-perception-positioning": {
    "schemaVersion": 2,
    "contractVersion": "2026-09-21-weighted-v3",
    "category": "Narrative intelligence for the digital asset industry",
    "coveredSources": [
      "media mentions",
      "podcasts",
      "company disclosures",
      "regulatory filings",
      "earnings calls",
      "public conversations"
    ],
    "complementarySources": [
      "on-chain activity",
      "wallet attribution",
      "blockchain transactions",
      "token prices",
      "order books",
      "trade execution"
    ]
  },
  "x-perception-commercial-model": {
    "schemaVersion": 3,
    "version": "2026-09-21-weighted-v2",
    "calculation": {
      "formula": "min(toolBaseCredits + ceil(requestedResults / 25), 10)",
      "toolBaseCredits": [1, 2, 3],
      "resultBlockSize": 25,
      "maximumCreditsPerCall": 10
    },
    "free": {
      "includedCredits": 5,
      "creditWindow": "utc-day"
    },
    "registeredMetered": {
      "subscriptionRequired": false,
      "toolCount": 33,
      "creditAccounting": "weighted",
      "priceUsdPerCredit": 0.05,
      "dailyPaidCreditLimit": 20,
      "signupUrl": "https://app.perception.to/auth/sign-up?source=pricing-metered&plan=metered"
    },
    "subscriptions": {
      "perceptionMonthlyCredits": 1000,
      "intelligenceMonthlyCredits": 8000,
      "overagePriceUsdPerCredit": 0.025,
      "overageActivationRequired": true
    },
    "x402": {
      "accountRequired": false,
      "priceUsdPerCredit": 0.1
    },
    "fundingOrder": [
      "included",
      "grandfathered-prepaid",
      "opted-in-overage"
    ]
  },
  "x-perception-usage-response-headers": {
    "X-Perception-Credits-Charged": "Weighted credits committed for this call",
    "X-Perception-Tool-Credits": "Base tool component",
    "X-Perception-Volume-Credits": "Requested-result component",
    "X-Perception-Funding-Source": "included, legacy_prepaid, subscriber_overage, registered_metered, or x402",
    "X-Perception-Included-Used": "Included credits used in the active period",
    "X-Perception-Included-Remaining": "Included credits remaining",
    "X-Perception-Credit-Reset": "ISO 8601 reset time, or not_applicable for accountless x402",
    "X-Perception-Overage-Accrued": "Accrued subscriber overage in USD",
    "X-Perception-Overage-Cap": "Selected monthly overage cap in USD",
    "X-Perception-Payment-Status": "Current saved-card payment status",
    "X-Perception-Credential-Daily-Credits": "Credential weighted usage for the current UTC day, or not_applicable for accountless x402",
    "X-Perception-Credential-Monthly-Credits": "Credential weighted usage for the current month, or not_applicable for accountless x402"
  },
  "x-x402-feed": {
    "scope": "full-text REST feed only",
    "endpoint": "https://api.perception.to/feed",
    "x402Version": 1,
    "network": "base",
    "networkName": "Base mainnet",
    "asset": "USDC",
    "assetContract": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
    "payTo": "0xA89dac7b70e04c880974b02758Bd8fde14280013",
    "maxAmountRequired": "1000000",
    "maxTimeoutSeconds": 120
  },
  "servers": [
    {
      "url": "https://api.perception.to",
      "description": "Production"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "paths": {
    "/feed": {
      "get": {
        "operationId": "searchArticles",
        "summary": "Search articles and mentions",
        "description": "Full-text search across thousands of indexed sources, including cited fundraising announcements, capital raises, partnerships, and company news. Use a Bearer API key or complete the x402 payment challenge for this feed. MCP tools use the separate OAuth/Bearer endpoint.",
        "security": [
          {
            "bearerAuth": []
          },
          {}
        ],
        "parameters": [
          {
            "name": "keyword",
            "in": "query",
            "description": "Search term. Supports basic boolean operators.",
            "schema": {
              "type": "string"
            },
            "example": "bitcoin+etf"
          },
          {
            "name": "startDate",
            "in": "query",
            "required": true,
            "description": "Start of date range (inclusive). YYYY-MM-DD, UTC.",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "example": "2026-03-01"
          },
          {
            "name": "endDate",
            "in": "query",
            "required": true,
            "description": "End of date range (inclusive). YYYY-MM-DD, UTC.",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "example": "2026-03-15"
          },
          {
            "name": "outlet",
            "in": "query",
            "description": "Filter by source name. Exact match.",
            "schema": {
              "type": "string"
            },
            "example": "Bloomberg"
          },
          {
            "name": "sentiment",
            "in": "query",
            "description": "Filter by sentiment classification.",
            "schema": {
              "type": "string",
              "enum": [
                "Positive",
                "Neutral",
                "Negative"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Results per page. Default 50, max 100.",
            "schema": {
              "type": "integer",
              "default": 50,
              "maximum": 100
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "Page number for pagination. Default 1.",
            "schema": {
              "type": "integer",
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of articles with metadata",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "Title": {
                            "type": "string"
                          },
                          "Content": {
                            "type": "string"
                          },
                          "Date": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "URL": {
                            "type": "string"
                          },
                          "Outlet": {
                            "type": "string"
                          },
                          "Sentiment": {
                            "type": "string"
                          },
                          "Outlet_Category": {
                            "type": "string"
                          },
                          "author_name": {
                            "type": "string"
                          },
                          "image_url": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer"
                        },
                        "page": {
                          "type": "integer"
                        },
                        "pageSize": {
                          "type": "integer"
                        },
                        "totalPages": {
                          "type": "integer"
                        },
                        "hasNextPage": {
                          "type": "boolean"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid API key"
          },
          "402": {
            "description": "x402 v1 payment required on Base mainnet at 0.10 USDC per weighted credit. The response challenge identifies the calculated amount, USDC asset contract, payment recipient, and a 120-second timeout."
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        }
      }
    },
    "/trends": {
      "get": {
        "operationId": "getTrends",
        "summary": "Get narrative trends",
        "description": "AI-extracted narrative trends with signal strength, velocity, and representative articles. Trends are clustered across thousands of sources.",
        "parameters": [
          {
            "name": "startDate",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "endDate",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Array of trend objects",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "title": {
                        "type": "string"
                      },
                      "description": {
                        "type": "string"
                      },
                      "signal_strength": {
                        "type": "number"
                      },
                      "category": {
                        "type": "string"
                      },
                      "article_count": {
                        "type": "integer"
                      },
                      "representative_articles": {
                        "type": "array",
                        "items": {
                          "type": "object"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/intelligence/categories": {
      "get": {
        "operationId": "getCategories",
        "summary": "Get trend category distribution",
        "description": "Returns distribution of trends across categories (Regulation, ETFs, Mining, DeFi, etc.).",
        "parameters": [
          {
            "name": "startDate",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "endDate",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Category distribution with trend counts",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "categories": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string"
                          },
                          "count": {
                            "type": "integer"
                          },
                          "pct": {
                            "type": "number"
                          }
                        }
                      }
                    },
                    "total_trends": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/sentiment-metrics": {
      "get": {
        "operationId": "getSentimentMetrics",
        "summary": "Get sentiment breakdown",
        "description": "Historical sentiment distribution by outlet and time period. Shows positive, neutral, and negative coverage ratios.",
        "parameters": [
          {
            "name": "startDate",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "endDate",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Sentiment distribution with per-outlet breakdown",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "sentiment": {
                      "type": "object"
                    },
                    "total_articles": {
                      "type": "integer"
                    },
                    "by_outlet": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/fear-greed-index": {
      "get": {
        "operationId": "getFearGreedIndex",
        "summary": "Get Fear & Greed Index",
        "description": "Perception's proprietary Fear & Greed Index. Derived from discussion sentiment across thousands of sources, not price action. Ranges from 0 (Extreme Fear) to 100 (Extreme Greed).",
        "parameters": [
          {
            "name": "startDate",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "endDate",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Daily Fear & Greed values with labels",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "date": {
                        "type": "string",
                        "format": "date"
                      },
                      "value": {
                        "type": "integer"
                      },
                      "label": {
                        "type": "string"
                      },
                      "article_count": {
                        "type": "integer"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/channel-volume": {
      "get": {
        "operationId": "getChannelVolume",
        "summary": "Get source volume distribution",
        "description": "Article/mention volume grouped by outlet or channel over time.",
        "parameters": [
          {
            "name": "startDate",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "endDate",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Volume counts grouped by outlet",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "outlet": {
                        "type": "string"
                      },
                      "count": {
                        "type": "integer"
                      },
                      "category": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/grouped-data": {
      "post": {
        "operationId": "getEntityMentions",
        "summary": "Get entity mentions",
        "description": "NLP-powered company mention tracking. Uses entity recognition for high-accuracy company detection. Returns mentions grouped by entity with full article metadata.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "startDate",
                  "endDate",
                  "groupBy"
                ],
                "properties": {
                  "startDate": {
                    "type": "string",
                    "format": "date"
                  },
                  "endDate": {
                    "type": "string",
                    "format": "date"
                  },
                  "groupBy": {
                    "type": "string",
                    "enum": [
                      "companies"
                    ],
                    "description": "Grouping mode."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Mentions grouped by company name",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "groupedData": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "array"
                      }
                    },
                    "totalVolume": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/indices": {
      "get": {
        "operationId": "getIndexPortfolio",
        "summary": "Get Perception proprietary indices",
        "description": "Returns current readings for the Perception Index, Narrative Cost Basis, Narrative Consensus, Narrative Reach, and Bitcoin Attention Share, the Bitcoin reading that supports Narrative Dominance. Narrative Dominance is served by /indices/dominance. Headline readings are public. Components, methodology receipts, provenance, and history require a Bearer API key.",
        "security": [
          {},
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "metric",
            "in": "query",
            "description": "Return every reading (all) or one: perception (Perception Index), bitcoin_discourse_dominance (Bitcoin Attention Share), narrative_cost_basis (Narrative Cost Basis), cohort_conviction_gap (Narrative Consensus), or perception_breadth (Narrative Reach).",
            "schema": {
              "type": "string",
              "default": "all",
              "enum": [
                "all",
                "perception",
                "bitcoin_discourse_dominance",
                "narrative_cost_basis",
                "cohort_conviction_gap",
                "perception_breadth"
              ]
            }
          },
          {
            "name": "full",
            "in": "query",
            "description": "Include components, methodology receipts, and provenance. Requires authentication.",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "include_history",
            "in": "query",
            "description": "Include bounded daily or weekly history. Requires authentication and implies the full response.",
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Current proprietary index portfolio or selected index",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IndexPortfolioResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid metric or view parameter"
          },
          "401": {
            "description": "Authentication required or API key invalid"
          },
          "429": {
            "description": "Rate limit exceeded"
          },
          "502": {
            "description": "Index portfolio temporarily unavailable"
          },
          "503": {
            "description": "Index portfolio is not configured"
          }
        }
      }
    },
    "/indices/dominance": {
      "get": {
        "operationId": "getNarrativeDominance",
        "summary": "Get multi-asset Narrative Dominance",
        "description": "Returns the current Narrative Dominance ranking across tracked assets. The current ranking is public. Protected detail and bounded history require a Bearer API key.",
        "security": [
          {},
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "window",
            "in": "query",
            "description": "Analysis window.",
            "schema": {
              "type": "string",
              "default": "1y",
              "enum": ["90d", "ytd", "1y", "3y", "5y", "all"]
            }
          },
          {
            "name": "granularity",
            "in": "query",
            "description": "Time bucket used for the series.",
            "schema": {
              "type": "string",
              "default": "weekly",
              "enum": ["daily", "weekly", "monthly"]
            }
          },
          {
            "name": "full",
            "in": "query",
            "description": "Include protected methodology detail and breakdowns. Requires authentication.",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "include_history",
            "in": "query",
            "description": "Include bounded history. Requires authentication.",
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Narrative Dominance ranking and requested detail",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "Invalid window, granularity, or view parameter"
          },
          "401": {
            "description": "Authentication required or API key invalid"
          },
          "429": {
            "description": "Weighted-credit allowance exhausted"
          },
          "502": {
            "description": "Narrative Dominance temporarily unavailable"
          }
        }
      }
    },
    "/workflow-runs": {
      "post": {
        "operationId": "recordWorkflowRun",
        "summary": "Record an agent workflow run receipt",
        "description": "Stores a metadata-only receipt for a configured agent workflow. Prompts and generated output are excluded.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Previously recorded workflow run receipt returned idempotently"
          },
          "201": {
            "description": "Workflow run receipt recorded"
          },
          "400": {
            "description": "Invalid workflow run metadata"
          },
          "401": {
            "description": "Authentication required or API key invalid"
          },
          "429": {
            "description": "Weighted-credit allowance exhausted"
          }
        }
      }
    },
    "/health": {
      "get": {
        "operationId": "healthCheck",
        "summary": "Health check",
        "description": "Returns API gateway status. No authentication required.",
        "security": [],
        "responses": {
          "200": {
            "description": "API is healthy",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "example": "ok"
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key as Bearer token. Keys start with 'pcp_'. Get yours at https://app.perception.to/app/settings/integrations"
      }
    },
    "schemas": {
      "IndexHistoryPoint": {
        "type": "object",
        "required": [
          "date",
          "value"
        ],
        "properties": {
          "date": {
            "type": "string",
            "format": "date"
          },
          "value": {
            "type": "number"
          },
          "btcPrice": {
            "type": "number",
            "nullable": true
          }
        }
      },
      "IndexMetricReading": {
        "type": "object",
        "required": [
          "id",
          "name",
          "methodologyVersion",
          "unit",
          "current",
          "change",
          "confidence",
          "observedItems",
          "windowStart",
          "windowEnd",
          "updatedAt",
          "frequency"
        ],
        "properties": {
          "id": {
            "type": "string",
            "enum": [
              "perception",
              "bitcoin_discourse_dominance",
              "narrative_cost_basis",
              "cohort_conviction_gap",
              "perception_breadth"
            ]
          },
          "name": {
            "type": "string"
          },
          "methodologyVersion": {
            "type": "string"
          },
          "unit": {
            "type": "string",
            "enum": [
              "score",
              "percent",
              "usd"
            ]
          },
          "current": {
            "type": "number",
            "nullable": true
          },
          "secondary": {
            "type": "object",
            "required": [
              "label",
              "value",
              "unit"
            ],
            "properties": {
              "label": {
                "type": "string"
              },
              "value": {
                "type": "number"
              },
              "unit": {
                "type": "string",
                "enum": [
                  "percent",
                  "usd"
                ]
              }
            }
          },
          "change": {
            "type": "number",
            "nullable": true
          },
          "confidence": {
            "type": "number",
            "minimum": 0,
            "maximum": 100
          },
          "observedItems": {
            "type": "integer",
            "minimum": 0
          },
          "windowStart": {
            "type": "string",
            "format": "date"
          },
          "windowEnd": {
            "type": "string",
            "format": "date"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "frequency": {
            "type": "string",
            "enum": [
              "realtime",
              "daily",
              "weekly"
            ]
          },
          "history": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/IndexHistoryPoint"
            }
          },
          "breakdown": {
            "type": "object",
            "additionalProperties": true
          },
          "provenance": {
            "type": "object",
            "additionalProperties": true
          },
          "methodology": {
            "type": "object",
            "required": [
              "summary",
              "minimumCoverage",
              "sourceTables"
            ],
            "properties": {
              "summary": {
                "type": "string"
              },
              "minimumCoverage": {
                "type": "string"
              },
              "sourceTables": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "IndexPortfolioResponse": {
        "type": "object",
        "required": [
          "schemaVersion",
          "asset",
          "generatedAt",
          "sourceMaxDate",
          "metrics",
          "attribution"
        ],
        "properties": {
          "schemaVersion": {
            "type": "integer",
            "enum": [
              1
            ]
          },
          "asset": {
            "type": "string",
            "enum": [
              "bitcoin"
            ]
          },
          "generatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "sourceMaxDate": {
            "type": "string",
            "format": "date"
          },
          "calculationDurationMs": {
            "type": "number",
            "minimum": 0
          },
          "errors": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "metrics": {
            "type": "object",
            "minProperties": 1,
            "additionalProperties": {
              "$ref": "#/components/schemas/IndexMetricReading"
            }
          },
          "attribution": {
            "type": "string"
          }
        }
      }
    }
  }
}
