Meyer Launch
Help center

Developer API guide

Connect your backend or automation to your Meyer Launch workspace. Start by reading your projects, then add only the permissions your integration needs.

Make your first read-only request

  1. A workspace owner opens Settings → API keys, creates a named key and selects projects:read.
  2. Copy the key when it appears. Store it in a protected server environment variable named MEYER_LAUNCH_API_KEY. Keys created in this screen expire after 90 days and are shown once.
  3. Send the request below from your backend. It reads project names, IDs and slugs without spending generation credits.
Read projects with curl
curl --fail-with-body --silent --show-error \
  "https://meyerlaunch.com/api/v1/projects" \
  --header "Authorization: Bearer $MEYER_LAUNCH_API_KEY"
Read projects with Node.js fetch
const key = process.env.MEYER_LAUNCH_API_KEY;
if (!key) throw new Error("Configure MEYER_LAUNCH_API_KEY on your server.");

const response = await fetch("https://meyerlaunch.com/api/v1/projects", {
  headers: { Authorization: `Bearer ${key}` },
});
const body = await response.json();
if (!response.ok) throw new Error(`API request failed (${response.status}): ${body.error}`);
console.log(body.data.map(({ id, name, slug }) => ({ id, name, slug })));

Base URL: https://meyerlaunch.com. Send Authorization: Bearer <key> over HTTPS. Never put a key in a browser bundle, mobile build, URL, chat transcript or repository.

This optional API is for your own integrations. Social and advertising accounts connect separately through Settings; creating a key alone does not connect an account or run an automation.

Choose the capabilities you need

Every key belongs to one workspace and has selected permissions. The issuing person must remain an owner. Revoke a compromised key in Settings and update your integration with a replacement.

CapabilityPermissionCredits
Read projectsprojects:readNo generation credits
Read paid campaignscampaigns:readNo generation credits
Create a campaign-plan draftplans:writeNo AI generation in this call
List plan taskstasks:readNo generation credits
Read a task and prepared outputtasks:readNo generation credits
Prepare a supported tasktasks:prepare1 workspace credit per preparation; refunded on failure
Message the marketing agentagent:chatVariable workspace credits; workspace balance and agent monthly cap apply
Request a media quotegenerations:writeQuote only; no generation credits spent until confirmation
Confirm a reviewed quotegenerations:writeSpends the quoted workspace credits
Read a generation jobgenerations:readNo additional generation credits
Submit app or website eventsevents:writeNo generation credits

Project context can describe a mobile app, SaaS product or service business. Use the returned project kind and confirmed facts; choose a goal appropriate to that project rather than inventing capabilities or results.

Keys are limited to 60 accepted requests per minute; authenticated operations that fail later can consume a slot. Project/campaign reads return up to 100 records; task lists up to 200. These endpoints currently do not provide pagination cursors.

Reads and event reporting do not spend generation credits. Task preparation costs 1 workspace credit. Agent use has variable credit costs and a workspace monthly cap. Media generation uses an explicit quote and confirmation. Your subscription, wallet balance, provider availability and existing workspace rules still apply.

Endpoint reference

Examples contain placeholder IDs and selected response fields. Replace IDs, slugs, source media and event times before sending. Sample credit values are illustrative; approve the live quote returned for your job.

Read projects

GET /api/v1/projects

Permission: projects:read
Credits: No generation credits

List projects in the key’s workspace. Use the project ID for plans, tasks and events; use its slug for agent and generation requests.

  • Returns up to 100 projects, newest first. There is no pagination cursor.
  • Fields: id, name, slug, kind and created_at. Project kinds are app, saas and business.
Read projects: 200 response example
{
  "data": [
    {
      "id": "10000000-0000-4000-8000-000000000001",
      "name": "Example product",
      "slug": "your-project",
      "kind": "saas",
      "created_at": "2026-11-04T12:00:00Z"
    }
  ],
  "limit": 100
}

Read paid campaigns

GET /api/v1/campaigns

Permission: campaigns:read
Credits: No generation credits

