Skip to main content

Documentation Index

Fetch the complete documentation index at: https://agenticadvertisingorg-changeset-release-main.mintlify.app/llms.txt

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

Experimental. Brand rights lifecycle (get_rights, acquire_rights, update_rights) is part of AdCP 3.0 as an experimental surface — it may change between 3.x releases with at least 6 weeks’ notice. Sellers implementing any of these tasks MUST declare brand.rights_lifecycle in experimental_features. See experimental status for the full contract.
Binding contractual request to acquire rights from a brand agent. Parallels create_media_buy — select a pricing_option_id from get_rights and provide campaign details. The agent clears against existing contracts and returns terms, generation credentials, and disclosure requirements.

Schema

Response time

Seconds to minutes for acquired or rejected. The pending_approval status means the rights holder needs to review — resolution may take hours to days.

Quick start

{
  "rights_id": "janssen_likeness_voice",
  "pricing_option_id": "monthly_exclusive",
  "buyer": {
    "domain": "bistro-oranje.nl",
    "brand_id": "bistro_oranje"
  },
  "campaign": {
    "description": "AI-generated video ads for Bistro Oranje steakhouse featuring Daan Janssen",
    "uses": ["likeness", "voice"],
    "countries": ["NL"],
    "format_ids": [
      { "agent_url": "https://creative.adcontextprotocol.org", "id": "video_social_1080x1920" }
    ],
    "estimated_impressions": 50000,
    "start_date": "2026-04-01",
    "end_date": "2026-06-30"
  },
  "revocation_webhook": {
    "url": "https://buyer.bistro-oranje.nl/webhooks/revocation",
    "authentication": {
      "schemes": ["HMAC-SHA256"],
      "credentials": "whsk_bo_abc123...shared_secret_min_32_chars"
    }
  },
  "idempotency_key": "acq_bo_janssen_2026q2_001",
  "push_notification_config": {
    "url": "https://buyer.bistro-oranje.nl/webhooks/adcp/acquire_rights/op_abc123",
    "authentication": {
      "schemes": ["HMAC-SHA256"],
      "credentials": "whsk_bo_xyz789...shared_secret_min_32_chars"
    }
  }
}

Parameters

Request

FieldTypeRequiredDescription
rights_idstringYesRights offering identifier from get_rights
pricing_option_idstringYesSelected pricing option
buyerbrand-refYesBuyer’s brand identity
accountaccount-refConditionalAccount context. Pass when the brand agent has a governance agent bound to this brand+operator via sync_governance — the brand agent uses it to resolve the bound governance agent and project commitment under the CPM-priced rights validation. Optional when the request is ungoverned or threads a governance_context token on the envelope instead.
campaign.descriptionstringYesHow the rights will be used
campaign.usesstring[]YesSpecific rights uses for this campaign
campaign.countriesstring[]NoCountries where the campaign will run
campaign.format_idsformat-id[]NoCreative formats that will be produced
campaign.estimated_impressionsintegerNoEstimated total impressions
campaign.start_datedateNoCampaign start date
campaign.end_datedateNoCampaign end date
revocation_webhookpush-notification-configYesWebhook for revocation notifications. If the rights holder needs to revoke rights, they POST a revocation-notification to this URL.
idempotency_keystringNoClient-generated key for safe retries. Resubmitting with the same key returns the original response.
push_notification_configpush-notification-configNoWebhook for async status updates if the acquisition requires approval. See push notifications.

Response statuses

The response uses a discriminated union on status:
StatusDescriptionKey fields
acquiredRights cleared, credentials issuedterms, generation_credentials, rights_constraint, disclosure
pending_approvalRequires rights holder reviewdetail, estimated_response_time
rejectedRequest deniedreason, suggestions (optional)
When suggestions is present on a rejected response, the rejection is actionable — the buyer can adjust their request and retry. When suggestions is absent, the rejection is final and the buyer should not retry for this rights/talent combination. This convention applies consistently across acquire_rights rejections, get_rights excluded results, and creative approval rejections.

Request validation

