Layers
Partner APIOperational

Security & compliance

PII handling, encryption, subprocessors, partner authentication, key revocation, kill-switch.

View as Markdown

How we handle your data and your customers' data, what third parties touch it, and how to revoke access in a hurry.

Security contact: security@layers.com. PGP key available on request.

Commercial terms (signed DPA, custom retention, security questionnaires, audit reports) are negotiated at contract time. Contact legal@layers.com.

What data flows where

Three classes of data cross the network:

  1. Partner API traffic. The bytes you send to api.layers.com/v1/*. Metadata (org, project, container ids) is logged with the request for 30 days; the body is not persisted beyond in-memory request scope.
  2. Customer SDK events. Events your app emits via the Layers SDK to in.layers.com. These carry the app-supplied user_id, optional email, optional phone, device identifiers, and the event properties you put on the payload. See PII handling at the SDK ingest below.
  3. Generated + inbound social content. Video/image assets generated for your projects, plus public-post metadata pulled from connected social accounts and (for UGC) via SIFT.

PII handling at the SDK ingest

The SDK ingest endpoint at in.layers.com is the only customer-PII entry point. Before events are persisted, direct identifiers are normalized and SHA-256 hashed in process — plaintext email and phone are never written to storage.

FieldTreatment
emailLower-cased, trimmed, SHA-256 hashed before persist + before CAPI forwarding.
phoneDigits-only normalization, then SHA-256.
user_idStored as-is. This is the id you assign — we recommend it not carry PII.
app_user_id, revenuecat_original_app_user_idStored as-is.
IP addressDropped at the edge after geo-IP region resolution.
Raw device identifiers (IDFA/GAID)Forwarded to ad platforms only when you enable CAPI; not retained server-side past the forward.

If your SDK integration sends emails with inconsistent casing or whitespace, the hash still matches because we normalize before hashing.

Compliance scope

  • HIPAA — Not in scope. Layers does not process PHI. Partners must not transmit PHI via the API or the SDK.
  • PCI DSS — Not in scope. Layers does not handle cardholder data; billing is delegated to Stripe.
  • GDPR / CCPA — DPA available on request. See Data protection.

For security questionnaires, audit artifacts, or a signed DPA, email legal@layers.com.

Encryption

At rest. All primary-database data is encrypted at rest with AES-256. Column-level secrets (OAuth tokens, webhook signing secrets, CAPI access tokens) are additionally encrypted at rest with a column-level secret store — decryption requires the service role and happens at usage time in the background-processing tier, never in the partner API request path. Object storage for generated media uses provider-managed encryption keys.

In transit. TLS 1.2 or higher required everywhere. api.layers.com, in.layers.com, and docs.layers.com terminate TLS at a managed edge with managed certificates; HTTP traffic is redirected to HTTPS. Internal service-to-service traffic runs over private networking.

Subprocessors

We name every vendor that stores or processes partner or end-customer data. This list is kept current.

Material sub-processor changes ship via the Changelog. The commercial side of this — advance-notice windows, objection rights, contractual remedies — is governed by your DPA.

SubprocessorPurposeData touched
Google Cloud PlatformApplication hosting, workflow orchestration, object storageAll application traffic, generated media, event stream
SupabasePrimary Postgres + auth + column-level secret storePartner API state, customer event records (hashed PII), OAuth tokens
UpstashRate-limit + idempotency cacheAPI key ids, per-minute counters, idempotency body hashes
SentryError trackingStack traces, request metadata (no bodies)
PostHogProduct analytics (internal)Layers-employee product usage; no partner-visible data
Google Vertex AI / GeminiLLM inference (content generation, scoring)Campaign prompts, brand/profile text
OpenAILLM inference (select pipelines)Same as above; per-request only, no training opt-in
AnthropicLLM inference (select pipelines)Same as above; per-request only
E2BSandboxed agent executionAgent scratch space only; purged on sandbox close
ReplicateModel hosting (image/video model inference)Generation inputs; per-request only
StripeCredit purchases + partner billingPartner billing contact, invoice metadata
ResendTransactional emailPartner recipient email; email body
LoopsLifecycle email (Layers account-owner only)Layers-employee email only
CloudflareEdge DNS + WAF on in.layers.comRequest metadata only; no bodies stored
SIFT (meetsift.com)Public social-post metadata retrievalPublic post IDs, public metrics; no private account data

Partner authentication

Partner API keys take the shape lp_<env>_<keyid>.<secret>. The secret portion is hashed with bcrypt at cost factor 12; only the hash is stored.

Verification is timing-safe: we use constant-time comparison so request timing can't leak whether a given key prefix exists.

Keys are never recoverable after issuance — we store only the bcrypt hash. If you lose a key, rotate it; we cannot send you the original.

Headers partners send

Authorization: Bearer lp_live_01HXZ9G7KMV2QX8Y1S5RJW3B7T.a4b3c2d1e0...

See Authentication for the wire-level specifics.

Key revocation

Three ways a key stops working, in operational precedence order:

  1. Kill switch (key.kill_switch = true). Immediate. Responses carry 503 KILL_SWITCH. Used for runaway clients or emergency shutoffs. Reversible without re-issuing the key. See Rate limits → Kill switch.
  2. Soft revoke (is_active = false or revoked_at set). Permanent. Responses carry 401 REVOKED. Used when a key is compromised, superseded, or the partnership ends. Not reversible — issue a fresh key.
  3. Organization-level kill (kill_switch.scope = "organization"). All keys for the org fail with 503 KILL_SWITCH. Contractual remedy only.

Self-serve revocation

When to revoke

  • A key appeared in a git commit, a log file, or any place you can't scrub completely.
  • An employee with access to a key left.
  • Any suspicion the secret is out of your control.

Rotating is free. Revoking is free. We'd rather see five false alarms than miss one real leak.

Kill-switch semantics

The kill switch is a per-key (or per-org, or global) boolean that short-circuits request handling after authentication but before business logic. It returns 503 KILL_SWITCH with details.scope ∈ {"key", "organization", "global"}.

We flip it ourselves in two cases:

  • Runaway client — you're paging an upstream platform at a rate that risks getting Layers or your app rate-limited by Meta/TikTok/Apple. We'd rather stop you than let a cascading ban happen. You'll hear from us on your partner channel the same minute.
  • Upstream incident — a platform is down in a way where retrying makes things worse. Global kill buys the ecosystem time to recover.

A kill is never silent. We post to the support and message your partner contact.

Responsible disclosure

If you find a vulnerability, email security@layers.com with repro steps and the requestId of any affected request. We aim to reply promptly and will not pursue legal action against good-faith researchers operating within the standard safe-harbor terms.

Layers does not currently run a paid bug-bounty program.

Please do not open public GitHub issues for vulnerabilities.

See also

On this page