Layers
Partner APIAPI referenceSDK apps

POST /v1/projects/:projectId/sdk-apps

Provision an SDK app for a project. Returns the ingest endpoint and API key once.

View as Markdown
POST/v1/projects/:projectId/sdk-apps
Phase 1stableidempotent
Auth
Bearer
Scope
projects:write

Creates an SDK app and creates its ingest API key. An SDK app is the binding between a platform build (iOS bundle, Android package, web domain) and the Layers event pipeline - once installed, the client SDK sends events to in.layers.com/l/events authenticated with the key returned here.

The API key in the response is shown once. Store it immediately - Layers does not display it again. Rotation is available via PATCH /v1/projects/:projectId/sdk-apps/:appId.

Path
  • projectId
    stringrequired
    Project ID.
Headers
  • Idempotency-Key
    string (UUID)required
    See [Idempotency](/docs/api/operational/idempotency). Recommended on every POST.
Body
  • name
    stringrequired
    Human-readable app name, 1–128 chars.
  • platform
    stringrequired
    Target platform.
    One of: ios, android, web, react-native, flutter, expo, nextjs, vite, react-router
  • bundleId
    stringoptional
    iOS bundle identifier, required when platform is ios.
  • androidPackage
    stringoptional
    Android package name, required when platform is android.
  • webDomain
    stringoptional
    Apex domain for web / Next.js / Vite / React Router installs, required when platform is one of those.

Example request

curl https://api.layers.com/v1/projects/prj_9cb958b5-11b5-4e30-8675-5d075d52da7c/sdk-apps \
  -H "Authorization: Bearer lp_..." \
  -H "Idempotency-Key: 2f0e1c88-4b1d-4ac1-bc0a-5e9f6d8a7b10" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme Coffee iOS",
    "platform": "ios",
    "bundleId": "com.acmecoffee.ios"
  }'
const app = await layers.sdkApps.create(
  "9cb958b5-11b5-4e30-8675-5d075d52da7c",
  {
    name: "Acme Coffee iOS",
    platform: "ios",
    bundleId: "com.acmecoffee.ios",
  },
  { idempotencyKey: crypto.randomUUID() }
);
// Store app.apiKey now - it won't be shown again.
app = layers.sdk_apps.create(
    project_id="prj_9cb958b5-11b5-4e30-8675-5d075d52da7c",
    name="Acme Coffee iOS",
    platform="ios",
    bundle_id="com.acmecoffee.ios",
    idempotency_key=str(uuid.uuid4()),
)
# Store app["apiKey"] now - it won't be shown again.

Response

201Created
{
  "appId": "app_8ffb9410eb0eb848264f8a65",
  "name": "Acme Coffee iOS",
  "platform": "ios",
  "bundleId": "com.acmecoffee.ios",
  "androidPackage": null,
  "webDomain": null,
  "ingestEndpoint": "https://in.layers.com/l/events",
  "capi": {},
  "createdAt": "2026-04-18T19:25:22Z",
  "lastRotatedAt": "2026-04-18T19:25:22Z",
  "lastEventAt": null,
  "apiKey": "sk_app_8eRq...k2P"
}

capi is an empty object until you enable per-platform forwarding via PATCH. lastRotatedAt is set to createdAt on first creation.

apiKey is returned only on creation and rotation. If you lose it, rotate via PATCH to create a new one - the previous key is invalidated immediately.

Errors

StatusCodeWhen
422VALIDATION:projectId is not a UUID, platform unknown, or missing platform-specific identifier (bundleId, androidPackage, webDomain).
401UNAUTHENTICATEDMissing or invalid key.
403FORBIDDEN_SCOPEKey lacks projects:write.
404NOT_FOUNDProject does not exist in the key's organization.
409IDEMPOTENCY_CONFLICTSame Idempotency-Key replayed with a different body.
409CONFLICTSDK app with the supplied (platform, bundleId/androidPackage/webDomain) already exists.
422VALIDATION_FAILEDBody includes appId (resource ids are server-minted — see Idempotency).
429RATE_LIMITEDWrite budget exhausted.

See also

On this page