Two campaign-field validations are normative for acquire_rights. Both produce INVALID_REQUEST with the offending field populated and recovery: "correctable" (the buyer can fix the request and retry).

Expired campaign window

Brand agents MUST reject with INVALID_REQUEST and field: "campaign.end_date" when campaign.end_date is in the past at the time of the request. Acquiring rights for a window that has already elapsed produces a zero-duration grant and is almost always a buyer-side bug — surfacing it deterministically is more useful than silently issuing credentials that immediately expire. Unlike create_media_buy, which supports an any_of past-start auto-adjust pattern (a flight can be time-shifted forward without re-licensing), rights grants are not time-shiftable: the contract attaches to the requested period, so reject-only is the correct contract for acquire_rights. Brand agents MAY also reject when campaign.start_date is more than the rights agent’s configured grace window in the past (typically the rights agent rejects start dates earlier than now - 24h since rights cannot be retroactively granted); that decision is contract-specific and SHOULD use field: "campaign.start_date". The end_date < now check is the normative floor.

CPM-priced rights under a governance plan

A request is governance-aware when the brand agent will project commitment against a governance plan before issuing credentials. That happens by either of two paths:
  1. Inline path — the request carries an intent-phase governance_context token on the protocol envelope. The buyer threads the token explicitly per request.
  2. Bound path — the request carries account (a seller-assigned account_id, or account.brand + account.operator resolving to a bound account), and the brand agent has a governance agent previously bound to that account via sync_governance. The brand agent looks up the bound agent without the buyer threading anything per request.
When both paths are present in the same request — an inline governance_context token AND an account with a bound governance agent — the inline token wins. The token is per-request, JWS-signed against a specific plan, and is the primary correlation key for audit and reporting; the bound agent serves as the resolver fallback when no token is threaded. Brand agents MUST consult the agent identified by the inline token when both are present, even if it differs from the bound agent — the buyer’s per-request decision overrides the persisted binding. Both paths trigger the same projection rule. When the request is governance-aware and the selected pricing option has model: "cpm", campaign.estimated_impressions is the input the brand agent uses to project commitment against remaining plan budget. To make that projection deterministic across implementations:
  • Brand agents MUST reject with INVALID_REQUEST and field: "campaign.estimated_impressions" when the request is governance-aware (either path), the selected pricing_option.model is "cpm", and campaign.estimated_impressions is either omitted or 0. Implementer-chosen defaults (e.g., assuming 1M impressions) are non-conformant — they hide a policy decision inside each implementation and produce different governance outcomes for identical requests.
  • When estimated_impressions is provided and non-zero, the projected commitment is (pricing_option.price / 1000) × campaign.estimated_impressions, evaluated in pricing_option.currency. If pricing_option.currency differs from the governance plan’s budget currency (as carried on the plan), the brand agent MUST reject with INVALID_REQUEST and field: "pricing_option_id" — currency conversion is not specified for governance projection, so currency-mismatched offers cannot be cleared against a governed plan.
  • If the projected commitment exceeds the buyer’s remaining plan budget, the agent MUST reject with INVALID_REQUEST and field: "campaign.estimated_impressions", populating reason with the projected commitment and remaining budget so the buyer can adjust.
  • Non-CPM pricing options (model: "flat_rate", etc.) commit the flat amount regardless of impression volume; brand agents MUST NOT require estimated_impressions for governance projection on those options. Buyers MAY still provide estimated_impressions for cap-tracking purposes.
Ungoverned requests — neither governance_context token nor an account with a bound governance agent — are unaffected by this validation. estimated_impressions remains optional in that case (sellers MAY refuse to transact ungoverned plans as a matter of commercial policy, per Spend-commit invocation, but that refusal is independent of this projection rule).

Generation credentials

When rights are acquired, the agent coordinates with LLM providers to issue scoped credentials:
  1. Agent clears the rights against existing contracts
  2. Agent tells the provider (e.g., Midjourney): “Issue a rights key for this talent, licensed to this buyer”
  3. Agent returns the credentials to the buyer