Read saved paid-campaign configuration, including status, platform, objective, currency, daily budget in cents, start date and end date.

  • Returns up to 100 campaigns, newest first. There is no pagination cursor.
  • This endpoint does not return a complete performance report or change a campaign’s budget or delivery. An empty data array means no records returned, not verified zero ad activity.
Read paid campaigns: 200 response example
{
  "data": [],
  "limit": 100
}

Create a campaign-plan draft

POST /api/v1/launch-plans

Permission: plans:write
Credits: No AI generation in this call

Create a draft plan for an existing project from a name, goal and optional notes. This creates the plan record; it does not generate every asset or launch a campaign.

  • name: 1–120 characters. notes: up to 4,000 characters; defaults to an empty string.
  • goal: traffic, leads, app_growth or awareness. leads requires a business project. For SaaS, start with traffic or awareness; app_growth is intended for mobile apps.
  • Use a new UUID requestKey for a new plan. On a retry, keep the same UUID and identical input.
Create a campaign-plan draft: request JSON
{
  "projectId": "10000000-0000-4000-8000-000000000001",
  "name": "Product introduction",
  "goal": "traffic",
  "notes": "Prepare drafts from the confirmed project brief.",
  "requestKey": "20000000-0000-4000-8000-000000000002"
}
Create a campaign-plan draft: 201 response example
{
  "id": "40000000-0000-4000-8000-000000000004",
  "state": "draft"
}

List plan tasks

GET /api/v1/tasks

Permission: tasks:read
Credits: No generation credits

List tasks and check whether each can be prepared by Meyer Launch. Optional query filters select a project and task status.

  • projectId: optional project UUID
  • status: optional task status
  • Returns up to 200 tasks ordered by due date, then priority. No pagination cursor is provided.
  • status filter: active, completed, skipped or stale. preparable indicates whether the preparation endpoint supports this task.
  • The list includes preparation status/error. Use task detail for prepared output.
List plan tasks: 200 response example
{
  "data": [],
  "limit": 200
}

Read a task and prepared output

GET /api/v1/tasks/{id}

Permission: tasks:read
Credits: No generation credits

Read one workspace task, its preparation state and any saved output. Response examples below show selected fields.

  • Use the id returned by the task list. preparation contains status, error and output.
  • The output varies by preparation kind: a review summary, brief gaps or draft copy. Check status and error before treating output as ready.
Read a task and prepared output: 200 response example
{
  "data": {
    "id": "30000000-0000-4000-8000-000000000003",
    "projectId": "10000000-0000-4000-8000-000000000001",
    "title": "Prepare a social post",
    "preparable": true,
    "prepareKind": "copy",
    "preparation": {
      "status": "none",
      "error": null,
      "output": null
    }
  }
}

Prepare a supported task

POST /api/v1/tasks/{id}/prepare

Permission: tasks:prepare
Credits: 1 workspace credit per preparation; refunded on failure

Queue draft preparation for a task whose preparable field is true. The result still needs review in Meyer Launch.

  • Supply a UUID requestKey. Retrying the same requestKey returns the same attempt without charging again.
  • 202 means queued, not completed. Poll the task detail for preparation output.
  • Unsupported tasks return 422. Preparation does not approve, publish or schedule the work.
Prepare a supported task: request JSON
{
  "requestKey": "20000000-0000-4000-8000-000000000002"
}
Prepare a supported task: 202 response example
{
  "id": "30000000-0000-4000-8000-000000000003",
  "state": "queued",
  "requestKey": "20000000-0000-4000-8000-000000000002"
}

Message the marketing agent

POST /api/agent/chat

Permission: agent:chat
Credits: Variable workspace credits; workspace balance and agent monthly cap apply

Ask the agent to read project context and propose marketing work. It acts as the workspace owner who issued the key. Responses stream as newline-delimited JSON, not one JSON document.

  • For a new project conversation, send projectSlug and text. To continue, send conversationId and text.
  • text is limited to 20,000 characters. The key remains restricted to its workspace and the issuing owner’s accessible conversations.
  • Stream events include conversation, text (delta), status, proposal, notice, error and done. Preserve conversation.id for the next request. A stream can report an error after HTTP 200; wait for done and inspect error events.
  • Costs depend on the run; this endpoint has no separate generation quote step. Configure the workspace’s agent credit cap before automating it. Draft proposals wait for approval in Meyer Launch.
