EntityMomentumResponse

{
  "type": "object",
  "properties": {
    "entity": {
      "$ref": "#/components/schemas/EntityRef"
    },
    "verdict": {
      "type": "string",
      "enum": [
        "accelerating",
        "flat",
        "fading",
        "none"
      ],
      "description": "Absolute delta of the window against the prior window of the same length. The delta it needs grows with the square root of the window: 3 at 7 days, 5 at 30, 9 at 90, 18 at 365. none when the entity has no mentions at all."
    },
    "as_of": {
      "type": [
        "string",
        "null"
      ],
      "description": "Newest indexed media that mentions the entity. Lead with it; it is the date the verdict is true as of."
    },
    "window": {
      "$ref": "#/components/schemas/MomentumWindow"
    },
    "coverage": {
      "type": "string",
      "description": "What the count measures. Always the shows we index, never the whole internet."
    },
    "volume": {
      "type": "object",
      "properties": {
        "mentions_7d": {
          "type": "integer"
        },
        "mentions_30d": {
          "type": "integer"
        },
        "mentions_prior_30d": {
          "type": "integer"
        },
        "delta_30d_absolute": {
          "type": "integer"
        },
        "delta_30d_pct": {
          "type": [
            "number",
            "null"
          ],
          "description": "Percent change against the prior 30 days. Null when the prior window was zero."
        },
        "mentions_90d": {
          "type": "integer"
        },
        "total": {
          "type": "integer",
          "description": "All-time mentions in the index."
        },
        "mentions_window": {
          "type": "integer",
          "description": "Mentions in window. Equals mentions_30d when days is 30."
        },
        "mentions_prior_window": {
          "type": "integer",
          "description": "Mentions in the same number of days before window.after. Equals mentions_prior_30d when days is 30."
        },
        "delta_window_absolute": {
          "type": "integer"
        },
        "delta_window_pct": {
          "type": [
            "number",
            "null"
          ],
          "description": "Percent change against the prior window. Null when the prior window was zero."
        }
      },
      "required": [
        "mentions_7d",
        "mentions_30d",
        "mentions_prior_30d",
        "delta_30d_absolute",
        "delta_30d_pct",
        "mentions_90d",
        "total",
        "mentions_window",
        "mentions_prior_window",
        "delta_window_absolute",
        "delta_window_pct"
      ],
      "description": "Each count ends where window ends. On a plan whose freshness gate cut the window, nothing published after window.before is counted."
    },
    "top_shows": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "channel_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "channel_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "channel_page": {
            "type": [
              "string",
              "null"
            ],
            "description": "The channel's page on arcmira.com, absolute. Null when no channel is known."
          },
          "mentions": {
            "type": "integer"
          }
        },
        "required": [
          "channel_id",
          "channel_name",
          "channel_page",
          "mentions"
        ]
      },
      "description": "Up to five channels by mentions in window."
    },
    "paid_vs_organic": {
      "type": "object",
      "properties": {
        "ad_reads": {
          "type": "integer"
        },
        "endorsements": {
          "type": "integer"
        },
        "organic": {
          "type": "integer"
        }
      },
      "required": [
        "ad_reads",
        "endorsements",
        "organic"
      ],
      "description": "Commercial split in window. Present only on a Pro+ plan; otherwise access names the gate."
    },
    "access": {
      "type": "object",
      "properties": {
        "type": {
          "type": "string",
          "enum": [
            "invalid_request_error",
            "authentication_error",
            "permission_error",
            "quota_exceeded",
            "rate_limit_error",
            "not_found",
            "conflict_error",
            "server_error"
          ],
          "description": "The error class. It fixes the HTTP status: invalid_request_error 400, authentication_error 401, quota_exceeded 402, permission_error 403, not_found 404, conflict_error 409, rate_limit_error 429, server_error 500. Switch on it for retry and gate handling."
        },
        "code": {
          "type": "string",
          "description": "The specific condition, stable and snake_case; doc_url anchors on it. x-arcmira-codes on this schema lists every code with its type, gate and meaning. The list is open: new codes may appear inside an existing type, so switch on type and gate first."
        },
        "reason": {
          "type": "string",
          "enum": [
            "no_credential",
            "invalid",
            "revoked"
          ],
          "description": "Only on invalid_api_key. no_credential: nothing was sent. invalid: a credential was sent and is unknown or malformed. revoked: the key exists and is no longer usable."
        },
        "message": {
          "type": "string",
          "description": "One plain line. Names the fix or the unlock."
        },
        "param": {
          "type": "string",
          "description": "The query or body parameter the gate refused, when one did."
        },
        "gate": {
          "type": "string",
          "enum": [
            "rows",
            "key",
            "plan",
            "freshness",
            "exposure_law",
            "rate",
            "pagination"
          ],
          "description": "Which boundary refused. Present on every gate error; switch on it without parsing the message."
        },
        "resource": {
          "$ref": "#/components/schemas/ErrorResource"
        },
        "unlock": {
          "type": "object",
          "properties": {
            "tier": {
              "type": "string",
              "description": "The plan that lifts the gate."
            },
            "url": {
              "type": "string",
              "description": "Absolute upgrade or sign-up URL carrying its ?src= attribution. Use it verbatim."
            },
            "offer": {
              "type": "null",
              "description": "Reserved for the agent-discount offer. Always null today."
            },
            "action": {
              "type": "object",
              "properties": {
                "kind": {
                  "type": "string",
                  "description": "What the call does. send_signup_code sends a verification code to an address for an account key."
                },
                "method": {
                  "type": "string",
                  "description": "HTTP method to use."
                },
                "url": {
                  "type": "string",
                  "description": "Absolute endpoint carrying its ?src= attribution. Call it verbatim."
                }
              },
              "required": [
                "kind",
                "method",
                "url"
              ],
              "description": "The request that lifts the gate with no human, present when the caller can fix this itself. A key gate carries the signup send here; a plan or quota gate has no action and its url is a page a person opens."
            }
          },
          "required": [
            "tier",
            "url",
            "offer"
          ],
          "description": "How to lift the gate. Present when the gate has an unlock."
        },
        "retry_after_seconds": {
          "type": "integer",
          "description": "Present on rate gates. Mirrors the Retry-After header."
        },
        "details": {
          "type": "object",
          "properties": {
            "quote": {
              "$ref": "#/components/schemas/RefusedQuote"
            },
            "limit": {
              "$ref": "#/components/schemas/Limit"
            },
            "url": {
              "type": "string",
              "description": "On terms_acceptance_required: the page where the person accepts the updated Terms of Service. On terms_updated: the Terms of Service page."
            }
          },
          "description": "Machine data the refusal carries for you to act on. Present only on the codes that name a field here."
        },
        "doc_url": {
          "type": "string"
        },
        "request_id": {
          "type": "string"
        }
      },
      "required": [
        "type",
        "code",
        "message",
        "doc_url",
        "request_id"
      ],
      "description": "The gate that reduced this response. Present only when something was withheld; carries the same code, gate, and unlock an outright refusal would."
    },
    "freshness": {
      "allOf": [
        {
          "$ref": "#/components/schemas/Freshness"
        },
        {
          "description": "Present when your plan's freshness gate cut the window: where results on this plan stop. unlock names the plan that reads past it."
        }
      ]
    },
    "unlock": {
      "type": "object",
      "properties": {
        "tier": {
          "type": "string",
          "description": "The plan that lifts the freshness gate."
        },
        "url": {
          "type": "string",
          "description": "Where to start that plan."
        }
      },
      "required": [
        "tier",
        "url"
      ],
      "description": "Present with freshness when your plan's freshness gate cut the window; note says so."
    },
    "note": {
      "type": "string",
      "description": "One steering sentence for the agent reading this."
    }
  },
  "required": [
    "entity",
    "verdict",
    "as_of",
    "window",
    "coverage",
    "volume",
    "top_shows",
    "note"
  ],
  "example": {
    "entity": {
      "id": "ent_14",
      "name": "Ramp",
      "type": "organization",
      "slug": "ramp",
      "page": "https://arcmira.com/org/ramp"
    },
    "verdict": "accelerating",
    "as_of": "2026-08-28T17:00:00.000Z",
    "window": {
      "after": "2026-06-01T00:00:00Z",
      "before": "2026-08-30T15:04:05Z",
      "days": 90
    },
    "coverage": "Shows we index, not the whole internet.",
    "volume": {
      "mentions_7d": 6,
      "mentions_30d": 23,
      "mentions_prior_30d": 11,
      "delta_30d_absolute": 12,
      "delta_30d_pct": 109.1,
      "mentions_90d": 41,
      "total": 188,
      "mentions_window": 41,
      "mentions_prior_window": 29,
      "delta_window_absolute": 12,
      "delta_window_pct": 41.4
    },
    "top_shows": [
      {
        "channel_id": "UC-DRzaGnL_vtBUpCFH5M0tg",
        "channel_name": "TBPN",
        "channel_page": "https://arcmira.com/yt/@TBPNLive",
        "mentions": 17
      },
      {
        "channel_id": "UClWkDGXEzsh77GAhs90wpXw",
        "channel_name": "Moment of Truth",
        "channel_page": "https://arcmira.com/yt/@MomentofTruthShow",
        "mentions": 3
      }
    ],
    "access": {
      "type": "permission_error",
      "code": "recommendations_not_enabled",
      "message": "The paid versus organic split requires Pro+. Open unlock.url to start Pro+.",
      "gate": "plan",
      "resource": {
        "kind": "commercial",
        "what": "paid_split"
      },
      "unlock": {
        "tier": "pro_plus",
        "url": "https://arcmira.com/pricing?src=mcp-tool",
        "offer": null
      },
      "doc_url": "https://arcmira.com/docs/errors#recommendations_not_enabled",
      "request_id": "req_7f3c2a"
    },
    "note": "Lead with verdict and as_of. Then volume and shows. The paid vs organic split needs a plan that carries it; card.access says so. Search transcripts second for quotes. Never invent a heat score."
  }
}