Any creative agent can use these credentials. The LLM provider enforces usage constraints at generation time — the rights agent sets up the permission, the provider is the gatekeeper.
FieldTypeDescription
providerstringLLM/generation service (e.g., “midjourney”, “elevenlabs”)
rights_keystringScoped API key for generating rights-cleared content
usesstring[]Rights uses this credential covers
expires_atdatetimeWhen the credential expires (provider-determined)
endpointuriProvider endpoint for rights-scoped generation (optional, uses provider default if omitted)

Rights constraint

When status is acquired, the response includes a rights_constraint object:
FieldTypeDescription
rights_constraintobjectPre-built constraint for creative manifests. Contains validity period, country restrictions, and impression cap from agreed terms. Embed directly in the manifest’s rights array.

Creative lifecycle

After acquiring rights:
  1. Generate: Creative agent uses generation_credentials to produce content
  2. Manifest: Embed the rights_constraint from the acquire_rights response directly into the creative manifest’s rights array. The rights agent pre-builds this constraint with the correct validity period, country restrictions, and impression cap from the agreed terms.
  3. Approve: POST a creative-approval-request to the approval_webhook URL, authenticating with the provided credentials. The response is a creative-approval-response with status approved, rejected, or pending_review. If pending_review, poll the returned status_url for updates (suggested: every 5 minutes, back off to every 30 minutes after 1 hour).
  4. Serve: Place approved creative via create_media_buy, respecting country and date restrictions
  5. Report: Use report_usage with rights_id for cap tracking and billing
If acquire_rights returns pending_approval and you provided push_notification_config, you’ll receive a webhook notification when the status changes to acquired or rejected. Otherwise, re-call acquire_rights with the same rights_id and idempotency_key after the estimated_response_time interval. Set approval_status: 'pending' on any creative manifests built during this period.

Revocation

If the rights holder needs to revoke rights (talent controversy, contract violation, etc.), they POST a revocation-notification to the buyer’s revocation_webhook, authenticating with the credentials provided at acquisition time. The notification contains an idempotency_key (required, used for deduplication across retries), rights_id, brand_id, reason, and effective_at timestamp. The buyer is responsible for:
  • Deduplicating by idempotency_key — the same revocation may be delivered multiple times; see Push Notifications — Reliability for the canonical dedup contract
  • Stopping creative delivery by effective_at
  • Removing or replacing affected creatives from active campaigns
  • Ceasing use of generation credentials (providers may also invalidate credentials independently)
Partial revocation is supported — if revoked_uses is present, only those uses are revoked (e.g., voice revoked but likeness remains).

Acknowledging revocations

Return HTTP 200 immediately upon receiving and validating a revocation notification. The rights holder retries on non-2xx responses using exponential backoff (1s, 5s, 30s, 5m, 30m). After 6 failed attempts, the rights holder may escalate through other channels. All webhook signing follows the AdCP push notification signing profile — RFC 9421 by default (rights agent signs with its adcp_use: "webhook-signing" key published at its brand.json agents[] entry), with the deprecated HMAC-SHA256 fallback available when the rights holder populates authentication.credentials on the webhook registration.

Impression caps and overage

When terms.impression_cap is set, it is a soft cap. Delivery is not automatically halted at the cap — the buyer is responsible for monitoring usage via report_usage and managing delivery accordingly. Impressions beyond the cap are billed at terms.overage_cpm. If the rights holder wants a hard cap (no delivery beyond the limit), they specify this in restrictions.

Usage reporting

The usage_reporting_url in the acquired response is a convenience endpoint provided by the rights agent for HTTP-based impression reporting. It accepts the same payload as the report_usage MCP task. Use whichever integration is simpler for your pipeline — the MCP tool for agent-to-agent workflows, or the URL for direct HTTP calls from ad servers.

Renewal and updates

To extend a rights grant, adjust impression caps, change pricing, or pause/resume, use update_rights. Extended grants receive re-issued generation credentials and an updated rights_constraint for re-embedding in manifests.

Next steps

update_rights

Extend, adjust, or pause an existing rights grant.

report_usage

Report impressions against rights grants for billing and cap tracking.

brand.json spec

Rights constraints on creative manifests.