Message the marketing agent: request JSON
{
  "projectSlug": "your-project",
  "text": "Read the brief and propose three social-post directions. Keep everything as drafts."
}
Message the marketing agent: 200 response example
{
  "type": "conversation",
  "id": "40000000-0000-4000-8000-000000000004",
  "title": "Marketing directions",
  "projectSlug": "your-project"
}
{
  "type": "text",
  "delta": "Here are three draft directions."
}
{
  "type": "done",
  "credits": 1
}

Request a media quote

POST /api/v1/generations

Permission: generations:write
Credits: Quote only; no generation credits spent until confirmation

Quote an image, narration or composed-video draft for a project. The image example is below; narration/video inputs and callbacks are described after the endpoint reference.

  • Use projectSlug, UUID requestKey, kind (image, narration or video) and input. webhookUrl is optional.
  • Same key + same requestKey + identical input returns the existing job. preparing means retry the same request; a failed quote requires a new requestKey.
  • The sample 2-credit value is illustrative. Always use the live credits and expiresAt returned for your quote.
  • Jobs belong to their issuing API key. A different key in the same workspace cannot read or confirm that job. Internal free Lab generation is outside this customer API.
Request a media quote: request JSON
{
  "projectSlug": "your-project",
  "requestKey": "20000000-0000-4000-8000-000000000002",
  "kind": "image",
  "input": {
    "prompt": "A blue notebook on a wooden desk",
    "size": "1K",
    "aspect": "1:1"
  }
}
Request a media quote: 201 response example
{
  "id": "40000000-0000-4000-8000-000000000004",
  "kind": "image",
  "status": "quoted",
  "credits": 2,
  "expiresAt": "2026-11-04T12:15:00Z",
  "confirmedAt": null,
  "sourceId": "30000000-0000-4000-8000-000000000003",
  "creativeId": null,
  "resultUrl": null,
  "resultUrlExpiresIn": null,
  "error": null,
  "dailyCreditCap": 50
}

Confirm a reviewed quote

POST /api/v1/generations/{id}/confirm

Permission: generations:write
Credits: Spends the quoted workspace credits

Approve the selected job’s credit charge with an explicit maxCredits ceiling. Ask the customer to approve the live quoted cost before calling this endpoint.

  • maxCredits must be an integer from 0 to 50 and at least the quoted cost. Use the exact approved cost rather than an unnecessarily high ceiling.
  • Each key can confirm up to 50 credits per UTC day, in addition to workspace balance and provider limits. Failed attempts keep their daily-cap reservation; normal generation-failure wallet refunds still apply.
  • Repeating confirmation uses the same generation/receipt. If an outcome is uncertain, poll or retry this same job; do not create a new paid job blindly.
  • Quotes expire. Changed project/media facts may require a fresh quote. Confirmation starts generation; it does not approve an ad, publish a post or launch a campaign.
Confirm a reviewed quote: request JSON
{
  "maxCredits": 2
}
Confirm a reviewed quote: 202 response example
{
  "id": "40000000-0000-4000-8000-000000000004",
  "kind": "image",
  "status": "queued",
  "credits": 2,
  "resultUrl": null,
  "resultUrlExpiresIn": null,
  "error": null
}

Read a generation job

GET /api/v1/generations/{id}

Permission: generations:read
Credits: No additional generation credits

Poll the same job about every 10 seconds. A ready result can include a private download URL valid for 900 seconds (15 minutes).

  • Possible lifecycle states include preparing, quoted, confirmed, queued, running, ready and failed; the underlying media job can supply its own render state. Treat only ready with a non-null resultUrl as downloadable.
  • An expired result URL can be refreshed with another GET. Keep URLs private.
  • For failed jobs, check error and the credit receipt in Billing. A callback is optional; polling remains available if callback delivery fails.
