Appearance
Subscribers
Register and manage push notification subscribers. A subscriber represents a device or browser endpoint that can receive notifications.
Base URL: https://app.krafter.dev/api/v1
Subscriber retention
PushCleanupWorker runs daily at 03:00 UTC (config.exs:89) and performs two passes (push_cleanup_worker.ex:31-62):
- Mark inactive after 90 days — subscribers whose
last_active_atis older than 90 days and whose status is notunsubscribedare flipped tostatus: "inactive". - Delete after 180 days —
inactivesubscribers whoselast_active_at(orinserted_at, whenlast_active_atisnil) is older than 180 days are deleted from the database. After both passes the parentPushApp.subscriber_countis recomputed from the count of remainingactivesubscribers, so the field always reflects reality.
If you re-register a deleted subscriber's token after this window, you get a fresh row with a new id. Tokens that the provider has already revoked (gone / unregistered errors during delivery) are marked inactive immediately by Push.mark_inactive/1, regardless of the 90-day rule.
List Subscribers
Retrieve subscribers for a specific app, with optional filtering by platform and status.
GET /push/apps/:app_id/subscribers?platform=...&status=...&limit=50&offset=0Required scope: push:read
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
platform | string | Filter by platform: web, ios, android. | |
status | string | Filter by status: active, inactive, unsubscribed (lib/krafter/push/push_subscriber.ex:34). inactive is set by Push.mark_inactive/1 after delivery failures or token expiry. | |
limit | integer | 50 | Maximum number of subscribers to return. |
offset | integer | 0 | Number of subscribers to skip for pagination. |
Example Request
bash
curl "https://app.krafter.dev/api/v1/push/apps/a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d/subscribers?platform=web&limit=20" \
-H "Authorization: Bearer kr_live_abc123def456"Example Response
json
{
"data": [
{
"id": "c3d4e5f6-7a8b-9c0d-1e2f-3a4b5c6d7e8f",
"app_id": "a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
"platform": "web",
"user_id": "usr_123",
"tags": ["beta", "premium"],
"properties": {
"browser": "Chrome",
"os": "macOS"
},
"status": "active",
"last_active_at": "2025-06-14T18:30:00Z",
"created_at": "2025-06-01T10:00:00Z",
"updated_at": "2025-06-14T18:30:00Z"
},
{
"id": "d4e5f6a7-8b9c-0d1e-2f3a-4b5c6d7e8f9a",
"app_id": "a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
"platform": "web",
"user_id": null,
"tags": [],
"properties": {
"browser": "Firefox",
"os": "Windows"
},
"status": "active",
"last_active_at": "2025-06-13T09:15:00Z",
"created_at": "2025-06-03T14:20:00Z",
"updated_at": "2025-06-13T09:15:00Z"
}
]
}Register Subscriber
Register a new subscriber or update an existing one. If a subscriber with the same token already exists, it is upserted with the new data. Returns 200 OK for both insert and update — the controller does not distinguish create from upsert (push_controller.ex:166).
POST /push/apps/:app_id/subscribersRequired scope: push:write
Rate limit (strict)
Subscriber registration uses the strict bucket — 30 requests / 60 seconds per team, shared with flags/{evaluate,bootstrap,track} and audit/scans/run. Have your client register once at app launch (not on every page load), and consider deduplicating on the SDK side before posting.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
platform | string | Yes | Device platform: web, ios, or android. |
token | string | Yes | Push subscription token or endpoint URL. |
user_id | string | No | Your application's user identifier for targeting. |
tags | string[] | No | Tags for segmenting subscribers (e.g., ["beta", "premium"]). |
properties | object | No | Custom key-value properties for the subscriber. |
Example Request
bash
curl -X POST https://app.krafter.dev/api/v1/push/apps/a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d/subscribers \
-H "Authorization: Bearer kr_live_abc123def456" \
-H "Content-Type: application/json" \
-d '{
"platform": "web",
"token": "https://fcm.googleapis.com/fcm/send/eKqL...",
"user_id": "usr_123",
"tags": ["beta", "premium"],
"properties": {
"browser": "Chrome",
"os": "macOS"
}
}'Example Response
json
// 200 OK
{
"data": {
"id": "c3d4e5f6-7a8b-9c0d-1e2f-3a4b5c6d7e8f",
"app_id": "a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
"platform": "web",
"user_id": "usr_123",
"tags": ["beta", "premium"],
"properties": {
"browser": "Chrome",
"os": "macOS"
},
"status": "active",
"last_active_at": "2025-06-01T10:00:00Z",
"created_at": "2025-06-01T10:00:00Z",
"updated_at": "2025-06-01T10:00:00Z"
}
}Update Subscriber
Update an existing subscriber's user_id, tags, or properties. The push token, platform, and status cannot be changed via this endpoint — re-register the subscriber with a fresh token to rotate it. Only fields explicitly present in the request body are touched (push_controller.ex:175-194); omitted keys keep their existing values.
PATCH /push/apps/:app_id/subscribers/:subscriber_idRequired scope: push:write
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
user_id | string | No | Replace your application's user identifier. Send null to clear it. |
tags | string[] | No | Replace the full tag list (this is a set, not a delta — pass the desired final state). |
properties | object | No | Replace the full custom-properties map. |
Example Request
bash
curl -X PATCH https://app.krafter.dev/api/v1/push/apps/a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d/subscribers/c3d4e5f6-7a8b-9c0d-1e2f-3a4b5c6d7e8f \
-H "Authorization: Bearer kr_live_abc123def456" \
-H "Content-Type: application/json" \
-d '{
"user_id": "usr_456",
"tags": ["beta", "premium", "ios"]
}'Example Response
json
{
"data": {
"id": "c3d4e5f6-7a8b-9c0d-1e2f-3a4b5c6d7e8f",
"app_id": "a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
"platform": "web",
"user_id": "usr_456",
"tags": ["beta", "premium", "ios"],
"properties": {
"browser": "Chrome",
"os": "macOS"
},
"status": "active",
"last_active_at": "2025-06-14T18:30:00Z",
"created_at": "2025-06-01T10:00:00Z",
"updated_at": "2025-06-15T09:00:00Z"
}
}Unsubscribe
Remove a subscriber. The subscriber will no longer receive notifications.
DELETE /push/apps/:app_id/subscribers/:subscriber_idRequired scope: push:write
Example Request
bash
curl -X DELETE https://app.krafter.dev/api/v1/push/apps/a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d/subscribers/c3d4e5f6-7a8b-9c0d-1e2f-3a4b5c6d7e8f \
-H "Authorization: Bearer kr_live_abc123def456"Example Response
// 204 No Content