PATCH /v1/projects/:projectId/sdk-apps/:appId
Update SDK-app config, enable CAPI for a platform, or rotate the API key.
/v1/projects/:projectId/sdk-apps/:appId- 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-scope — ads:write:capi — when minting partner keys that need to flip CAPI per-app.
projectIdstringrequiredProject ID.appIdstringrequiredSDK app ID.
namestringoptional1–128 chars.bundleIdstringoptionaliOS builds only.androidPackagestringoptionalAndroid builds only.webDomainstringoptionalWeb builds only.capiobjectoptionalPer-platform CAPI toggles. Shape: { meta?: { enabled }, tiktok?: { enabled }, apple?: { enabled } }.rotateKeybooleanoptionalIf 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
{
"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
| Status | Code | When |
|---|---|---|
| 422 | VALIDATION | Unknown field, platform-identifier mismatch (e.g. passing androidPackage on an iOS app). |
| 401 | UNAUTHENTICATED | Missing or invalid key. |
| 403 | FORBIDDEN_SCOPE | Key lacks projects:write. |
| 404 | NOT_FOUND | Project or SDK app does not exist. |
| 409 | CONFLICT | CAPI enable requested for a platform without the required pixel or credential. Connect the ad account first. |
| 429 | RATE_LIMITED | Write budget exhausted. |
See also
GET /v1/projects/:projectId/sdk-apps/:appId- read current state- Ad accounts OAuth - prerequisite for CAPI enable