Read a generation job: 200 response example
{
  "id": "40000000-0000-4000-8000-000000000004",
  "kind": "image",
  "status": "ready",
  "credits": 2,
  "resultUrl": "https://storage.example.invalid/private-signed-result",
  "resultUrlExpiresIn": 900,
  "error": null
}

Submit app or website events

POST /api/v1/events

Permission: events:write
Credits: No generation credits

Send real first_open, onboarding_done, paywall_view, trial_start and purchase events from a trusted backend for the selected project.

  • Send 1–100 events per batch. platform is ios, android or web. appVersion is optional, up to 64 characters.
  • Use random UUID installId and dedupeKey values. Reuse a dedupeKey only for the identical event; conflicting reuse rejects the whole batch with 409.
  • occurredAt must be an ISO 8601 timestamp within the past 90 days (up to five minutes of future clock skew is tolerated). Replace the example timestamp with the real occurrence time.
  • Do not send names, email addresses, hardware/ad identifiers or free-text properties. Never embed this workspace key in a browser or mobile build.
  • These are reported events, not independently verified purchases or automatically attributed ad conversions. Do not submit synthetic purchase events to production.
Submit app or website events: request JSON
{
  "projectId": "10000000-0000-4000-8000-000000000001",
  "events": [
    {
      "name": "first_open",
      "platform": "ios",
      "installId": "30000000-0000-4000-8000-000000000003",
      "dedupeKey": "20000000-0000-4000-8000-000000000002",
      "occurredAt": "2026-11-04T12:00:00Z",
      "appVersion": "1.0"
    }
  ]
}
Submit app or website events: 200 response example
{
  "accepted": 1,
  "duplicates": 0
}

Narration and video inputs

The same generation quote endpoint supports kind: narration and kind: video. Use the same key to quote, confirm and read a job. A generated asset remains a draft for review.

Narration

Supply an owned creativeId and its exact current version. The script is 3–960 characters, up to eight nonempty lines of 120 characters each, with no angle-bracket markup. Style is clear, warm or energetic.

Available voice IDs: Kore, Puck, Zephyr, Charon, Orus, Schedar, Erinome, Despina, Rasalgethi, Iapetus, Algieba, Sadaltager, Gacrux, Achird, Sulafat.

Narration quote request
{
  "projectSlug": "your-project",
  "requestKey": "20000000-0000-4000-8000-000000000002",
  "kind": "narration",
  "input": {
    "creativeId": "30000000-0000-4000-8000-000000000003",
    "version": 1,
    "script": "Keep your project notes together.",
    "voice": "Kore",
    "style": "clear"
  }
}

Composed video

Required fields are source, aspect, feed, headline, primaryText, cta, showLogo and cards. Source is an owned photo or recording media-asset ID, or a permitted screenshot URL. Aspects: 1:1, 4:5, 9:16 and 16:9; feed: light or dark.

Video quote request
{
  "projectSlug": "your-project",
  "requestKey": "20000000-0000-4000-8000-000000000002",
  "kind": "video",
  "input": {
    "source": {
      "type": "photo",
      "mediaAssetId": "30000000-0000-4000-8000-000000000003"
    },
    "aspect": "9:16",
    "feed": "light",
    "headline": "Your product in use",
    "primaryText": "Show one confirmed product benefit.",
    "cta": "Learn more",
    "showLogo": false,
    "cards": []
  }
}

Advanced optional fields include presentation, controls, captions, photoIds, screenshotUrls, parentCreativeId/parentRenderVersion, aiGenerated and customer narration. Their nested schemas and bounds are in the OpenAPI reference. Captions must be ordered, non-overlapping and within the video duration. Customer narration uses trackId, exact script and optional timing; private Lab audio is refused. Ownership, source-version and product-claim checks still apply. This API composes video from existing sources; it is not a general-purpose footage-generation endpoint.

Receive generation callbacks

Add an optional webhookUrl to your quote request. Use a public HTTPS endpoint on port 443. The response includes a job-specific webhookSecret; save it only on your backend. Redirects and private-network destinations are refused.

