# SDK HTTP API reference

The public SDK contract for event ingestion, published configuration and experiment assignments. Base URL: https://aplyna.com.

## Authentication

Send Authorization: Bearer YOUR_APP_SDK_KEY on every SDK request. The key determines the organization and application. Do not send a client-controlled organization ID or use an Apple private key. These endpoints are for native clients; account/dashboard administration uses a different authenticated boundary.

### HTTP

```
Authorization: Bearer YOUR_APP_SDK_KEY
Content-Type: application/json
```

## POST /api/v1/events

Consent must be true. Send 1–100 events with stable IDs and timestamps. The example is an onboarding event, not a payment.

### Shell · replace placeholders

```
curl --fail-with-body https://aplyna.com/api/v1/events \
  -H "Authorization: Bearer YOUR_APP_SDK_KEY" \
  -H "Content-Type: application/json" \
  --data '{"consent":true,"events":[{
    "event_id":"evt_REPLACE_WITH_UNIQUE_ID",
    "installation_id":"YOUR_PERSISTED_INSTALLATION_ID",
    "name":"onboarding_step_viewed",
    "flow_id":"YOUR_FLOW_ID",
    "step_id":"welcome",
    "occurred_at":"REPLACE_WITH_CURRENT_ISO8601_TIMESTAMP",
    "properties":{"app_version":"1.0.0"}
  }]}'
```

| Response | Meaning |
| --- | --- |
| 202 Accepted | Validated ingestion response with accepted, duplicates, received_at and cloud delivery status. SDK receipt is not verified payment confirmation. |
| accepted | Number of newly accepted events. |
| duplicates | Events already stored under the same app and event ID. |
| received_at | Server receipt timestamp; separate from client occurred_at. |
| cloud | Event-forwarding status. App processing configuration may differ; this does not mean a store is connected. |

A curl timestamp placeholder must be replaced with a current ISO timestamp before running. Reuse the event ID when retrying that same event. The app-level ingestion rate limit is 600 requests per minute; handle 429 responses with bounded backoff.

## GET /api/v1/config

| Query | Value |
| --- | --- |
| flow_id | Required published flow belonging to the SDK key's app. |
| schema_version | 1 or 2, representing the maximum schema the client understands. Defaults to 1. |

### Shell

```
curl --fail-with-body --get https://aplyna.com/api/v1/config \
  -H "Authorization: Bearer YOUR_APP_SDK_KEY" \
  --data-urlencode "flow_id=YOUR_FLOW_ID" \
  --data-urlencode "schema_version=2"
```

Returns 200 and the published configuration, including schema_version and steps. ETag identifies the immutable release; Cache-Control is private, max-age=30. Send If-None-Match with the returned ETag to receive 304 if unchanged. A 304 has no JSON body. A newer layout than the declared schema returns 422; an unpublished or unavailable flow returns 404.

## GET /api/v1/assignment

| Query | Value |
| --- | --- |
| flow_id | Required published app-scoped flow. |
| installation_id | Required persisted pseudonymous installation identity. |

### Shell

```
curl --fail-with-body --get https://aplyna.com/api/v1/assignment \
  -H "Authorization: Bearer YOUR_APP_SDK_KEY" \
  --data-urlencode "flow_id=YOUR_FLOW_ID" \
  --data-urlencode "installation_id=YOUR_PERSISTED_INSTALLATION_ID"
```

### JSON · example control without an active experiment

```
{
  "variant": "A",
  "experiment_id": null,
  "flow_id": "YOUR_FLOW_ID"
}
```

The response uses Cache-Control: no-store. An active experiment can return its ID and A/B variant. This request does not record an exposure. Attach the returned assignment to exposure and conversion events.

## Errors and retries

### JSON · error envelope

```
{"error":"Readable error message"}
```

| Status | Action |
| --- | --- |
| 400 | Fix malformed JSON or schema validation failures; inspect the error field. |
| 401 / 403 | Check the app SDK key and authorization. Do not retry indefinitely. |
| 404 | Check the flow ID, publication and application scope. |
| 413 | Reduce request size below the body limit. |
| 422 | Check timestamps, semantic validation or requested configuration schema. |
| 429 | Rate limit reached; wait and use bounded retry/backoff. |
| 5xx / network failure | Retain queued IDs and retry later, with a native fallback for configuration. |

- [Troubleshooting guide](https://aplyna.com/docs/troubleshooting): Diagnose missing events and delivery failures.
