Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.arcmira.com/llms.txt

Use this file to discover all available pages before exploring further.

The recommendations API exposes Arcmira’s commercial-extraction pipeline. Each row links one entity to one piece of media and carries a mention_classad_read, endorsement, or mention — plus extracted commercial metadata (verbatim quote, promo code, offer, speaker role, conflict status).
GET /v1/recommendations
GET /v1/entities/{id}/recommendations
Both forms return the same shape and accept the same filters; the entity-scoped variant pulls the canonical ent_<id> from the path.
Recommendations are gated behind Pro+ and require the recommendations:read scope. Lower tiers receive 403 recommendations_not_enabled; correctly tiered keys missing the scope receive 403 insufficient_scope. See Scopes and Commercial intelligence.

Minimal request

cURL
curl 'https://api.arcmira.com/v1/recommendations?entity_id=ent_14&limit=25' \
  -H "Authorization: Bearer $ARCMIRA_API_KEY"
Node 20+
const res = await fetch(
  'https://api.arcmira.com/v1/recommendations?entity_id=ent_14&limit=25',
  { headers: { 'x-api-key': process.env.ARCMIRA_API_KEY } },
);
const { data, has_more, next_cursor, entity } = await res.json();
Exactly one of entity_id or entity_name is required.
By name
curl 'https://api.arcmira.com/v1/recommendations?entity_name=Ramp&entity_type=organization&mention_class=ad_read&limit=10' \
  -H "x-api-key: $ARCMIRA_API_KEY"
entity_type is optional but strongly recommended when names are ambiguous.

Mention classes

ClassWhat it means
ad_readA paid sponsor read. Typically explicit, often with a promo code or call-to-action.
endorsementAn organic recommendation from a host or guest. No money involved.
mentionA lower-signal commercial reference that didn’t meet the ad_read / endorsement bar.
allThe default. Returns all three classes.
Filter with mention_class=ad_read to scope to paid placements only — useful for advertiser dashboards.

Filters

ParameterDescription
entity_idCanonical ent_<id>. Mutually exclusive with entity_name.
entity_nameHuman-readable name. Pair with entity_type to disambiguate.
entity_typeOne of person, organization, product, topic, channel.
channel_idRestrict to a single channel (YouTube channel ID).
channel_nameSubstring match on the source channel name.
mention_classad_read, endorsement, mention, or all (default).
min_confidenceFloat in [0, 1]. Default 0.7.
include_disputedtrue or false. Default false — excludes rows where extraction conflicts were marked disputed.
date_fromISO date. Lower bound (inclusive) on media.published_at.
date_toISO date. Upper bound (inclusive) on media.published_at.
limit1–100. Default 20.
cursorOpaque cursor from a previous response’s next_cursor.
Entity resolution is merge-aware: a request against ent_14 covers every row attached to entities merged into ent_14.

Response shape

{
  "data": [
    {
      "id": "com_119682",
      "recommendation_id": 119682,
      "mention_class": "ad_read",
      "entity": {
        "id": "ent_124261",
        "name": "Bezel",
        "type": "organization"
      },
      "media": {
        "video_id": "DRZatti6mVM",
        "title": "...",
        "published_at": "2025-12-17",
        "channel_id": "UC-DRzaGnL_vtBUpCFH5M0tg",
        "source_channel": {
          "id": "ent_6",
          "name": "TBPN"
        }
      },
      "start_timestamp": "12:34",
      "end_timestamp": "13:02",
      "verbatim_quote": "...",
      "promo_code": "BEZEL20",
      "offer": null,
      "sentiment": 0.8,
      "confidence": 0.95,
      "speaker_role": "host",
      "conflict_status": null,
      "resolution": null
    }
  ],
  "has_more": true,
  "next_cursor": "eyJvZmZzZXQiOjI1fQ",
  "entity": {
    "id": "ent_124261",
    "name": "Bezel",
    "type": "organization",
    "appearance_count": 0
  }
}
A few notes:
  • id is the public com_<recommendation_id> form. Use it when submitting corrections through POST /v1/feedback.
  • start_timestamp / end_timestamp are MM:SS strings sourced from the extraction pipeline, not seconds (this differs from /v1/mentions).
  • promo_code and offer are nullable. They’re populated when the extractor found explicit codes or offers in the verbatim quote.
  • speaker_role indicates whether a host or guest delivered the recommendation.
  • conflict_status is null for normal rows. When the same timestamp produced conflicting classifications across extraction passes, the resolution is surfaced in resolution. Disputed rows are excluded unless you pass include_disputed=true.

Entity-scoped variant

If you already have an ent_<id>, the path-scoped form is identical except for how you express the target:
curl 'https://api.arcmira.com/v1/entities/ent_14/recommendations?mention_class=ad_read&limit=10' \
  -H "x-api-key: $ARCMIRA_API_KEY"
This is the recommended shape for production integrations — explicit entity, no URL-encoded names, cleaner logs.

Pagination

Recommendations use the same cursor pagination as the rest of the API. Pass the previous response’s next_cursor as the cursor query parameter; has_more tells you whether to continue. See Pagination for the full pattern.

Billing

Each row returned by /v1/recommendations is a premium row — billed at a higher rate than appearance rows because the commercial pipeline is more expensive to run and curate. The same applies to /v1/channels/{id}/sponsors. Feedback and entity search are free. See Usage & billing for the full picture. /v1/me exposes recommendations_api_enabled: true|false so you can short-circuit calls on lower-tier keys without hitting 403.

Errors

CodeWhen
recommendations_not_enabledTier below Pro+. Upgrade required.
insufficient_scopeKey is Pro+ but missing recommendations:read.
entity_not_foundentity_id / entity_name didn’t resolve to a canonical entity.
invalid_querySchema validation failed — see error.message.
See Errors for the full envelope.