Layers
Partner APIAPI referenceProjects

POST /v1/projects

Create a project, typically one per end-customer.

View as Markdown
POST/v1/projects
Phase 1stableidempotent
Auth
Bearer
Scope
projects:write

Create a project to hold one end-customer's brand context, layers, influencers, social accounts, and generated content. Set customerExternalId to your partner-side customer handle so later lookups don't require Layers IDs.

The call is synchronous and idempotent via the Idempotency-Key header. It provisions the project shell; downstream ingestion (GitHub, website, App Store) is a separate, async step.

Providing appDescription here also kicks off two background workflows:

Both auto-triggers fire-and-forget — failures don't fail the create.

Headers
  • Idempotency-Key
    string (UUID)optional
    Optional but strongly recommended on every POST. Same key + same body replays the cached response (`409 IDEMPOTENCY_CONFLICT` on body mismatch). Without it, retries after a connection error create duplicate projects. See [Idempotency](/docs/api/operational/idempotency).
Body
  • name
    stringrequired
    Internal display name. 3–30 chars.
  • customerExternalId
    stringoptional
    Your internal customer handle. Unique per organization. Looked up via ?customerExternalId=.
  • ownerEmail
    stringoptional
    Notification email. Defaults to the API key's registered owner.
  • timezone
    stringrequired
    IANA timezone. Controls cron schedule resolution. Use `"UTC"` if you have no preference.
  • primaryLanguage
    stringoptionaldefault: en
    BCP-47 language tag (e.g. `en`, `pt-BR`).
  • appName
    stringoptional
    Product name the generator anchors hooks and captions on. 3–30 chars. Required before `GET /v1/projects/:id/content/hooks` returns a bank — and the strongest single lever on content quality.
  • appDescription
    stringoptional
    Product pitch the planner uses for hooks and captions. 100–1000 chars. Same precondition for `/content/hooks`.
  • tagline
    stringoptional
    Short one-liner (≤ 80 chars) used in end-cards and overlays.
  • brandVoice
    stringoptional
    Caption tone preset. Defaults to `authentic` when omitted.
    One of: authentic, witty, professional, warm, casual, educational
  • targetGender
    stringoptional
    Audience gender. Drives influencer persona defaults at create time.
    One of: all, female, male
  • metadata
    objectoptional
    Opaque JSON, ≤ 8KB. Round-tripped unchanged.

Example request

curl https://api.layers.com/v1/projects \
  -H "Authorization: Bearer lp_..." \
  -H "Idempotency-Key: 4c1a2e92-7b18-4c4b-9b2a-d7a3f8b1c210" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme Coffee",
    "customerExternalId": "acme-coffee",
    "timezone": "America/Los_Angeles",
    "primaryLanguage": "en",
    "ownerEmail": "growth@gicgrowth.com",
    "appName": "Acme Coffee",
    "appDescription": "Daily ritual coffee subscriptions for runners and night-shift workers. Single-origin beans from named farms, roasted weekly, and shipped on a cadence that matches how you actually drink coffee — so the bag never goes stale and you never run out before a hard workout.",
    "tagline": "Coffee that shows up before you run out.",
    "brandVoice": "warm",
    "targetGender": "all"
  }'
const project = await layers.projects.create(
  {
    name: "Acme Coffee",
    customerExternalId: "acme-coffee",
    timezone: "America/Los_Angeles",
    primaryLanguage: "en",
    ownerEmail: "growth@gicgrowth.com",
    appName: "Acme Coffee",
    appDescription:
      "Daily ritual coffee subscriptions for runners and night-shift workers. Single-origin beans from named farms, roasted weekly, and shipped on a cadence that matches how you actually drink coffee — so the bag never goes stale and you never run out before a hard workout.",
    tagline: "Coffee that shows up before you run out.",
    brandVoice: "warm",
    targetGender: "all",
  },
  { idempotencyKey: crypto.randomUUID() }
);
project = layers.projects.create(
    name="Acme Coffee",
    customer_external_id="acme-coffee",
    timezone="America/Los_Angeles",
    primary_language="en",
    owner_email="growth@gicgrowth.com",
    app_name="Acme Coffee",
    app_description=(
        "Daily ritual coffee subscriptions for runners and night-shift workers. "
        "Single-origin beans from named farms, roasted weekly, and shipped on a "
        "cadence that matches how you actually drink coffee — so the bag never "
        "goes stale and you never run out before a hard workout."
    ),
    tagline="Coffee that shows up before you run out.",
    brand_voice="warm",
    target_gender="all",
    idempotency_key=str(uuid.uuid4()),
)

Response

201Created
{
  "id": "prj_9cb958b5-11b5-4e30-8675-5d075d52da7c",
  "organizationId": "org_2481fa5c-a404-44ed-a561-565392499abc",
  "name": "Acme Coffee iOS",
  "status": "active",
  "customerExternalId": "acme-coffee",
  "timezone": "America/Los_Angeles",
  "primaryLanguage": "en",
  "ownerEmail": "growth@gicgrowth.com",
  "appName": "Acme Coffee",
  "appDescription": "Daily ritual coffee subscriptions for runners and night-shift workers. Single-origin beans from named farms, roasted weekly, and shipped on a cadence that matches how you actually drink coffee — so the bag never goes stale and you never run out before a hard workout.",
  "tagline": "Coffee that shows up before you run out.",
  "brandVoice": "warm",
  "targetGender": "all",
  "platformIosBundleId": null,
  "platformAndroidBundleId": null,
  "platformWebDomain": null,
  "ingestState": {
    "github": null,
    "website": null,
    "appstore": null
  },
  "metadata": null,
  "createdAt": "2026-04-18T19:02:11.959888+00:00",
  "updatedAt": "2026-04-18T19:02:11.959888+00:00"
}

Errors

StatusCodeWhen
422VALIDATIONname empty, timezone invalid, metadata > 8KB.
401UNAUTHENTICATEDMissing or invalid key.
403FORBIDDEN_SCOPEKey lacks projects:write.
409IDEMPOTENCY_CONFLICTSame Idempotency-Key replayed with a different body.
409CONFLICTcustomerExternalId already in use on another project.
422VALIDATION_FAILEDBody includes id (resource ids are server-minted — see Idempotency).
429RATE_LIMITEDWrite budget exhausted.

See also

On this page