Layers
Partner APIAPI referenceSDK apps

PATCH /v1/projects/:projectId/sdk-apps/:appId

Update SDK-app config, enable CAPI for a platform, or rotate the API key.

View as Markdown
PATCH/v1/projects/:projectId/sdk-apps/:appId
Phase 1stable
Auth
Bearer
Scope
projects:write

Patch any user-editable field on an SDK app, enable or disable CAPI forwarding per ad platform, or force a key rotation. Omitted fields stay unchanged.

Passing rotateKey: true is the only case where the response includes a plaintext apiKey - the old key is invalidated immediately. Clients using the old key start receiving 401 on the ingest endpoint.

Enabling CAPI requires a configured platform pixel and a valid ad-platform credential. Set these up via the ad-accounts OAuth flow before flipping capi.{platform}.enabled here.

CAPI toggle wires through. As of 2026-05-08, the capi block on this PATCH writes through to project_layers.config.capi — the same path the SDK relay reads at https://in.layers.com. Previous releases accepted the toggle but did not propagate it to the relay's read path (CF-3); that disconnection is fixed. Verify end-to-end with POST …/verify-tracking.

Use the capi:write sub-scopeads:write:capi — when minting partner keys that need to flip CAPI per-app.

Path
  • projectId
    stringrequired
    Project ID.
  • appId
    stringrequired
    SDK app ID.
Body
  • name
    stringoptional
    1–128 chars.
  • bundleId
    stringoptional
    iOS builds only.
  • androidPackage
    stringoptional
    Android builds only.
  • webDomain
    stringoptional
    Web builds only.
  • capi
    objectoptional
    Per-platform CAPI toggles. Shape: { meta?: { enabled }, tiktok?: { enabled }, apple?: { enabled } }.
  • rotateKey
    booleanoptional
    If true, create a fresh API key and invalidate the current one. The new key is returned once.

Example request

curl -X PATCH "https://api.layers.com/v1/projects/prj_9cb958b5-11b5-4e30-8675-5d075d52da7c/sdk-apps/app_8ffb9410eb0eb848264f8a65" \
  -H "Authorization: Bearer lp_..." \
  -H "Content-Type: application/json" \
  -d '{
    "capi": { "meta": { "enabled": true } },
    "rotateKey": true
  }'
const app = await layers.sdkApps.update(
  "9cb958b5-11b5-4e30-8675-5d075d52da7c",
  "app_8ffb9410eb0eb848264f8a65",
  {
    capi: { meta: { enabled: true } },
    rotateKey: true,
  }
);
// Store app.apiKey - the previous key is dead.
app = layers.sdk_apps.update(
    project_id="prj_9cb958b5-11b5-4e30-8675-5d075d52da7c",
    app_id="app_8ffb9410eb0eb848264f8a65",
    capi={"meta": {"enabled": True}},
    rotate_key=True,
)
# Store app["apiKey"] - the previous key is dead.

Response

200OK
{
  "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": {
    "meta": { "enabled": true }
  },
  "createdAt": "2026-04-18T19:25:22Z",
  "lastRotatedAt": "2026-04-18T19:31:42Z",
  "lastEventAt": "2026-04-18T19:42:11Z",
  "apiKey": "sk_app_3mNp...x9F"
}

The response body is the full SDK-app shape (same as GET /v1/projects/:projectId/sdk-apps/:appId) plus apiKey when rotateKey: true was set. capi only carries entries for platforms you've toggled - pixel/lastForwardAt fill in once the ad-account OAuth flow has stored credentials and the relay has forwarded an event.

Errors

StatusCodeWhen
422VALIDATIONUnknown field, platform-identifier mismatch (e.g. passing androidPackage on an iOS app).
401UNAUTHENTICATEDMissing or invalid key.
403FORBIDDEN_SCOPEKey lacks projects:write.
404NOT_FOUNDProject or SDK app does not exist.
409CONFLICTCAPI enable requested for a platform without the required pixel or credential. Connect the ad account first.
429RATE_LIMITEDWrite budget exhausted.

See also

On this page