# SDK Architecture (/docs/sdk/architecture)



```
[ Your app ]
   ↓ (Layers SDK)
   ↓ HTTPS POST → in.layers.com/events         (returns 202)
   ↓
[ Layers SDK ingest ]
   ↓
[ Async processing ]
   ↓
[ durable event store ]
   ↓
[ CAPI relay ]
   ├──→ Meta CAPI       (SDK events mapped to standard Meta events; unmapped dropped)
   ├──→ TikTok Events   (SDK events mapped to standard TikTok events; unmapped dropped)
   └──→ Apple Search Ads (uses attribution token from the SDK, via a separate sync job)
```

## The reverse-proxy entry point [#the-reverse-proxy-entry-point]

`in.layers.com` is the SDK's only client-side endpoint. Why a reverse
proxy:

* **Bypasses ad-blockers.** A first-party-style domain is rarely
  blocked.
* **Single TLS termination** for SDK traffic.
* **Server-side enrichment** — IP, geo, and user-agent details are
  resolved at the edge and merged into each event before storage.
* **Returns 202 immediately** — fire-and-forget for the client.

Authentication is via the `X-App-Id` header; the SDK sends this on every
request. (A legacy `X-Api-Key` header is accepted but currently ignored
server-side for backward compatibility.)

## Async pipeline [#async-pipeline]

After ingest, events flow through an async queue. This means:

* The client doesn't block on platform-API success.
* Layers can retry CAPI delivery to Meta / TikTok if they're slow.
* A single client request can route to multiple platforms.

## CAPI relay decision [#capi-relay-decision]

For each ingested event:

1. Resolve the SDK app to its project.
2. Find the project's Meta / TikTok ad layers.
3. For each layer, check that it is active, CAPI is enabled, the pixel
   ID is set, and the access token can be decrypted.
4. If all checks pass, decrypt the access token from the
   [Layers credential vault](/docs/trust/vault) and POST to the platform.

## Event name mapping [#event-name-mapping]

The relay does NOT forward SDK event names verbatim. It translates them
to standard Meta and TikTok event names via a fixed map:

| SDK event                               | Meta CAPI              | TikTok Events          |
| --------------------------------------- | ---------------------- | ---------------------- |
| `purchase_success`, `paywall_purchased` | `Purchase`             | `Purchase`             |
| `subscription_start`                    | `Subscribe`            | `Purchase`             |
| `subscription_renew`                    | `Subscribe`            | —                      |
| `trial_start`                           | `StartTrial`           | `Purchase`             |
| `trial_convert`                         | `Subscribe`            | —                      |
| `sign_up`                               | `CompleteRegistration` | `CompleteRegistration` |
| `add_to_cart`                           | `AddToCart`            | `AddToCart`            |
| `content_open`                          | `ViewContent`          | `ViewContent`          |
| `search`                                | `Search`               | `Search`               |
| `purchase_attempt`                      | `InitiateCheckout`     | —                      |
| `bookmark_add`                          | `AddToWishlist`        | —                      |
| `screen_view`                           | —                      | `PageView`             |

Events not in the map are stored in the durable event store but
**dropped at the relay** — they are not forwarded to Meta or TikTok.

Per-app overrides are supported via an `event_map` on the layer's
CAPI config, which takes precedence over the defaults above.

## Event ID dedup [#event-id-dedup]

Each event has a UUID `event_id`. Forwarded as Meta's `event_id` and
TikTok's `event_id`, allowing both platforms to dedupe against any
client-side Pixel you may also have running.

## Latency [#latency]

* **Client → in.layers.com** is a fire-and-forget POST that returns `202`
  once the request is accepted.
* **Ingest → CAPI relay** runs asynchronously. End-to-end latency from an
  event firing in the app to becoming visible in Meta Events Manager /
  TikTok Events Debugger is typically measured in seconds but can spike
  during platform incidents.

## Reliability [#reliability]

* **At-least-once** delivery to platforms.
* **Dedup** via `event_id` at the platform level (Meta / TikTok dedupe
  on `event_id`).
* **Retry** on transient failures with backoff; permanent failures are
  logged.

## What's NOT in this pipeline [#whats-not-in-this-pipeline]

* Client-side Pixel SDKs are NOT installed by Layers. If you also have a
  Meta Pixel on your marketing site, that's a separate client-side
  integration; Layers' CAPI relay deduplicates against it via
  `event_id`.
* AppsFlyer / Adjust SDKs can run alongside Layers for non-Meta /
  non-TikTok ad networks; they do not interfere.
