Layers
Partner APIAPI referenceContent

POST /v1/content/:containerId/clone-from-post

Fork or reimagine an existing platform post into a new generated container.

View as Markdown
POST/v1/content/:containerId/clone-from-post
Phase 1stableidempotent
Auth
Bearer
Scope
content:write

Takes a platform post (one of yours or one of the top-performers we surface) and produces a new generated container inspired by it.

This is the "clone a top performer" workflow. The :containerId in the URL is the target — pass a fresh UUID for idempotency. Pass a sourcePlatformPostId we already track — typically one surfaced by top-performers — along with the projectId the new container belongs to. We run a content job that uses the source's hook, pacing, and visual structure as input.

Two modes:

  • "fork" (default) — structurally close to the source. Same hook shape, same length, same CTA position. The generator treats the source as a template.
  • "reimagine" — uses the source's premise but lets the generator diverge on structure, voice, and visuals. More variance in output. Higher chance the generator improves on the source.

Path parameters

  • containerId
    string (uuid)required
    The new container id (partner-supplied UUID). Used as an idempotency key — replaying with the same id returns the prior response.

Body

Body
  • projectId
    string (uuid)required
    Project the new container belongs to. Must be in this org.
  • projectLayerId
    string (uuid)optional
    Which content layer to run through. Omit if the project only has one.
  • sourcePlatformPostId
    stringrequired
    Id of a post Layers tracks. Accepts the internal `platform_posts.id` or the platform-native `external_id`.
  • mode
    stringoptionaldefault: "fork"
    Generation posture.
    One of: fork, reimagine
  • variations
    integeroptionaldefault: 1
    Number of variations to produce. Max 10.
  • overrides
    objectoptional
    Caption, CTA, or voice-over script overrides for the clone.
  • overrides.caption
    stringoptional
    Override the source caption.
  • overrides.cta
    stringoptional
    Override the source CTA.
  • overrides.voiceOverScript
    stringoptional
    Replace the voice-over script.

Request

terminal
curl -X POST https://api.layers.com/v1/content/{newContainerId}/clone-from-post \
  -H "X-Api-Key: $LAYERS_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 8d2f1a3e-0b4c-4a11-9f7e-33c0a2c1bd55" \
  -d '{
    "projectId": "proj_01HX...",
    "sourcePlatformPostId": "pp_01HX...",
    "mode": "reimagine",
    "variations": 3
  }'
clone-from-post.ts
const newContainerId = crypto.randomUUID();
const res = await fetch(
  `https://api.layers.com/v1/content/${newContainerId}/clone-from-post`,
  {
    method: 'POST',
    headers: {
      'X-Api-Key': process.env.LAYERS_API_KEY!,
      'Content-Type': 'application/json',
      'Idempotency-Key': crypto.randomUUID(),
    },
    body: JSON.stringify({
      projectId,
      sourcePlatformPostId,
      mode: 'fork',
    }),
  },
);
const { jobId, containerId } = await res.json();
clone_from_post.py
import os, uuid, httpx

new_container_id = str(uuid.uuid4())
r = httpx.post(
    f"https://api.layers.com/v1/content/{new_container_id}/clone-from-post",
    headers={
        "X-Api-Key": os.environ["LAYERS_API_KEY"],
        "Content-Type": "application/json",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "projectId": project_id,
        "sourcePlatformPostId": source_id,
        "mode": "reimagine",
        "variations": 2,
    },
)
data = r.json()

Responses

202One job for the clone. The workflow produces variations as part of that single job.
{
  "jobId": "job_01HXZ9G7KMV2QX8Y1S5RJW3B7T",
  "kind": "content_clone_from_post",
  "status": "running",
  "containerId": "cnt_01HXZ9...",
  "locationUrl": "/v1/jobs/job_01HXZ9G7KMV2QX8Y1S5RJW3B7T"
}
404Source post not in this org's scope, or project not found.
{
  "error": {
    "code": "NOT_FOUND",
    "message": "Source post not found.",
    "requestId": "req_..."
  }
}
409Project has no active content layers, or multiple layers with no projectLayerId.
{
  "error": {
    "code": "CONFLICT",
    "message": "Multiple content layers — pass projectLayerId to disambiguate.",
    "requestId": "req_...",
    "details": { "layerCount": 2 }
  }
}

Notes

Clone-from-post does not republish or repost the source. It produces a new, generated container with your project's brand voice. The source is an input, not a direct reference in the output.

  • Source selection. Only posts we already track (via SIFT or your ad accounts) are valid sources. If you want to seed from an arbitrary URL, upload the media first and use generate-content with brief.referenceMediaIds.
  • Rights. You are responsible for whether cloning a given source is appropriate for your customer.

Errors

CodeWhen
NOT_FOUNDSource post not in this org's scope, or project not found.
VALIDATION_FAILEDBad mode, variations > 10.
CONFLICTLayer ambiguity or container id already exists.
BILLING_EXHAUSTEDCredits insufficient.

See also

On this page