curl --request POST \
--url https://app.uselamina.ai/v1/content/create \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '
{
"brief": "Create an eye-catching Instagram post showcasing our new summer sneaker collection with lifestyle photography",
"platform": "instagram",
"modality": "image",
"brandProfileId": null,
"campaignId": null
}
'import requests
url = "https://app.uselamina.ai/v1/content/create"
payload = {
"brief": "Create an eye-catching Instagram post showcasing our new summer sneaker collection with lifestyle photography",
"platform": "instagram",
"modality": "image",
"brandProfileId": None,
"campaignId": None
}
headers = {
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-api-key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
brief: 'Create an eye-catching Instagram post showcasing our new summer sneaker collection with lifestyle photography',
platform: 'instagram',
modality: 'image',
brandProfileId: null,
campaignId: null
})
};
fetch('https://app.uselamina.ai/v1/content/create', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.uselamina.ai/v1/content/create",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'brief' => 'Create an eye-catching Instagram post showcasing our new summer sneaker collection with lifestyle photography',
'platform' => 'instagram',
'modality' => 'image',
'brandProfileId' => null,
'campaignId' => null
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.uselamina.ai/v1/content/create"
payload := strings.NewReader("{\n \"brief\": \"Create an eye-catching Instagram post showcasing our new summer sneaker collection with lifestyle photography\",\n \"platform\": \"instagram\",\n \"modality\": \"image\",\n \"brandProfileId\": null,\n \"campaignId\": null\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://app.uselamina.ai/v1/content/create")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"brief\": \"Create an eye-catching Instagram post showcasing our new summer sneaker collection with lifestyle photography\",\n \"platform\": \"instagram\",\n \"modality\": \"image\",\n \"brandProfileId\": null,\n \"campaignId\": null\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.uselamina.ai/v1/content/create")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"brief\": \"Create an eye-catching Instagram post showcasing our new summer sneaker collection with lifestyle photography\",\n \"platform\": \"instagram\",\n \"modality\": \"image\",\n \"brandProfileId\": null,\n \"campaignId\": null\n}"
response = http.request(request)
puts response.read_body{
"data": {
"status": "plan",
"canonicalStatus": "awaiting_approval",
"planId": "fc32ae7d-6840-4be3-8fb1-539a60e33fc3",
"planFingerprint": "sha256-fingerprint",
"estimatedCredits": 12,
"plan": {
"status": "awaiting_approval",
"steps": []
}
}
}{
"error": "brief is required (string)"
}{
"error": "Invalid API key"
}"Too many requests from this IP, please try again in a minute"Create Content
Compatibility endpoint over Lamina’s canonical frozen-plan lifecycle.
Interactive calls return clarification questions, route choices, or an
approval-ready plan without dispatching generation. Unattended calls must
set headless: true, send Idempotency-Key, and provide a positive
maxCredits; they execute only an approval-ready plan within that ceiling.
curl --request POST \
--url https://app.uselamina.ai/v1/content/create \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '
{
"brief": "Create an eye-catching Instagram post showcasing our new summer sneaker collection with lifestyle photography",
"platform": "instagram",
"modality": "image",
"brandProfileId": null,
"campaignId": null
}
'import requests
url = "https://app.uselamina.ai/v1/content/create"
payload = {
"brief": "Create an eye-catching Instagram post showcasing our new summer sneaker collection with lifestyle photography",
"platform": "instagram",
"modality": "image",
"brandProfileId": None,
"campaignId": None
}
headers = {
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-api-key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
brief: 'Create an eye-catching Instagram post showcasing our new summer sneaker collection with lifestyle photography',
platform: 'instagram',
modality: 'image',
brandProfileId: null,
campaignId: null
})
};
fetch('https://app.uselamina.ai/v1/content/create', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.uselamina.ai/v1/content/create",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'brief' => 'Create an eye-catching Instagram post showcasing our new summer sneaker collection with lifestyle photography',
'platform' => 'instagram',
'modality' => 'image',
'brandProfileId' => null,
'campaignId' => null
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.uselamina.ai/v1/content/create"
payload := strings.NewReader("{\n \"brief\": \"Create an eye-catching Instagram post showcasing our new summer sneaker collection with lifestyle photography\",\n \"platform\": \"instagram\",\n \"modality\": \"image\",\n \"brandProfileId\": null,\n \"campaignId\": null\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://app.uselamina.ai/v1/content/create")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"brief\": \"Create an eye-catching Instagram post showcasing our new summer sneaker collection with lifestyle photography\",\n \"platform\": \"instagram\",\n \"modality\": \"image\",\n \"brandProfileId\": null,\n \"campaignId\": null\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.uselamina.ai/v1/content/create")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"brief\": \"Create an eye-catching Instagram post showcasing our new summer sneaker collection with lifestyle photography\",\n \"platform\": \"instagram\",\n \"modality\": \"image\",\n \"brandProfileId\": null,\n \"campaignId\": null\n}"
response = http.request(request)
puts response.read_body{
"data": {
"status": "plan",
"canonicalStatus": "awaiting_approval",
"planId": "fc32ae7d-6840-4be3-8fb1-539a60e33fc3",
"planFingerprint": "sha256-fingerprint",
"estimatedCredits": 12,
"plan": {
"status": "awaiting_approval",
"steps": []
}
}
}{
"error": "brief is required (string)"
}{
"error": "Invalid API key"
}"Too many requests from this IP, please try again in a minute"brief describing the content you need. The engine resolves brand context, selects the best-fit app, injects creative guidance, and starts the execution.
The operation is asynchronous — use the returned run ID with the wait, stream, or get-run endpoints to retrieve results.
Best for agent-driven workflows where you want a single call to go from intent to finished asset.
Headless mode (unattended agents)
By default,create may return status: "needs_input" with askUser prompts when the chosen path needs information a human would supply — a dead end for an unattended worker or agent.
Pass headless: true (or terminalMode: "auto") to make the call reliable for agentic callers. In headless mode the engine:
- forces the self-drafting recipe path and dispatches best-effort — it never returns
needs_input; - returns
status: "unmatched"(machine-actionable) if a run genuinely can’t be formed, instead of an interactive ask; - surfaces any unmet asks on the
ranresponse as structuredunmetAsks[]— each{ name, key, question, type, required, autoFillable }— so an agent can satisfy one (e.g. generate animage_urlviaPOST /v1/generate/image) and re-run.
appId is ignored in headless mode. See the Agent Creation Loop guide for the full create → satisfy → run pattern.Authorizations
Workspace API key. Prefix: lma_. Example: lma_abc123...
Headers
Required for headless execution.
200Body
Natural-language description of what content to create. This is the primary input.
Target platform (e.g. instagram, tiktok, facebook). Helps select the right app and optimize guidance.
Desired content modality.
image, video, audio Scope brand context to a specific brand profile.
Scope guidance to a specific campaign.
Force a specific app instead of automatic selection. Use GET /v1/apps to find app IDs.
Pin a known creative scenario for deterministic planning.
64Free-text feedback to fold into a revised plan.
2000Optional route-family preference; the planner still freezes the route.
auto, atomic, compose, app Planning constraint; do not return a plan estimated above this amount.
x >= 1Execute an approval-ready frozen plan without an interactive approval step. Requires Idempotency-Key and maxCredits. Questions and route choices are still returned without dispatch.
Required hard ceiling for headless execution.
x >= 1Explicitly allow an unknown-cost plan under maxCredits.
Override specific input parameters on the selected app. Keys are parameter names.
Apply a content template for structured guidance. Use GET /v1/templates to find template IDs.
Auto-quality guarantee. Score output after completion and retry if below threshold.
Show child attributes
Show child attributes
Output aspect ratio. Auto-mapped to the matching workflow parameter. Common values: 1:1, 16:9, 9:16, 4:3, 3:4, 4:5, auto.
"9:16"
Freeform context about the target placement, injected into prompt engineering as structured document context. Useful for passing context from the calling application without manually writing it into the brief.
{ "documentTitle": "Summer Collection 2026", "fieldName": "heroImage", "fieldPurpose": "Main banner image for collection landing page", "dimensions": { "width": 1920, "height": 1080 } }
Deprecated compatibility field. Canonical pipeline runs do not attach this callback; poll GET /v1/content/runs/{runId}. A warning is returned when supplied.
"https://example.com/webhooks/lamina"
Response
Frozen plan, or a queued pipeline run for an authorized headless request.
Frozen plan, or a bounded headless pipeline run.