Layers
Partner APIAPI referenceMetrics

PATCH /v1/projects/:projectId/ads-content/:id

Force-include or force-exclude a creative from ad rotation, overriding the organic score gate.

View as Markdown
PATCH/v1/projects/{projectId}/ads-content/{id}
Phase 1stable
Auth
Bearer
Scope
ads:write

Pins a creative as include or exclude, bypassing the automatic organicScore >= 4.0 gate. Use include to keep a creative in rotation even after its score decays below threshold. Use exclude to pull a creative off the eligible list immediately, regardless of how well it is scoring.

This is the only ads-content mutation available today. Everything else about the creative — score, performance, promotions — is derived. The override field is the single human-writable lever.

Path
  • projectId
    string (UUID)required
    Project containing the creative.
  • id
    string (UUID)required
    adsContentId — from GET /ads-content.
Body
  • override
    string | nullrequired
    Set the override. null clears it and returns to score-based gating.
    One of: include, exclude,
  • note
    stringoptional
    Short context saved alongside the override. Visible in the audit log; max 280 chars.

Example request

curl -X PATCH https://api.layers.com/v1/projects/prj_01HX9Y7K8M2P4RSTUV56789AB/ads-content/01HXC9MNPQRSTUVWXYZAB12345 \
  -H "Authorization: Bearer lp_live_01HX9Y6K7EJ4T2_4QZpN..." \
  -H "Content-Type: application/json" \
  -d '{ "override": "exclude", "note": "Legal flagged the background music" }'
const res = await fetch(
  `https://api.layers.com/v1/projects/${projectId}/ads-content/${adsContentId}`,
  {
    method: "PATCH",
    headers: {
      Authorization: `Bearer ${apiKey}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ override: "exclude", note: "Legal flagged background music" }),
  },
);
const updated = await res.json();
import httpx

r = httpx.patch(
    f"https://api.layers.com/v1/projects/{project_id}/ads-content/{ads_content_id}",
    headers={"Authorization": f"Bearer {api_key}"},
    json={"override": "exclude", "note": "Legal flagged background music"},
)
updated = r.json()

Response

200OK — returns the updated ads_content row.
{
  "adsContentId": "01HXC9MNPQRSTUVWXYZAB12345",
  "sourceType": "content_container",
  "sourceId": "01HXC8A2B3C4D5E6F7G8H9J0K1",
  "platformPostId": null,
  "scoringPool": "generated",
  "organicScore": 3.2,
  "organicPerformance": null,
  "adPerformance": null,
  "scoredAt": "2026-04-18T12:00:00Z",
  "scoringVersion": 3,
  "eligibility": { "isEligible": false, "reason": "excluded by override" },
  "override": "exclude",
  "overrideNote": "Legal flagged background music",
  "overrideSetBy": "lp_live_HHMRNJ2AHYJ6WZJ4 (api_key_id)",
  "overrideSetAt": "2026-04-18T19:22:05Z",
  "activePromotions": []
}
400Invalid override value or empty body.
{
  "error": {
    "code": "VALIDATION",
    "message": "Invalid patch body.",
    "requestId": "req_..."
  }
}
404ads_content row not found.

What override does

override is consulted before organicScore in every place Layers picks creatives to promote:

  • "include" — eligible regardless of score, pool, or decay. Use this to pin a seasonal hero, a creative legal has cleared, or a winner you want to keep running after its decay curve dips below 4.0.
  • "exclude" — ineligible regardless of score. Use this to retire a creative from future ad selection. Ads currently running against it are not paused — ad pause decisions are made from live performance, not from override. Pause them in the platform's ad manager.
  • null — clears the override. Eligibility follows the score again.

Notes

  • Idempotent: PATCHing the same override twice is a no-op with respect to downstream selection.
  • :id is the raw UUID returned in adsContentId from the list endpoint — pass it back without any partner prefix.
  • overrideSetBy stores the API key prefix and the api_key id that made the change ("<prefix> (<api_key_id>)"). Audit who-did-what via GET /v1/audit with subjectType=ads_content.
  • Override does not change organicScore. Clearing the override restores score-based eligibility as if you had never touched it.
  • Excluding a creative on one platform excludes it across all platforms. There is no per-platform override.

See also

On this page