Generation callback example
{
  "eventId": "40000000-0000-4000-8000-000000000004",
  "type": "generation.ready",
  "jobId": "40000000-0000-4000-8000-000000000004",
  "kind": "image",
  "status": "ready"
}
  1. Read the exact raw request body before JSON parsing.
  2. Verify Meyer-Signature as hexadecimal HMAC-SHA256 with the job’s webhookSecret over Meyer-Timestamp + "." + raw body. Use a constant-time comparison.
  3. Reject timestamps outside a five-minute window. Deduplicate Meyer-Event-Id in durable storage and confirm the payload belongs to the expected job.
  4. Return 2xx after recording the event. Fetch the job with your API key for a fresh media URL; callback payloads never include one.

Completion types are generation.ready and generation.failed. The callback queue checks every five minutes and makes up to six attempts with backoff. Polling remains available. Key revocation or expiry stops callbacks. Rotating server signing credentials invalidates existing callback secrets; create a new job after rotation if needed. Completion is not publication or approval.

Handle errors and retries

Error response shape
{
  "error": "Key expired, revoked, unavailable or missing this scope."
}

Most errors return an error string. Agent refusals may also include code; after streaming begins, errors are NDJSON events even if the HTTP response began with 200.

HTTP statusMeaningNext step
400Invalid JSON or fieldsCorrect the request. Retrying unchanged invalid input will not help.
401Missing, expired, revoked or insufficiently scoped keyCheck workspace, permissions and expiry; replace or revoke keys in Settings.
402Insufficient credits or agent cap reachedReview Billing and the agent cap before retrying.
403Access refusedCheck the issuing owner’s current access and workspace policy.
404Project, task, conversation or job unavailableCheck the ID, workspace and issuing key.
409Conflicting retry, expired quote, cap or unavailable stateRead the error. Reuse an existing request/job where appropriate; avoid duplicate paid work.
413Request too largeReduce the payload. Limits differ by endpoint.
422Task cannot be preparedChoose a task with preparable: true or complete it in the workspace.
429Per-key rate limit reachedHonor Retry-After (normally 60 seconds), then retry with backoff.
500 / 503Temporary server or provider/configuration issueUse bounded backoff. Check existing write/job state before creating another request.

For rate limits, honor Retry-After (normally 60 seconds). Use bounded backoff for temporary failures. Preserve the same requestKey and identical payload for uncertain writes, and check existing task/job status before creating another paid attempt.

A failed media generation can refund wallet credits while retaining its daily API-cap reservation. An expired quote or changed source can require a new quote. An error is not permission to repeat spending without approval.

Connect Claude Code

Configure the key in Claude Code’s server environment, then copy this prompt. The public guide and downloads contain documentation only; they do not reveal your projects or credentials.

Claude Code connection prompt
Connect to the Meyer Launch API using MEYER_LAUNCH_API_KEY from my server environment. Never print, commit or expose the key in client code or URLs.
Read https://meyerlaunch.com/help/api and its OpenAPI document at https://meyerlaunch.com/help/api/openapi.json.
Start read-only with GET https://meyerlaunch.com/api/v1/projects and help me choose a project. Use only permissions granted to the key.
Ask before creating plans, preparing tasks, sending events, messaging the agent or confirming media quotes. Show fixed or quoted credit costs before spending; explain variable agent charges and the workspace cap before requesting approval. Agent calls spend variable credits without a quote; task preparation costs 1 workspace credit; media uses quote then confirmation.
Reuse requestKey and identical input for retries. Respect 429/Retry-After. Do not assume undocumented endpoints exist. Do not send synthetic purchase events.
Keep generated work as drafts for review. Report successful checks and missing permissions; do not claim publication, campaign delivery or paid conversions from a successful API response.

Keep the first check read-only. A successful connection proves access to the returned workspace records; it does not prove that an ad was delivered, a payment occurred or a customer converted.

Need help? info@meyerappstudio.com. Share the endpoint and safe error text, never your key.