{
  "components": {
    "schemas": {
      "Body_import_ndjson_route_v1_apps__app_id__import_ndjson_post": {
        "properties": {
          "file": {
            "contentMediaType": "application/octet-stream",
            "title": "File",
            "type": "string"
          }
        },
        "required": [
          "file"
        ],
        "title": "Body_import_ndjson_route_v1_apps__app_id__import_ndjson_post",
        "type": "object"
      },
      "Body_import_subscriptions_v1_apps__app_id__import_post": {
        "properties": {
          "file": {
            "contentMediaType": "application/octet-stream",
            "title": "File",
            "type": "string"
          }
        },
        "required": [
          "file"
        ],
        "title": "Body_import_subscriptions_v1_apps__app_id__import_post",
        "type": "object"
      },
      "HTTPValidationError": {
        "properties": {
          "detail": {
            "items": {
              "$ref": "#/components/schemas/ValidationError"
            },
            "title": "Detail",
            "type": "array"
          }
        },
        "title": "HTTPValidationError",
        "type": "object"
      },
      "MessageSendResult": {
        "additionalProperties": true,
        "description": "Immediate-send response from POST /messages.",
        "properties": {
          "failed": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Failed"
          },
          "funnel": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Funnel"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "note": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Note"
          },
          "provider_accepted": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "FCM/APNs accepted the push; this is not a device receipt.",
            "title": "Provider Accepted"
          },
          "report": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Path of the message report.",
            "title": "Report"
          },
          "sent": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Sent"
          },
          "status": {
            "description": "The message's state. A delivery status for an immediate send, `Scheduled` for a future one, or `pending_approval` on a `202` when the app requires a second person to approve a send — in which case nothing has been sent or scheduled.",
            "title": "Status",
            "type": "string"
          },
          "title": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Title"
          },
          "warnings": {
            "description": "Advisory only — never a refusal. An `audience_collision` entry means this audience already had, or is about to have, another message inside 24 hours: {code, message, message_id, name, at, overlap_pct}. `overlap_pct` is null when the two audience definitions are identical and nothing needed measuring. A `blast_radius` entry means this send is far larger than this app's usual one — at least 500 devices, and over both 3x the median of the last ten sends and half of everyone subscribed: {code, message, audience, median_recent, subscribed, reason}. `median_recent` is null when the app has never sent, and `reason` is `3x_median` or `half_of_app` — whichever bar was binding.",
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "title": "Warnings",
            "type": "array"
          }
        },
        "required": [
          "id",
          "status"
        ],
        "title": "MessageSendResult",
        "type": "object"
      },
      "ValidationError": {
        "properties": {
          "ctx": {
            "title": "Context",
            "type": "object"
          },
          "input": {
            "title": "Input"
          },
          "loc": {
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "integer"
                }
              ]
            },
            "title": "Location",
            "type": "array"
          },
          "msg": {
            "title": "Message",
            "type": "string"
          },
          "type": {
            "title": "Error Type",
            "type": "string"
          }
        },
        "required": [
          "loc",
          "msg",
          "type"
        ],
        "title": "ValidationError",
        "type": "object"
      }
    },
    "securitySchemes": {
      "ApiKey": {
        "description": "Per-app REST key, or the global OP_API_KEY.",
        "in": "header",
        "name": "X-OP-API-Key",
        "type": "apiKey"
      },
      "DataSourceKey": {
        "description": "Receiving key for one incoming Data connection. Not a REST or SDK key.",
        "scheme": "bearer",
        "type": "http"
      },
      "RestAuthorization": {
        "description": "REST key for Live Activity sends; use Authorization: Key <REST API key>.",
        "in": "header",
        "name": "Authorization",
        "type": "apiKey"
      },
      "SdkKey": {
        "description": "Per-app SDK key, or the global OP_SDK_KEY — device/ingest routes.",
        "in": "header",
        "name": "X-OP-SDK-Key",
        "type": "apiKey"
      }
    }
  },
  "info": {
    "description": "OpenPush sends push notifications to **iOS, Android and web** devices through\nFCM using your own credentials, and to iOS devices directly over APNs when the\napp has an APNs key and the device registered a real APNs device token.\nDelivery uses the app's configured platform credentials.\n\n## Base URL\n\nThe API is served from `https://app.openpush.ai`, and all examples use that\nhost.\nEverything except the health routes lives under `/v1`, and almost every route\nis scoped to a single app by its slug in the path:\n\n```\nhttps://app.openpush.ai/v1/apps/{app_id}/{resource}\n```\n\n`{app_id}` is the app's slug — the lowercase id you chose when the app was\ncreated (`runner-club`), not a generated identifier. Ids the API returns are\nprefixed and twelve hex characters: `msg_9f21c4a70b3d`, `sub_4b7e0a1c93df`.\n\n## Authentication\n\nEvery authenticated public REST API route takes a key in a header. Browser OAuth\nis available separately for MCP and the scanner CLI; those routes are outside\n`/v1` and omitted from this REST contract. There is no body signature.\n\n| Header | Key kind | What it can do |\n|---|---|---|\n| `X-OP-API-Key` | REST API key | Full admin of **one** app — send messages, read the audience, manage segments, templates, dynamic content, journeys, settings, exports and key rotation |\n| `X-OP-SDK-Key` | SDK key | **Ingest only** — register a subscription, post sessions, delivery receipts and custom events, register Live Activity tokens |\n\nThe two kinds are enforced by kind, not by convention: an SDK key presented on\nan admin route fails, and a REST key presented on an ingest route fails. That\nis what makes the **SDK key safe to ship inside a public app binary** — it is\ndesigned to be extracted, and it cannot send a message or read your audience.\nA **REST key must never be shipped in a binary**: it is full admin of that app,\nand a leaked one is a full compromise. Key comparison is constant-time.\n\nA per-app REST key resolves to exactly one app, so it cannot cross an app or a\nworkspace boundary. The deployment-level `OP_API_KEY` / `OP_SDK_KEY` are the\nexception: they match every app, and `OP_API_KEY` is the only credential\naccepted by `GET /v1/apps` and `POST /v1/apps`. Set `OP_GLOBAL_KEYS=off` to\nclose that hatch on `/v1`.\n\nThe two Live Activity migration routes additionally accept\n`Authorization: Key <REST API key>`. That spelling works only there — everywhere\nelse on `/v1` the native `X-OP-API-Key` header is required.\n\n## Errors\n\nSuccessful responses have no envelope: the resource *is* the body. An ordinary\nerror carries a single human-readable string:\n\n```json\n{\"detail\": \"priority must be 'high' or 'normal', not 'urgent'\"}\n```\n\nThere are two exceptions. The **Journeys** routes use a structured envelope so\nvalidation issues can be enumerated\n(`{\"errors\": [{\"code\": \"invalid-payload\", \"title\": \"…\", \"meta\": {…}}]}`), and\nthe **Live Activity** migration routes return a plain list\nof strings (`{\"errors\": [\"use exactly one targeting method\"]}`).\n\nAn unhandled exception returns a JSON body containing a short random error id\nand nothing else — no stack trace, no module names, no SQL. The traceback is\nlogged on the server against that id; quote it when reporting a problem.\n\n`404` on a send is worth calling out: an immediate send whose targeting matches\nno sendable subscription is refused, not recorded as a zero-audience campaign.\n\n## Rate limits\n\nThese routes have dedicated rate limits. Event accounting is shared across\nserver replicas; Live Activity migration rate accounting is process local.\n\n| Route | Limit | Response |\n|---|---|---|\n| `POST /v1/apps/{app_id}/events` | 500 events per app per 5 seconds | `429` with `Retry-After: 5` |\n| Live Activity migration routes | 60 requests per app per 60 seconds (`OP_COMPAT_RATE_MAX` / `OP_COMPAT_RATE_WINDOW_S`) | `429` with `Retry-After: 60` |\n\n**Nothing else is rate limited** — not message create, not `/v1/ingest`, not\nsubscription registration, not sessions, not send-test, not any segment,\ntemplate, dynamic-content or list route. What bounds those instead is the 8 MB\nrequest body ceiling (`OP_MAX_BODY_BYTES`; 150 MB on import uploads via\n`OP_MAX_IMPORT_BYTES`) and the `limit` clamp of 1000 on paginated reads.\n\nA `429` that originates inside APNs or FCM is the *provider* throttling\nOpenPush, not OpenPush throttling you; it drives our own retry and backoff and\nnever surfaces as an API response.\n\n## Idempotency\n\n**One route on `/v1` reads an `Idempotency-Key` header: `POST\n/v1/apps/{app_id}/messages`.** The value is 16-128 characters and yours to\nchoose. For 24 hours, the same key with the same body replays the original\nresponse — same status, same message id, and no second push — with\n`Idempotent-Replayed: true` on it. The same key with a *different* body is a\n`409`, and so is a key whose first request is still in flight. Nothing else on\n`/v1` reads the header, and a create sent **without** it is not deduplicated at\nall: a retry is a second send, to the same devices.\n\nThe Live Activity migration **start** route has its own, older spelling:\na **body field** named `idempotency_key` whose value must be a UUID. A replay\nthere returns the original `notification_id` with the same\n`Idempotent-Replayed: true` header and sends nothing; those records are\nretained for 30 days. It is not honoured on the update/end route.\n\nPractical guidance: send an `Idempotency-Key` on every create you would retry.\nWithout one, treat a send request that times out as *possibly delivered* — give\nevery campaign a distinct `name`, then poll `GET /v1/apps/{app_id}/messages`\nand match on `name` before retrying.\n",
    "title": "OpenPush",
    "version": "0.1.0"
  },
  "openapi": "3.1.0",
  "paths": {
    "/apps/{app_id}/activities/activity/{activity_type}": {
      "post": {
        "description": "Starts an iOS Live Activity on every targeted device that has already registered a **push-to-start token** for `{activity_type}`. The path is mounted at the server root, not under `/v1`.\n\n**Auth.** `Authorization: Key <REST API key>` or `X-OP-API-Key`. The `Authorization` header also accepts the `Basic`, `Bearer` and bare-value spellings, and in every one of them the raw REST key is taken as the literal text after the scheme word — `Basic` here is *not* RFC 7617 and nothing is base64-decoded.\n\n**Body.** `event` must be `\"start\"`. `activity_id` is required and cannot contain `/`. `event_attributes` (ActivityKit `attributes`) and `event_updates` (`content-state`) must both be non-empty objects. `name` is required and capped at 128 characters. `contents` and `headings` are required and must each carry a non-blank `en` entry. Optional: `stale_date` (unix **seconds**; a value at or above 1e11 is rejected as milliseconds), `priority` (`5` or `10`, default `10`), `ios_relevance_score` (0–1), `ios_sound`/`sound` (first non-blank wins), and `idempotency_key`.\n\n**Targeting.** Supply exactly one of `include_aliases`, `include_subscription_ids`, `included_segments` or `filters`; `excluded_segments` requires `included_segments`. Before anything is sent the server checks that at least one targeted device holds a push-to-start token for this activity type, and fails with `400` rather than reporting a send that reaches nobody.\n\n**Idempotency.** `idempotency_key` is the only idempotency mechanism in OpenPush and it is a body field, not a header. It must be a UUID; a replay returns the original `notification_id` with `Idempotent-Replayed: true` and sends nothing; records are retained for 30 days.\n\n**Caveats.** Unknown body keys return `400`; `is_ios`, `isAndroid`, `ios_interruption_level`, `apns_push_type_override`, `subtitle` and `custom_data` are not implemented. Errors use this pair's own envelope, `{\"errors\": [\"…\"]}`, not `detail`. Rate limited to 60 requests per app per 60 seconds, shared with the update/end route.",
        "operationId": "start_activity_apps__app_id__activities_activity__activity_type__post",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "activity_type",
            "required": true,
            "schema": {
              "title": "Activity Type",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "activity_id": "game-42",
                    "contents": {
                      "en": "The game is live"
                    },
                    "event": "start",
                    "event_attributes": {
                      "away": "B",
                      "home": "A"
                    },
                    "event_updates": {
                      "awayScore": 0,
                      "homeScore": 0
                    },
                    "headings": {
                      "en": "Game started"
                    },
                    "include_subscription_ids": [
                      "sub_123"
                    ],
                    "name": "Game started"
                  }
                }
              },
              "schema": {
                "additionalProperties": false,
                "description": "Root-level server route for starting an iOS Live Activity.",
                "properties": {
                  "activity_id": {
                    "title": "Activity Id",
                    "type": "string"
                  },
                  "contents": {
                    "additionalProperties": {
                      "type": "string"
                    },
                    "title": "Contents",
                    "type": "object"
                  },
                  "event": {
                    "const": "start",
                    "title": "Event",
                    "type": "string"
                  },
                  "event_attributes": {
                    "additionalProperties": true,
                    "title": "Event Attributes",
                    "type": "object"
                  },
                  "event_updates": {
                    "additionalProperties": true,
                    "title": "Event Updates",
                    "type": "object"
                  },
                  "excluded_segments": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Excluded Segments"
                  },
                  "filters": {
                    "anyOf": [
                      {
                        "items": {
                          "additionalProperties": true,
                          "type": "object"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Filters"
                  },
                  "headings": {
                    "additionalProperties": {
                      "type": "string"
                    },
                    "title": "Headings",
                    "type": "object"
                  },
                  "idempotency_key": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Idempotency Key"
                  },
                  "include_aliases": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "items": {
                            "type": "string"
                          },
                          "type": "array"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Include Aliases"
                  },
                  "include_subscription_ids": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Include Subscription Ids"
                  },
                  "included_segments": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Included Segments"
                  },
                  "ios_relevance_score": {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Ios Relevance Score"
                  },
                  "ios_sound": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Ios Sound"
                  },
                  "name": {
                    "title": "Name",
                    "type": "string"
                  },
                  "priority": {
                    "anyOf": [
                      {
                        "enum": [
                          5,
                          10
                        ],
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Priority"
                  },
                  "sound": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Sound"
                  },
                  "stale_date": {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Stale Date"
                  }
                },
                "required": [
                  "event",
                  "activity_id",
                  "event_attributes",
                  "event_updates",
                  "name",
                  "contents",
                  "headings"
                ],
                "title": "LiveActivityStartBody",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "notification_id": "msg_01hq8d"
                }
              }
            },
            "description": "Started. The response key is `notification_id` — note the update/end route answers with `id` instead. A replay of a used `idempotency_key` returns the original id plus the `Idempotent-Replayed: true` header."
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "errors": [
                    "use exactly one targeting method"
                  ]
                }
              }
            },
            "description": "Bad body, bad field value, zero or several targeting methods, an invalid segment filter, a non-UUID `idempotency_key`, or no device holding a push-to-start token for this activity type."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "errors": [
                    "bad API key — send `Authorization: Key <your app's REST API key>` or X-OP-API-Key"
                  ]
                }
              }
            },
            "description": "Missing or wrong REST key."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "errors": [
                    "not your row on this shared app"
                  ]
                }
              }
            },
            "description": "Refused for this app — a cross-tenant reach on a shared sample app."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "errors": [
                    "unknown app 'runner-club'"
                  ]
                }
              }
            },
            "description": "No such app."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "errors": [
                    "too many Live Activity requests for this app"
                  ]
                }
              }
            },
            "description": "Over 60 requests per app per 60 seconds (`OP_COMPAT_RATE_MAX` / `OP_COMPAT_RATE_WINDOW_S`). Carries `Retry-After`."
          }
        },
        "security": [
          {
            "ApiKey": []
          },
          {
            "RestAuthorization": []
          }
        ],
        "summary": "Start a Live Activity across an audience",
        "tags": [
          "Live Activities"
        ]
      }
    },
    "/apps/{app_id}/live_activities/{activity_id}/notifications": {
      "post": {
        "description": "Updates or ends an activity that is already running on devices. Targeting is **fixed to the `activity_id` in the path** — there are no segments, aliases or filters here, so every device still holding that activity is pushed. Mounted at the server root, not under `/v1`.\n\n**Auth.** `Authorization: Key <REST API key>` or `X-OP-API-Key`, exactly as on the start route.\n\n**Body.** `event` must be `\"update\"` or `\"end\"`. `event_updates` (the new `content-state`) is required and non-empty on an end too. `name` is required, 128 characters or fewer. `contents` and `headings` are optional, but if present must carry a non-blank `en` entry. `stale_date` is accepted on both events; `dismissal_date` is **end-only** and is a `400` on an update. Optional `priority` (`5` or `10`), `ios_relevance_score` (0–1) and `sound`/`ios_sound`.\n\n**Not honoured here.** `idempotency_key` is start-only — a retried update or end pushes again. Unknown body keys return `400`. Errors use this pair's own envelope, `{\"errors\": [\"…\"]}`. Rate limited to 60 requests per app per 60 seconds, shared with the start route.\n\nAn activity that has ended can never be updated again: both the pre-flight and a fan-out that reaches nobody answer `404`.",
        "operationId": "update_activity_apps__app_id__live_activities__activity_id__notifications_post",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "activity_id",
            "required": true,
            "schema": {
              "title": "Activity Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "event": "update",
                    "event_updates": {
                      "awayScore": 0,
                      "homeScore": 1
                    },
                    "name": "Half time"
                  }
                }
              },
              "schema": {
                "additionalProperties": false,
                "description": "Root-level server route for updating or ending an iOS Live Activity.",
                "properties": {
                  "contents": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Contents"
                  },
                  "dismissal_date": {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Dismissal Date"
                  },
                  "event": {
                    "enum": [
                      "update",
                      "end"
                    ],
                    "title": "Event",
                    "type": "string"
                  },
                  "event_updates": {
                    "additionalProperties": true,
                    "title": "Event Updates",
                    "type": "object"
                  },
                  "headings": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Headings"
                  },
                  "ios_relevance_score": {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Ios Relevance Score"
                  },
                  "ios_sound": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Ios Sound"
                  },
                  "name": {
                    "title": "Name",
                    "type": "string"
                  },
                  "priority": {
                    "anyOf": [
                      {
                        "enum": [
                          5,
                          10
                        ],
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Priority"
                  },
                  "sound": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Sound"
                  },
                  "stale_date": {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Stale Date"
                  }
                },
                "required": [
                  "event",
                  "event_updates",
                  "name"
                ],
                "title": "LiveActivityUpdateBody",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "id": "msg_01hq8e"
                }
              }
            },
            "description": "Pushed. The response key here is `id` — the start route answers with `notification_id` instead."
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "errors": [
                    "event must be \"update\" or \"end\" on this route"
                  ]
                }
              }
            },
            "description": "Bad body, an `event` that is neither `update` nor `end`, an empty `event_updates`, a `dismissal_date` on an update, or a bad `priority`, `stale_date` or relevance score."
          },
          "401": {
            "content": {
              "application/json": {
                "example": {
                  "errors": [
                    "bad API key — send `Authorization: Key <your app's REST API key>` or X-OP-API-Key"
                  ]
                }
              }
            },
            "description": "Missing or wrong REST key."
          },
          "403": {
            "content": {
              "application/json": {
                "example": {
                  "errors": [
                    "not your row on this shared app"
                  ]
                }
              }
            },
            "description": "Refused for this app — a cross-tenant reach on a shared sample app."
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "errors": [
                    "no live activity with that id is open on this app — an activity that has ended can never be updated again"
                  ]
                }
              }
            },
            "description": "Unknown app, or no open activity with that id on this app."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          },
          "429": {
            "content": {
              "application/json": {
                "example": {
                  "errors": [
                    "too many Live Activity requests for this app"
                  ]
                }
              }
            },
            "description": "Over 60 requests per app per 60 seconds. Carries `Retry-After`."
          }
        },
        "security": [
          {
            "ApiKey": []
          },
          {
            "RestAuthorization": []
          }
        ],
        "summary": "Update or end a running Live Activity",
        "tags": [
          "Live Activities"
        ]
      }
    },
    "/healthz": {
      "get": {
        "description": "Liveness plus the numbers an operator needs during an incident: app and\nsubscription counts, the running commit, whether FCM and APNs are configured, and the\nsend queue's depth. No authentication.\n\nThe `fcm` / `apns` flags are **server-wide** (the `APNS_P8` / FCM environment\ncredentials), not per app — per-app platform readiness is on\n`GET /v1/apps/{app_id}/settings` under `platforms`. If the queue backend is itself down,\n`queue` degrades to `{\"backend\": \"unavailable\", \"error\": ...}` rather than failing the\nhealth check.",
        "operationId": "healthz_healthz_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Health flags, app/subscription counts and send-queue stats"
          }
        },
        "summary": "Check server health",
        "tags": [
          "Health"
        ]
      }
    },
    "/status": {
      "get": {
        "description": "The human-readable status page — the same snapshot as `/status.json`,\nrendered as a self-contained HTML document. No authentication.",
        "operationId": "status_page_status_get",
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "An HTML status page"
          }
        },
        "summary": "View the status page",
        "tags": [
          "Health"
        ]
      }
    },
    "/status.json": {
      "get": {
        "description": "The machine-readable status snapshot behind the public status page:\ncomponent states and the recent history the page renders. No authentication.",
        "operationId": "status_json_status_json_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "A status snapshot object"
          }
        },
        "summary": "Read the status snapshot",
        "tags": [
          "Health"
        ]
      }
    },
    "/v1/apps": {
      "get": {
        "description": "Every app on the server, across every workspace, with subscriber count,\nCTR and monthly active users (both rounded and exact, so the figure can be reconciled\nagainst your own query).\n\n**Global operator key only.** There is no workspace-scoped version of this route: a\nper-app REST key knows one app, and listing a workspace's apps is a console operation that\nresolves the workspace from the signed-in session.",
        "operationId": "list_apps_v1_apps_get",
        "parameters": [],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Every app with subscriber, CTR and MAU figures"
          },
          "401": {
            "description": "This route needs the global operator key"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "List all apps",
        "tags": [
          "Apps, keys & settings"
        ]
      },
      "post": {
        "description": "Creates an app from a slug (`id`, or `slug`), optionally with a display\nname, and mints its key set. Calling it again with an existing slug returns that app rather\nthan failing.\n\n**Global operator key only, and the app lands in the default workspace** — a REST call\ncarries no console session and therefore no workspace to put it in. Creating an app inside\na specific workspace is a console action.",
        "operationId": "create_app_v1_apps_post",
        "parameters": [],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "id": "runner-club",
                    "name": "Runner Club"
                  }
                }
              },
              "schema": {
                "additionalProperties": true,
                "properties": {
                  "id": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "App slug; supply id or slug.",
                    "title": "Id"
                  },
                  "name": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Display name; defaults from the slug.",
                    "title": "Name"
                  },
                  "slug": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Alias of id.",
                    "title": "Slug"
                  }
                },
                "title": "AppCreate",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "The app row, including its freshly minted keys"
          },
          "400": {
            "description": "id (slug) required"
          },
          "401": {
            "description": "This route needs the global operator key"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Create an app",
        "tags": [
          "Apps, keys & settings"
        ]
      }
    },
    "/v1/apps/{app_id}": {
      "get": {
        "operationId": "get_app_metadata_v1_apps__app_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Get App Metadata",
        "tags": [
          "Apps, keys & settings"
        ]
      },
      "patch": {
        "operationId": "patch_app_metadata_v1_apps__app_id__patch",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "name": "My app"
                  }
                }
              },
              "schema": {
                "additionalProperties": true,
                "properties": {
                  "icon_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Icon Url"
                  },
                  "name": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Name"
                  },
                  "play_store_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Play Store Url"
                  },
                  "tile_color": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Tile Color"
                  }
                },
                "title": "AppMetadataUpdate",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "403": {
            "description": "Read-only API key or shared sample app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Patch App Metadata",
        "tags": [
          "Apps, keys & settings"
        ]
      }
    },
    "/v1/apps/{app_id}/activity-exports/{export_id}": {
      "get": {
        "operationId": "get_activity_export_v1_apps__app_id__activity_exports__export_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "export_id",
            "required": true,
            "schema": {
              "title": "Export Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Get Activity Export",
        "tags": [
          "Messages"
        ]
      }
    },
    "/v1/apps/{app_id}/activity-exports/{export_id}/download": {
      "get": {
        "operationId": "download_activity_export_v1_apps__app_id__activity_exports__export_id__download_get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "export_id",
            "required": true,
            "schema": {
              "title": "Export Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Download Activity Export",
        "tags": [
          "Messages"
        ]
      }
    },
    "/v1/apps/{app_id}/analytics/series": {
      "get": {
        "description": "One point per day for the window, and gaps are explicit `null`s rather than\nzeros — a chart must not draw \"we were not counting\" as \"we had no users\". Each point carries the\nsubscriber state columns and the derived send/delivery/click columns; the envelope carries\n`complete`, `missing_days`, `backfilled_days`, `imported_days` and `state_from` so the chart can be\nlabelled honestly. `days` is 1–400, `until` is `YYYY-MM-DD` (default today).",
        "operationId": "analytics_series_v1_apps__app_id__analytics_series_get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "days",
            "required": false,
            "schema": {
              "default": 30,
              "title": "Days",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "until",
            "required": false,
            "schema": {
              "default": "",
              "title": "Until",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Dense daily series with completeness flags"
          },
          "400": {
            "description": "Bad window"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "404": {
            "description": "Unknown app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Daily analytics series",
        "tags": [
          "Analytics"
        ]
      }
    },
    "/v1/apps/{app_id}/analytics/totals": {
      "get": {
        "description": "The derived columns summed over the window — sent, delivered, failed, dead,\nreceived, confirmed, clicked, messages — plus `ctr` and how much of the window is real\n(`days_with_data` against `days_requested`).",
        "operationId": "analytics_totals_v1_apps__app_id__analytics_totals_get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "days",
            "required": false,
            "schema": {
              "default": 30,
              "title": "Days",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "until",
            "required": false,
            "schema": {
              "default": "",
              "title": "Until",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Totals for the window"
          },
          "400": {
            "description": "Bad window"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "404": {
            "description": "Unknown app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Windowed analytics totals",
        "tags": [
          "Analytics"
        ]
      }
    },
    "/v1/apps/{app_id}/audience-preview": {
      "post": {
        "description": "Counts who a message would reach for the given `include_segments`,\n`exclude_segments`, `target` and generic `filters`, broken down by the delivery guards that would hold or drop\ndevices, and renders `title` and `body` against a **real sampled device** from that audience\nso the personalisation can be checked before sending.\n\nNothing is created and nothing is sent. Malformed rules or a half-specified target are a\n`400` here, exactly as they would be on the send.",
        "operationId": "audience_preview_v1_apps__app_id__audience_preview_post",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "body": "Preview only — nothing is sent.",
                    "exclude_segments": [
                      "Test Users"
                    ],
                    "filters": [
                      {
                        "field": "tag",
                        "key": "plan",
                        "op": "is",
                        "value": "pro"
                      },
                      {
                        "operator": "or"
                      },
                      {
                        "field": "country",
                        "op": "is",
                        "value": "US"
                      }
                    ],
                    "include_segments": [
                      "Subscribed Users"
                    ],
                    "title": "Hello, {{ user.external_id | default: 'there' }}"
                  }
                }
              },
              "schema": {
                "additionalProperties": true,
                "properties": {
                  "body": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Body rendered against a sampled matching device.",
                    "title": "Body"
                  },
                  "delivery_policy": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "integer"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Optional stricter frequency and pacing policy.",
                    "title": "Delivery Policy"
                  },
                  "exclude_segments": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Segment names to exclude.",
                    "title": "Exclude Segments"
                  },
                  "filters": {
                    "anyOf": [
                      {
                        "items": {
                          "additionalProperties": true,
                          "type": "object"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Inline audience filters, with the same semantics as message create.",
                    "title": "Filters"
                  },
                  "include_segments": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Segment names to include.",
                    "title": "Include Segments"
                  },
                  "target": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Direct audience selector, including bounded recipient ID lists.",
                    "title": "Target"
                  },
                  "title": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Title rendered against a sampled matching device.",
                    "title": "Title"
                  }
                },
                "title": "AudiencePreview",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Audience counts plus the rendered title and body, with any render errors"
          },
          "400": {
            "description": "Malformed segment rules or target"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Preview an audience",
        "tags": [
          "Messages"
        ]
      }
    },
    "/v1/apps/{app_id}/audit": {
      "get": {
        "description": "Who did what on this app, newest first: console actions, REST calls and MCP tool\ncalls (`source=mcp`, `action=<tool name>`). Filter with `source` and `action`; `limit` is capped at\n1000. Network metadata — IP address, user agent, country — is deliberately **not** returned here:\nthis route answers \"what was done\", and the console's own audit view is where a network fact is\nlooked up by someone who can be held to it. The rows name operators, so this read needs a\nfull-scope key, like `/keys`.",
        "operationId": "audit_read_v1_apps__app_id__audit_get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 50,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "source",
            "required": false,
            "schema": {
              "default": "",
              "title": "Source",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "action",
            "required": false,
            "schema": {
              "default": "",
              "title": "Action",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Audit entries, newest first"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "403": {
            "description": "Read-only X-OP-API-Key, or the shared sample app is read from the console only"
          },
          "404": {
            "description": "Unknown app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Read the app's audit log",
        "tags": [
          "Apps, keys & settings"
        ]
      }
    },
    "/v1/apps/{app_id}/data/connections": {
      "get": {
        "operationId": "api_list_v1_apps__app_id__data_connections_get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "List data connections",
        "tags": [
          "Data connections"
        ]
      },
      "post": {
        "operationId": "api_create_v1_apps__app_id__data_connections_post",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "additionalProperties": true,
                "title": "Body",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Create a data connection",
        "tags": [
          "Data connections"
        ]
      }
    },
    "/v1/apps/{app_id}/data/connections/{cid}": {
      "get": {
        "operationId": "api_report_v1_apps__app_id__data_connections__cid__get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "cid",
            "required": true,
            "schema": {
              "title": "Cid",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "days",
            "required": false,
            "schema": {
              "default": 7,
              "title": "Days",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "offset",
            "required": false,
            "schema": {
              "default": 0,
              "title": "Offset",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Read data connection delivery report",
        "tags": [
          "Data connections"
        ]
      },
      "put": {
        "operationId": "api_update_v1_apps__app_id__data_connections__cid__put",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "cid",
            "required": true,
            "schema": {
              "title": "Cid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "additionalProperties": true,
                "title": "Body",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Update a data connection",
        "tags": [
          "Data connections"
        ]
      }
    },
    "/v1/apps/{app_id}/data/connections/{cid}/actions/{action}": {
      "post": {
        "operationId": "api_action_v1_apps__app_id__data_connections__cid__actions__action__post",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "cid",
            "required": true,
            "schema": {
              "title": "Cid",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "action",
            "required": true,
            "schema": {
              "title": "Action",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {}
                }
              },
              "schema": {
                "additionalProperties": true,
                "description": "No request fields.",
                "properties": {},
                "title": "EmptyBody",
                "type": "object"
              }
            }
          },
          "required": false
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Activate, pause, retry or delete a connection",
        "tags": [
          "Data connections"
        ]
      }
    },
    "/v1/apps/{app_id}/data/connections/{cid}/test": {
      "post": {
        "operationId": "api_test_v1_apps__app_id__data_connections__cid__test_post",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "cid",
            "required": true,
            "schema": {
              "title": "Cid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "additionalProperties": true,
                "default": {},
                "title": "Body",
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Test a saved connection",
        "tags": [
          "Data connections"
        ]
      }
    },
    "/v1/apps/{app_id}/data/sources/{cid}/events": {
      "post": {
        "operationId": "source_events_v1_apps__app_id__data_sources__cid__events_post",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "cid",
            "required": true,
            "schema": {
              "title": "Cid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "anyOf": [
                  {
                    "additionalProperties": true,
                    "type": "object"
                  },
                  {
                    "items": {},
                    "type": "array"
                  }
                ],
                "title": "Body"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "DataSourceKey": []
          }
        ],
        "summary": "Receive Amplitude or custom integration events",
        "tags": [
          "Data connections"
        ]
      }
    },
    "/v1/apps/{app_id}/dynamic-content": {
      "get": {
        "description": "The app's lookup tables by name and size, without expanding their data\ngrids, alongside the per-app storage quota and how much of it is used.",
        "operationId": "list_dynamic_content_v1_apps__app_id__dynamic_content_get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Table summaries with the app's quota and usage"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "List dynamic content tables",
        "tags": [
          "Templates & dynamic content"
        ]
      }
    },
    "/v1/apps/{app_id}/dynamic-content/{name}": {
      "delete": {
        "description": "Deletes one lookup table. Messages and templates that still reference it\nby name are not rewritten — they will fail validation the next time they are saved or\nsent.",
        "operationId": "delete_dynamic_content_v1_apps__app_id__dynamic_content__name__delete",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "name",
            "required": true,
            "schema": {
              "title": "Name",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "The name of the deleted table"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "403": {
            "description": "Read-only X-OP-API-Key"
          },
          "404": {
            "description": "Unknown dynamic-content table"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Delete a dynamic content table",
        "tags": [
          "Templates & dynamic content"
        ]
      },
      "get": {
        "description": "One lookup table with its full data grid expanded — the row keys and the\ncolumn values Liquid resolves against at send time.",
        "operationId": "get_dynamic_content_v1_apps__app_id__dynamic_content__name__get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "name",
            "required": true,
            "schema": {
              "title": "Name",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "The table row with its data grid"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "404": {
            "description": "Unknown dynamic-content table"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Read a dynamic content table",
        "tags": [
          "Templates & dynamic content"
        ]
      },
      "put": {
        "description": "Writes a whole lookup table under `name`, replacing any table already\nthere — this is a replace, not a merge. The body is either `{\"data\": {...}}` or the grid\nitself: an object of row key → object of columns, where every row must carry the same\ncolumn names as the first.\n\n**One table may not exceed 200 KB, and one app's tables may not exceed 2 MB in total**;\neither ceiling is a `413`.",
        "operationId": "put_dynamic_content_v1_apps__app_id__dynamic_content__name__put",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "name",
            "required": true,
            "schema": {
              "title": "Name",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "data": {
                      "returning": {
                        "reward": 25,
                        "title": "Welcome back"
                      },
                      "starter": {
                        "reward": 100,
                        "title": "Welcome"
                      }
                    }
                  }
                }
              },
              "schema": {
                "additionalProperties": true,
                "properties": {
                  "data": {
                    "additionalProperties": {
                      "additionalProperties": true,
                      "type": "object"
                    },
                    "description": "Row key to a consistent object of column values.",
                    "title": "Data",
                    "type": "object"
                  }
                },
                "required": [
                  "data"
                ],
                "title": "DynamicContentPut",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "The stored table with its size"
          },
          "400": {
            "description": "Malformed grid — empty data, duplicate row keys, or mismatched columns"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "403": {
            "description": "Read-only X-OP-API-Key"
          },
          "413": {
            "description": "Table exceeds 200 KB, or the app exceeds its 2 MB dynamic-content quota"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Create or replace a dynamic content table",
        "tags": [
          "Templates & dynamic content"
        ]
      }
    },
    "/v1/apps/{app_id}/dynamic-content/{name}/csv": {
      "get": {
        "description": "Streams one lookup table back as a CSV attachment — the same round trip\nthe import route reads. Cells are escaped against spreadsheet formula injection, so a value\nbeginning with `=`, `+`, `-` or `@` comes back with a leading apostrophe.",
        "operationId": "export_dynamic_content_csv_v1_apps__app_id__dynamic_content__name__csv_get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "name",
            "required": true,
            "schema": {
              "title": "Name",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "A CSV attachment of the table"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "404": {
            "description": "Unknown dynamic-content table"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Export a dynamic content table as CSV",
        "tags": [
          "Templates & dynamic content"
        ]
      },
      "post": {
        "description": "Replaces the table under `name` from an uploaded CSV, sent as a multipart\nfield called `file`. The header row is a key column followed by one or more value columns;\nduplicate column names, duplicate row keys and empty keys are all refused with the line\nnumber.\n\n**The CSV may not exceed 200 KB**, and the app's 2 MB dynamic-content quota still applies;\neither is a `413`.",
        "operationId": "import_dynamic_content_csv_v1_apps__app_id__dynamic_content__name__csv_post",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "name",
            "required": true,
            "schema": {
              "title": "Name",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "file": {
                    "description": "CSV lookup table with a key column followed by one or more value columns.",
                    "format": "binary",
                    "type": "string"
                  }
                },
                "required": [
                  "file"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "The stored table with its size"
          },
          "400": {
            "description": "Missing file field, undecodable bytes, or a malformed CSV"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "403": {
            "description": "Read-only X-OP-API-Key"
          },
          "413": {
            "description": "CSV exceeds 200 KB, or the app exceeds its 2 MB dynamic-content quota"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Import a dynamic content table from CSV",
        "tags": [
          "Templates & dynamic content"
        ]
      }
    },
    "/v1/apps/{app_id}/events": {
      "get": {
        "description": "The most recent custom events your apps sent, newest first, with their\nproperties parsed and the user's external id resolved. `limit` is capped at 1000, `offset` pages\nback through them, and `total` is the count for the whole app, not for this page.",
        "operationId": "events_recent_v1_apps__app_id__events_get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 100,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "offset",
            "required": false,
            "schema": {
              "default": 0,
              "title": "Offset",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Recent events and the app's total count"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "403": {
            "description": "The shared sample app is read from the console only"
          },
          "404": {
            "description": "Unknown app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "List recent custom events",
        "tags": [
          "Events & ingest"
        ]
      },
      "post": {
        "description": "Accepts up to **50 custom events per request** with per-item partial\nacceptance: valid items are recorded and the rest come back counted in `dropped_reasons`\nrather than failing the whole batch. There are no standard event names — every event is\nwhatever your app calls it.\n\nEach event may carry `idempotency_key`; retrying the same event returns the stored event\nwith `duplicate: true`, while reusing the key for different content is reported as a\nper-item `idempotency-conflict` drop. Authenticate with either an SDK key or a writable\nREST key; send only one credential header.\n\n**Rate limit: 500 events per app per 5 seconds.** Over that the whole request is refused\nwith `429` and a `Retry-After: 5` header, and nothing in it is stored.",
        "operationId": "custom_events_v1_apps__app_id__events_post",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "events": [
                      {
                        "external_id": "player-42",
                        "name": "level_completed",
                        "properties": {
                          "level": 8,
                          "score": 1200
                        }
                      }
                    ]
                  }
                }
              },
              "schema": {
                "additionalProperties": true,
                "properties": {
                  "events": {
                    "description": "Up to 50 custom events.",
                    "items": {
                      "additionalProperties": true,
                      "properties": {
                        "external_id": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "User that produced the event; supply this or subscription_id.",
                          "title": "External Id"
                        },
                        "idempotency_key": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "Optional per-event retry key, 1–200 characters. Reuse with changed content is dropped as idempotency-conflict.",
                          "title": "Idempotency Key"
                        },
                        "name": {
                          "description": "Event name, 1–128 allowed characters.",
                          "title": "Name",
                          "type": "string"
                        },
                        "properties": {
                          "additionalProperties": true,
                          "description": "Free-form JSON properties, up to 2048 encoded bytes.",
                          "title": "Properties",
                          "type": "object"
                        },
                        "subscription_id": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "Subscription that produced the event; supply this or external_id.",
                          "title": "Subscription Id"
                        },
                        "timestamp": {
                          "anyOf": [
                            {
                              "type": "number"
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "Unix seconds; defaults to now.",
                          "title": "Timestamp"
                        }
                      },
                      "required": [
                        "name"
                      ],
                      "title": "CustomEvent",
                      "type": "object"
                    },
                    "title": "Events",
                    "type": "array"
                  }
                },
                "required": [
                  "events"
                ],
                "title": "EventBatch",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Counts of accepted and dropped events, with per-reason drops"
          },
          "400": {
            "description": "Body is not JSON, events is not an array, or more than 50 items"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app SDK/REST key"
          },
          "403": {
            "description": "Read-only REST key"
          },
          "404": {
            "description": "Unknown app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          },
          "429": {
            "description": "Rate limited — 500 events per app per 5 seconds; retry after 5s"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Record custom events",
        "tags": [
          "Events & ingest"
        ]
      }
    },
    "/v1/apps/{app_id}/events/catalogue": {
      "get": {
        "description": "The distinct event names seen in the last `days` (default 30, max 400) with a\ncount and a last-seen for each — the names a segment or a journey trigger can actually use, since\nOpenPush has no standard event vocabulary.",
        "operationId": "events_catalogue_v1_apps__app_id__events_catalogue_get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "days",
            "required": false,
            "schema": {
              "default": 30,
              "title": "Days",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Event names with counts and last-seen"
          },
          "400": {
            "description": "Bad window"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "404": {
            "description": "Unknown app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "List the custom event catalogue",
        "tags": [
          "Events & ingest"
        ]
      }
    },
    "/v1/apps/{app_id}/export.ndjson": {
      "get": {
        "description": "The whole app as newline-delimited JSON — settings, segments, templates,\ndynamic content, users, subscriptions, in-app messages and their engagement, messages,\ntest devices, imports and deliveries — one object per line, in REST field names, streamed\nrather than buffered. Free, on every tier, at any time.\n\nBy default the stream holds one transaction open so every entity in the file is the same\ninstant; the last line is a terminal record carrying per-entity counts, and the importer\nrefuses a file without it, because a truncated stream otherwise looks exactly like a\ncomplete one.\n\n**What is not in it:** journeys and journey history, custom events, and the daily usage\nrollups have no export entity. Nor do secrets and routing state — API keys, platform\ncredentials, device credentials, Live Activity and push-to-start tokens, and media\nmetadata are all deliberately withheld and named in the manifest.",
        "operationId": "export_ndjson_v1_apps__app_id__export_ndjson_get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "A streamed NDJSON attachment ending in a terminal count record"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "403": {
            "description": "Read-only X-OP-API-Key"
          },
          "404": {
            "description": "Unknown app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Export the app as NDJSON",
        "tags": [
          "Import & export"
        ]
      }
    },
    "/v1/apps/{app_id}/export/{entity}.csv": {
      "get": {
        "description": "One entity of the export rendered as CSV and streamed as an attachment.\nMost entities contain the same records as the NDJSON archive. `subscriptions` joins every\ndevice to all portable fields on its user profile, because a standalone CSV cannot express\nthe archive's two related streams. `test_subscriptions` adds the test-device name and timestamp;\nimporting it restores the subscription, user profile and named test-device marker. An\nunrecognised entity is a `404` that names the full list.\n\n**Every cell, including the header row, is escaped against spreadsheet formula injection:**\na value beginning with `=`, `+`, `-`, `@`, a tab or a carriage return comes back with a\nleading apostrophe. The CSV import route strips that back off; if you parse these files\nyourself, strip it too.",
        "operationId": "export_entity_csv_v1_apps__app_id__export__entity__csv_get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "entity",
            "required": true,
            "schema": {
              "title": "Entity",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "A streamed CSV attachment for one entity"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "404": {
            "description": "Unknown app, or an unrecognised entity name"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Export one entity as CSV",
        "tags": [
          "Import & export"
        ]
      }
    },
    "/v1/apps/{app_id}/iams/{iam_id}/html": {
      "get": {
        "description": "The self-contained HTML document for one in-app message, with Liquid\nalready resolved against the given device, a narrow native bridge, safe-area-aware\nplacement and carousel page-change events.\n\n`subscription_id` is required as a query parameter — the document is personalised, so there\nis no device-less rendering of it.",
        "operationId": "iam_html_v1_apps__app_id__iams__iam_id__html_get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "iam_id",
            "required": true,
            "schema": {
              "title": "Iam Id",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "subscription_id",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Subscription Id"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "A self-contained HTML document"
          },
          "400": {
            "description": "subscription_id query parameter is required"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-SDK-Key"
          },
          "404": {
            "description": "Unknown app, unknown subscription, or unknown in-app message"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "SdkKey": []
          }
        ],
        "summary": "Fetch compiled in-app message HTML",
        "tags": [
          "In-app messages"
        ]
      }
    },
    "/v1/apps/{app_id}/import": {
      "post": {
        "description": "Imports subscriptions from a CSV uploaded as a multipart `file` field.\nUnlike the NDJSON restore this is an **upsert on the push token**, so it can be run against\nan app that already has data.\n\nSmall files are processed inline and answer `200` with the summary. Anything larger is\nspooled and handed to the job queue, answering `202` with an `import_id` to poll on\n`GET /v1/apps/{app_id}/imports/{import_id}`. Uploads over the server's CSV size ceiling are\nrefused with `413` and the spool file is removed.",
        "operationId": "import_subscriptions_v1_apps__app_id__import_post",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/Body_import_subscriptions_v1_apps__app_id__import_post",
                "properties": {
                  "file": {
                    "description": "CSV subscription export to upsert by push token.",
                    "format": "binary",
                    "type": "string"
                  }
                },
                "required": [
                  "file"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "The import summary, or a 202 with an import_id to poll"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "403": {
            "description": "Read-only X-OP-API-Key"
          },
          "404": {
            "description": "Unknown app"
          },
          "413": {
            "description": "The CSV exceeds the server's import size limit"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Import subscriptions from CSV",
        "tags": [
          "Import & export"
        ]
      }
    },
    "/v1/apps/{app_id}/import.ndjson": {
      "post": {
        "description": "Reads an OpenPush NDJSON archive back in, uploaded as a multipart `file`\nfield. **This is a restore into an EMPTY app, not a merge** — a target that already has\nsubscriptions is refused with `409`, which says how many it found. (`409` rather than `400`\non purpose: the file is fine, the target is wrong.)\n\nRows commit in batches as they are read, so a refusal partway through leaves the rows\nalready written in place and says how many. There is deliberately no cleanup sweep — the\nempty-app precondition is what makes the remedy trivial: delete the app, make a new one,\nre-run the import.",
        "operationId": "import_ndjson_route_v1_apps__app_id__import_ndjson_post",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/Body_import_ndjson_route_v1_apps__app_id__import_ndjson_post",
                "properties": {
                  "file": {
                    "description": "OpenPush NDJSON archive to restore into an empty app.",
                    "format": "binary",
                    "type": "string"
                  }
                },
                "required": [
                  "file"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Per-entity counts of the rows restored"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "403": {
            "description": "Read-only X-OP-API-Key"
          },
          "404": {
            "description": "Unknown app"
          },
          "409": {
            "description": "The target app is not empty, or the archive is missing its terminal record"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Restore an NDJSON export",
        "tags": [
          "Import & export"
        ]
      }
    },
    "/v1/apps/{app_id}/imports": {
      "get": {
        "description": "The **25 most recent** import jobs for one app, newest first, with row and\nbyte progress, status, summary and any error. Older jobs are not reachable through this\nroute.",
        "operationId": "list_imports_v1_apps__app_id__imports_get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "The 25 most recent import jobs"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "List import jobs",
        "tags": [
          "Import & export"
        ]
      }
    },
    "/v1/apps/{app_id}/imports/{import_id}": {
      "get": {
        "description": "Progress for one import job — status, rows done against rows total, the\nsummary, and the error if it failed. This is the route to poll after a `202` from the CSV\nimport.",
        "operationId": "import_status_api_v1_apps__app_id__imports__import_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "import_id",
            "required": true,
            "schema": {
              "title": "Import Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Status and progress for one import job"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "404": {
            "description": "No such import for this app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Read import job status",
        "tags": [
          "Import & export"
        ]
      }
    },
    "/v1/apps/{app_id}/in-app-messages": {
      "get": {
        "description": "In-app message definitions for one app with per-tab counts and a total.\n`status` filters by lifecycle tab; omit it for all. The page is capped at 100 rows.",
        "operationId": "list_in_app_messages_v1_apps__app_id__in_app_messages_get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "title": "Status",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Definitions, per-status counts and the total"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "404": {
            "description": "Unknown app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "List in-app messages",
        "tags": [
          "In-app messages"
        ]
      },
      "post": {
        "description": "Creates an in-app message definition — layout, blocks, triggers, audience,\ndismissal, scheduling, frequency, and optional Liquid fields. It is created as a **draft**\nunless the body sets `live: true`, in which case it is taken live in the same call.",
        "operationId": "create_in_app_message_v1_apps__app_id__in_app_messages_post",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "blocks": {
                      "cards": [
                        {
                          "blocks": [
                            {
                              "kind": "text",
                              "text": "Welcome!"
                            }
                          ]
                        }
                      ]
                    },
                    "editor": "blocks",
                    "frequency": "once",
                    "layout": "center",
                    "name": "Welcome card",
                    "triggers": [
                      {
                        "kind": "session_count",
                        "operator": "greater",
                        "value": 0
                      }
                    ]
                  }
                }
              },
              "schema": {
                "additionalProperties": true,
                "properties": {
                  "blocks": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Structured cards and blocks for the block editor.",
                    "title": "Blocks"
                  },
                  "dismiss_mode": {
                    "default": "until_dismissed",
                    "description": "How the message closes.",
                    "enum": [
                      "until_dismissed",
                      "after_time"
                    ],
                    "title": "Dismiss Mode",
                    "type": "string"
                  },
                  "display_duration": {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Seconds before auto-dismissal.",
                    "title": "Display Duration"
                  },
                  "editor": {
                    "default": "blocks",
                    "description": "Structured blocks or raw HTML editor.",
                    "enum": [
                      "blocks",
                      "html"
                    ],
                    "title": "Editor",
                    "type": "string"
                  },
                  "end_at": {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Optional Unix end time.",
                    "title": "End At"
                  },
                  "exclude_segments": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Excluded segment names.",
                    "title": "Exclude Segments"
                  },
                  "frequency": {
                    "default": "once",
                    "description": "Redisplay policy.",
                    "enum": [
                      "once",
                      "every_trigger",
                      "multiple"
                    ],
                    "title": "Frequency",
                    "type": "string"
                  },
                  "html_source": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "HTML source, up to 256 KB, when editor is html.",
                    "title": "Html Source"
                  },
                  "include_segments": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Included segment names when target is segments.",
                    "title": "Include Segments"
                  },
                  "layout": {
                    "default": "center",
                    "description": "Supported in-app layout.",
                    "title": "Layout",
                    "type": "string"
                  },
                  "live": {
                    "default": false,
                    "description": "Create and immediately take the message live.",
                    "title": "Live",
                    "type": "boolean"
                  },
                  "name": {
                    "description": "Message name shown in the console and reports.",
                    "title": "Name",
                    "type": "string"
                  },
                  "redisplay_gap_s": {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Minimum seconds between redisplays.",
                    "title": "Redisplay Gap S"
                  },
                  "redisplay_limit": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Maximum displays when frequency is multiple.",
                    "title": "Redisplay Limit"
                  },
                  "start_at": {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Optional Unix start time.",
                    "title": "Start At"
                  },
                  "target": {
                    "default": "all",
                    "description": "Audience selection mode.",
                    "enum": [
                      "all",
                      "segments"
                    ],
                    "title": "Target",
                    "type": "string"
                  },
                  "triggers": {
                    "description": "Rules that make the message eligible to show.",
                    "items": {
                      "additionalProperties": true,
                      "type": "object"
                    },
                    "title": "Triggers",
                    "type": "array"
                  }
                },
                "required": [
                  "name"
                ],
                "title": "InAppMessageCreate",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "The new definition's id and lifecycle status"
          },
          "400": {
            "description": "The definition was rejected — the message names the field"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "403": {
            "description": "Read-only X-OP-API-Key"
          },
          "404": {
            "description": "Unknown app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Create an in-app message",
        "tags": [
          "In-app messages"
        ]
      }
    },
    "/v1/apps/{app_id}/in-app-messages/{iam_id}": {
      "delete": {
        "description": "Deletes an in-app message definition. **Drafts only** — a definition that\nhas been live is archived rather than deleted, and asking to delete one is a `409`.",
        "operationId": "delete_in_app_message_v1_apps__app_id__in_app_messages__iam_id__delete",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "iam_id",
            "required": true,
            "schema": {
              "title": "Iam Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Confirmation that the definition was deleted"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "403": {
            "description": "Read-only X-OP-API-Key"
          },
          "409": {
            "description": "Unknown message, or it is not a draft and cannot be deleted"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Delete an in-app message",
        "tags": [
          "In-app messages"
        ]
      },
      "get": {
        "description": "One in-app message definition together with its report summary —\nimpressions, clicks and the per-block engagement recorded from device receipts.",
        "operationId": "get_in_app_message_v1_apps__app_id__in_app_messages__iam_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "iam_id",
            "required": true,
            "schema": {
              "title": "Iam Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "The definition and its report summary"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "404": {
            "description": "Unknown in-app message for this app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Read an in-app message report",
        "tags": [
          "In-app messages"
        ]
      },
      "patch": {
        "description": "Updates an in-app message definition. **Only drafts are editable** —\nlifecycle changes are explicit actions on the action route, never a field in this patch.",
        "operationId": "update_in_app_message_v1_apps__app_id__in_app_messages__iam_id__patch",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "iam_id",
            "required": true,
            "schema": {
              "title": "Iam Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "frequency": "every_trigger",
                    "name": "Welcome card — revised"
                  }
                }
              },
              "schema": {
                "additionalProperties": true,
                "properties": {
                  "blocks": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Structured cards and blocks for the block editor.",
                    "title": "Blocks"
                  },
                  "dismiss_mode": {
                    "default": "until_dismissed",
                    "description": "How the message closes.",
                    "enum": [
                      "until_dismissed",
                      "after_time"
                    ],
                    "title": "Dismiss Mode",
                    "type": "string"
                  },
                  "display_duration": {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Seconds before auto-dismissal.",
                    "title": "Display Duration"
                  },
                  "editor": {
                    "default": "blocks",
                    "description": "Structured blocks or raw HTML editor.",
                    "enum": [
                      "blocks",
                      "html"
                    ],
                    "title": "Editor",
                    "type": "string"
                  },
                  "end_at": {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Optional Unix end time.",
                    "title": "End At"
                  },
                  "exclude_segments": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Excluded segment names.",
                    "title": "Exclude Segments"
                  },
                  "frequency": {
                    "default": "once",
                    "description": "Redisplay policy.",
                    "enum": [
                      "once",
                      "every_trigger",
                      "multiple"
                    ],
                    "title": "Frequency",
                    "type": "string"
                  },
                  "html_source": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "HTML source, up to 256 KB, when editor is html.",
                    "title": "Html Source"
                  },
                  "include_segments": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Included segment names when target is segments.",
                    "title": "Include Segments"
                  },
                  "layout": {
                    "default": "center",
                    "description": "Supported in-app layout.",
                    "title": "Layout",
                    "type": "string"
                  },
                  "live": {
                    "default": false,
                    "description": "Create and immediately take the message live.",
                    "title": "Live",
                    "type": "boolean"
                  },
                  "name": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Replacement message name.",
                    "title": "Name"
                  },
                  "redisplay_gap_s": {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Minimum seconds between redisplays.",
                    "title": "Redisplay Gap S"
                  },
                  "redisplay_limit": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Maximum displays when frequency is multiple.",
                    "title": "Redisplay Limit"
                  },
                  "start_at": {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Optional Unix start time.",
                    "title": "Start At"
                  },
                  "target": {
                    "default": "all",
                    "description": "Audience selection mode.",
                    "enum": [
                      "all",
                      "segments"
                    ],
                    "title": "Target",
                    "type": "string"
                  },
                  "triggers": {
                    "description": "Rules that make the message eligible to show.",
                    "items": {
                      "additionalProperties": true,
                      "type": "object"
                    },
                    "title": "Triggers",
                    "type": "array"
                  }
                },
                "title": "InAppMessagePatch",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "The updated definition"
          },
          "400": {
            "description": "Unknown message, or a definition change that was rejected"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "403": {
            "description": "Read-only X-OP-API-Key"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Update an in-app message",
        "tags": [
          "In-app messages"
        ]
      }
    },
    "/v1/apps/{app_id}/in-app-messages/{iam_id}/{action}": {
      "post": {
        "description": "Moves an in-app message along its lifecycle. `action` is exactly one of\n**`set-live`, `pause`, `resume`, `end`, `archive` or `restore`** — those six values and\nnothing else; anything else is `404 unknown in-app action`.\n\nDuplicating a definition and sending a test exist in the product but are **console-only**,\nso `POST …/duplicate` and `POST …/test` are `404`s here. A transition the message's current\nstatus does not allow is a `409`.",
        "operationId": "lifecycle_in_app_message_v1_apps__app_id__in_app_messages__iam_id___action__post",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "iam_id",
            "required": true,
            "schema": {
              "title": "Iam Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "action",
            "required": true,
            "schema": {
              "title": "Action",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {}
                }
              },
              "schema": {
                "additionalProperties": true,
                "description": "No request fields.",
                "properties": {},
                "title": "EmptyBody",
                "type": "object"
              }
            }
          },
          "required": false
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "The message id and its new lifecycle status"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "403": {
            "description": "Read-only X-OP-API-Key"
          },
          "404": {
            "description": "Unknown in-app action"
          },
          "409": {
            "description": "Unknown message, or a transition its current status does not allow"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Run an in-app lifecycle action",
        "tags": [
          "In-app messages"
        ]
      }
    },
    "/v1/apps/{app_id}/journeys": {
      "get": {
        "description": "Journey summaries for one app, newest ids last. Filter with `state`, page\nwith `cursor` (a keyset walk on the primary key); `limit` is capped at 1000. Errors on this\nroute are returned as a `{\"errors\": [...]}` envelope with a machine-readable `code`.",
        "operationId": "list_journeys_v1_apps__app_id__journeys_get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "state",
            "required": false,
            "schema": {
              "default": "",
              "title": "State",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 50,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "default": "",
              "title": "Cursor",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Journey summaries, has_more, and a next_cursor when there is one"
          },
          "400": {
            "description": "Unknown journey state, or an invalid cursor"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "404": {
            "description": "Unknown app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "List journeys",
        "tags": [
          "Journeys"
        ]
      },
      "post": {
        "description": "Creates a journey in the draft state. Only `name`, `description` and the\n    definition fields (`audience`, `nodes`, `early_exit`, `reentry_rules`, `schedule`, `goal`,\n`objective`, `personalization`)\nare accepted — any other key, including a server-controlled one, is refused and named back\nto you. Node ids are assigned by the server; supplying your own is an error.\n\nA draft may still have gaps a live journey could not have, so validation here is the draft\nruleset, not the start-up one. Errors use the `{\"errors\": [...]}` envelope.",
        "operationId": "create_journey_v1_apps__app_id__journeys_post",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "audience": {
                      "kind": "segment",
                      "segments": [
                        "Subscribed Users"
                      ]
                    },
                    "name": "New player welcome",
                    "nodes": [
                      {
                        "duration": 3600,
                        "kind": "wait"
                      },
                      {
                        "kind": "message",
                        "template": "Welcome"
                      }
                    ]
                  }
                }
              },
              "schema": {
                "additionalProperties": true,
                "properties": {
                  "audience": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Journey entry audience definition.",
                    "title": "Audience"
                  },
                  "description": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Operator-facing description.",
                    "title": "Description"
                  },
                  "early_exit": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Rules that remove a user before the journey ends.",
                    "title": "Early Exit"
                  },
                  "goal": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Conversion goal.",
                    "title": "Goal"
                  },
                  "name": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Journey display name.",
                    "title": "Name"
                  },
                  "nodes": {
                    "description": "Journey graph nodes; ids are assigned by the server.",
                    "items": {
                      "additionalProperties": true,
                      "type": "object"
                    },
                    "title": "Nodes",
                    "type": "array"
                  },
                  "objective": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Versioned correlated success event for read-only personal decisions. Separate from aggregate goal metrics.",
                    "title": "Objective"
                  },
                  "personalization": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Bounded personal decision settings and optional experiment configuration.",
                    "title": "Personalization"
                  },
                  "reentry_rules": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Whether and when a user may enter again.",
                    "title": "Reentry Rules"
                  },
                  "schedule": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Start/end schedule.",
                    "title": "Schedule"
                  }
                },
                "title": "JourneyCreate",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "The created journey, including the concurrency_key needed to update it"
          },
          "400": {
            "description": "Body is not a JSON object, unknown fields, or a journey that fails draft validation"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "403": {
            "description": "Read-only X-OP-API-Key"
          },
          "404": {
            "description": "Unknown app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Create a journey",
        "tags": [
          "Journeys"
        ]
      }
    },
    "/v1/apps/{app_id}/journeys-personal-settings": {
      "get": {
        "operationId": "personal_settings_v1_apps__app_id__journeys_personal_settings_get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Read personal journey settings",
        "tags": [
          "Journeys"
        ]
      },
      "patch": {
        "operationId": "update_personal_settings_v1_apps__app_id__journeys_personal_settings_patch",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "ai_enabled": false,
                    "enabled": false
                  }
                }
              },
              "schema": {
                "properties": {
                  "ai_enabled": {
                    "anyOf": [
                      {
                        "type": "boolean"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Allow runtime model calls using workspace provider configuration.",
                    "title": "Ai Enabled"
                  },
                  "config": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "anyOf": [
                            {
                              "type": "number"
                            },
                            {
                              "type": "integer"
                            }
                          ]
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Bounded hourly_calls, daily_tokens, concurrency, deadline_seconds, daily_cost_limit, estimated_usd_per_million_tokens and history_days overrides.",
                    "title": "Config"
                  },
                  "enabled": {
                    "anyOf": [
                      {
                        "type": "boolean"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Enable or park personal journeys; disabling cancels unsent actions.",
                    "title": "Enabled"
                  },
                  "shadow_reviewed": {
                    "anyOf": [
                      {
                        "type": "boolean"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Acknowledge review of shadow decisions before controlled live AI.",
                    "title": "Shadow Reviewed"
                  }
                },
                "title": "PersonalJourneySettings",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "400": {
            "description": "Invalid flag or bounded runtime limit"
          },
          "403": {
            "description": "Read-only key or unscoped shared sample access refused"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Update personal journey settings",
        "tags": [
          "Journeys"
        ]
      }
    },
    "/v1/apps/{app_id}/journeys/{journey_id}": {
      "delete": {
        "description": "Deletes a journey. Whether a journey in a given state may be deleted is\ndecided by the journey engine; a refusal comes back in the `{\"errors\": [...]}` envelope\nwith `400`.",
        "operationId": "delete_journey_v1_apps__app_id__journeys__journey_id__delete",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "journey_id",
            "required": true,
            "schema": {
              "title": "Journey Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Confirmation that the journey was deleted"
          },
          "400": {
            "description": "This journey may not be deleted in its current state"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "403": {
            "description": "Read-only X-OP-API-Key"
          },
          "404": {
            "description": "Unknown journey for this app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Delete a journey",
        "tags": [
          "Journeys"
        ]
      },
      "get": {
        "description": "The full journey definition — audience, nodes, schedule, goal, exit and\nreentry rules. The response carries a `concurrency_key`; `PATCH` requires it, so read\nbefore you write.",
        "operationId": "get_journey_v1_apps__app_id__journeys__journey_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "journey_id",
            "required": true,
            "schema": {
              "title": "Journey Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "The journey definition and its current concurrency_key"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "404": {
            "description": "Unknown journey for this app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Retrieve a journey",
        "tags": [
          "Journeys"
        ]
      },
      "patch": {
        "description": "A merge patch over the journey definition: keys you send replace what is\nthere, and an explicit `null` removes a key. `state` moves the journey along its allowed\ntransitions.\n\n**A matching `concurrency_key` is required in the body.** If the journey changed since you\nread it the patch is refused with `409` and nothing is written — refresh and retry.",
        "operationId": "patch_journey_v1_apps__app_id__journeys__journey_id__patch",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "journey_id",
            "required": true,
            "schema": {
              "title": "Journey Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "concurrency_key": "journey-version-key",
                    "description": "Updated after launch review"
                  }
                }
              },
              "schema": {
                "additionalProperties": true,
                "properties": {
                  "audience": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Journey entry audience definition.",
                    "title": "Audience"
                  },
                  "concurrency_key": {
                    "description": "Value from the latest journey read; prevents lost updates.",
                    "title": "Concurrency Key",
                    "type": "string"
                  },
                  "description": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Operator-facing description.",
                    "title": "Description"
                  },
                  "early_exit": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Rules that remove a user before the journey ends.",
                    "title": "Early Exit"
                  },
                  "goal": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Conversion goal.",
                    "title": "Goal"
                  },
                  "name": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Journey display name.",
                    "title": "Name"
                  },
                  "nodes": {
                    "description": "Journey graph nodes; ids are assigned by the server.",
                    "items": {
                      "additionalProperties": true,
                      "type": "object"
                    },
                    "title": "Nodes",
                    "type": "array"
                  },
                  "objective": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Versioned correlated success event for read-only personal decisions. Separate from aggregate goal metrics.",
                    "title": "Objective"
                  },
                  "personalization": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Bounded personal decision settings and optional experiment configuration.",
                    "title": "Personalization"
                  },
                  "reentry_rules": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Whether and when a user may enter again.",
                    "title": "Reentry Rules"
                  },
                  "schedule": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Start/end schedule.",
                    "title": "Schedule"
                  },
                  "state": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Requested lifecycle transition.",
                    "title": "State"
                  }
                },
                "required": [
                  "concurrency_key"
                ],
                "title": "JourneyPatch",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "The updated journey definition"
          },
          "400": {
            "description": "Body is not a JSON object, unknown fields, or a definition that fails validation"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "403": {
            "description": "Read-only X-OP-API-Key"
          },
          "404": {
            "description": "Unknown journey for this app"
          },
          "409": {
            "description": "Missing or stale concurrency_key — the journey changed since it was read"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Update a journey",
        "tags": [
          "Journeys"
        ]
      }
    },
    "/v1/apps/{app_id}/journeys/{journey_id}/nodes/{node_id}": {
      "patch": {
        "description": "A merge patch over one node of a journey. A node's `id` and `kind` are\nimmutable — sending either is an error. The whole journey is revalidated after the patch,\nso a node change that would break the journey is refused and nothing is saved.\n\n**A matching `concurrency_key` is required in the body**, exactly as on the journey\npatch.",
        "operationId": "patch_journey_node_v1_apps__app_id__journeys__journey_id__nodes__node_id__patch",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "journey_id",
            "required": true,
            "schema": {
              "title": "Journey Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "node_id",
            "required": true,
            "schema": {
              "title": "Node Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "concurrency_key": "journey-version-key",
                    "config": {
                      "duration": 7200
                    }
                  }
                }
              },
              "schema": {
                "additionalProperties": true,
                "properties": {
                  "concurrency_key": {
                    "description": "Value from the latest journey read.",
                    "title": "Concurrency Key",
                    "type": "string"
                  },
                  "config": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Node-specific settings to merge.",
                    "title": "Config"
                  },
                  "name": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Replacement node label when the node kind supports it.",
                    "title": "Name"
                  },
                  "position": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "number"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Optional editor position metadata.",
                    "title": "Position"
                  }
                },
                "required": [
                  "concurrency_key"
                ],
                "title": "JourneyNodePatch",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "The updated journey definition"
          },
          "400": {
            "description": "Body is not a JSON object, an attempt to change node id or kind, or a definition that fails validation"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "403": {
            "description": "Read-only X-OP-API-Key"
          },
          "404": {
            "description": "Unknown journey or unknown node"
          },
          "409": {
            "description": "Missing or stale concurrency_key"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Update a journey node",
        "tags": [
          "Journeys"
        ]
      }
    },
    "/v1/apps/{app_id}/journeys/{journey_id}/personal-report": {
      "get": {
        "operationId": "personal_report_v1_apps__app_id__journeys__journey_id__personal_report_get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "journey_id",
            "required": true,
            "schema": {
              "title": "Journey Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Read personal journey report",
        "tags": [
          "Journeys"
        ]
      }
    },
    "/v1/apps/{app_id}/journeys/{journey_id}/preview": {
      "post": {
        "description": "Read-only rules evaluation of a saved or unsaved draft. Never enrolls, sends, writes decisions, or calls AI. This is not a delivery promise. Shared sample apps require console owner scope and cannot use this REST route.",
        "operationId": "preview_journey_v1_apps__app_id__journeys__journey_id__preview_post",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "journey_id",
            "required": true,
            "schema": {
              "title": "Journey Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "node_id": "jnode_decision",
                    "subject": {
                      "quest_id": "first-quest"
                    },
                    "user_id": "usr_player"
                  }
                }
              },
              "schema": {
                "additionalProperties": true,
                "properties": {
                  "definition": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Optional unsaved draft definition. Omit to preview the saved revision.",
                    "title": "Definition"
                  },
                  "node_id": {
                    "description": "Personal decision node id (or client_node_id in an unsaved draft).",
                    "title": "Node Id",
                    "type": "string"
                  },
                  "run_id": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Existing run for this journey and user; provides entry subject, time and saved revision.",
                    "title": "Run Id"
                  },
                  "subject": {
                    "additionalProperties": {
                      "type": "string"
                    },
                    "description": "Hypothetical subject, for example {quest_id: first-quest}. Required when no run supplies it.",
                    "title": "Subject",
                    "type": "object"
                  },
                  "user_id": {
                    "description": "Internal user id, scoped to this app and workspace.",
                    "title": "User Id",
                    "type": "string"
                  }
                },
                "required": [
                  "user_id",
                  "node_id"
                ],
                "title": "JourneyPreview",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "400": {
            "description": "Invalid policy, user input, or missing subject"
          },
          "401": {
            "description": "Missing or wrong-app API key"
          },
          "403": {
            "description": "Shared sample app requires a scoped console session"
          },
          "404": {
            "description": "Journey, user, or run not found in scope"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Preview a personal decision for one user",
        "tags": [
          "Journeys"
        ]
      }
    },
    "/v1/apps/{app_id}/journeys/{journey_id}/runs": {
      "get": {
        "operationId": "list_personal_runs_v1_apps__app_id__journeys__journey_id__runs_get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "journey_id",
            "required": true,
            "schema": {
              "title": "Journey Id",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "user_id",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "User Id"
            }
          },
          {
            "in": "query",
            "name": "offset",
            "required": false,
            "schema": {
              "default": 0,
              "title": "Offset",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 20,
              "title": "Limit",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "List personal journey runs",
        "tags": [
          "Journeys"
        ]
      }
    },
    "/v1/apps/{app_id}/journeys/{journey_id}/runs/{run_id}/decisions": {
      "get": {
        "operationId": "list_personal_decisions_v1_apps__app_id__journeys__journey_id__runs__run_id__decisions_get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "journey_id",
            "required": true,
            "schema": {
              "title": "Journey Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "run_id",
            "required": true,
            "schema": {
              "title": "Run Id",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "offset",
            "required": false,
            "schema": {
              "default": 0,
              "title": "Offset",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 20,
              "title": "Limit",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "List personal journey decisions",
        "tags": [
          "Journeys"
        ]
      }
    },
    "/v1/apps/{app_id}/journeys/{journey_id}/stats": {
      "get": {
        "description": "Lifetime totals for one journey — entered, completed, exited early and\nhalted — plus the count of runs currently active, waiting or processing, and a per-node\nevent breakdown. Totals come from the daily rollup, so they are as fresh as the last roll.",
        "operationId": "journey_stats_v1_apps__app_id__journeys__journey_id__stats_get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "journey_id",
            "required": true,
            "schema": {
              "title": "Journey Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Lifetime totals, active run count, and per-node event counts"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "404": {
            "description": "Unknown journey for this app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Read journey statistics",
        "tags": [
          "Journeys"
        ]
      }
    },
    "/v1/apps/{app_id}/keys": {
      "get": {
        "description": "Metadata for every key on one app. Secret values are omitted by default.\n`include_values=true` is a temporary compatibility option through 2026-10-23 UTC;\nafterward it returns 410. New and rotated secret values are returned once by their write calls.\nA disabled or expired key remains in this list but cannot authenticate.\n\nEach row carries a `scope`: `full`, which is what a REST key has always meant, or `read`,\nwhich may read reports, audiences and settings but cannot send, schedule, cancel or change\nanything — including this route, which reveals key values.",
        "operationId": "list_keys_v1_apps__app_id__keys_get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "include_values",
            "required": false,
            "schema": {
              "default": false,
              "title": "Include Values",
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "The app's key rows"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "403": {
            "description": "Read-only X-OP-API-Key"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "List API keys",
        "tags": [
          "Apps, keys & settings"
        ]
      },
      "post": {
        "operationId": "create_key_v1_apps__app_id__keys_post",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "kind": "rest",
                    "name": "backend"
                  }
                }
              },
              "schema": {
                "additionalProperties": true,
                "properties": {
                  "allowed_ips": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Up to 16 network ranges in CIDR notation.",
                    "title": "Allowed Ips"
                  },
                  "kind": {
                    "enum": [
                      "rest",
                      "sdk"
                    ],
                    "title": "Kind",
                    "type": "string"
                  },
                  "name": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Name"
                  },
                  "scope": {
                    "anyOf": [
                      {
                        "enum": [
                          "full",
                          "read"
                        ],
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Scope"
                  }
                },
                "required": [
                  "kind"
                ],
                "title": "KeyCreate",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "403": {
            "description": "Read-only API key or shared sample app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Create Key",
        "tags": [
          "Apps, keys & settings"
        ]
      }
    },
    "/v1/apps/{app_id}/keys/{key_id}": {
      "delete": {
        "operationId": "delete_key_v1_apps__app_id__keys__key_id__delete",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "key_id",
            "required": true,
            "schema": {
              "title": "Key Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "403": {
            "description": "Read-only API key or shared sample app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Delete Key",
        "tags": [
          "Apps, keys & settings"
        ]
      },
      "patch": {
        "operationId": "patch_key_v1_apps__app_id__keys__key_id__patch",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "key_id",
            "required": true,
            "schema": {
              "title": "Key Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "enabled": false
                  }
                }
              },
              "schema": {
                "additionalProperties": true,
                "properties": {
                  "allowed_ips": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Allowed Ips"
                  },
                  "enabled": {
                    "anyOf": [
                      {
                        "type": "boolean"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Enabled"
                  },
                  "name": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Name"
                  },
                  "scope": {
                    "anyOf": [
                      {
                        "enum": [
                          "full",
                          "read"
                        ],
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Scope"
                  }
                },
                "title": "KeyUpdate",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "403": {
            "description": "Read-only API key or shared sample app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Patch Key",
        "tags": [
          "Apps, keys & settings"
        ]
      }
    },
    "/v1/apps/{app_id}/keys/{kind}/rotate": {
      "post": {
        "description": "Create a replacement for a key ID or an active key kind. The new secret is\nreturned once. The previous REST value remains valid for 24 hours; a previous SDK value\nremains valid for seven days. Its expiry is returned as `old_key_expires_at`.\nDisable a specific key early with `PATCH /keys/{key_id}` if rollout is complete.",
        "operationId": "rotate_key_v1_apps__app_id__keys__kind__rotate_post",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "kind",
            "required": true,
            "schema": {
              "title": "Kind",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {}
                }
              },
              "schema": {
                "additionalProperties": true,
                "description": "No request fields.",
                "properties": {},
                "title": "EmptyBody",
                "type": "object"
              }
            }
          },
          "required": false
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "The new key value, shown once, and old-key expiry"
          },
          "400": {
            "description": "kind must be rest, sdk or legacy"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "403": {
            "description": "Read-only X-OP-API-Key"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Rotate an API key",
        "tags": [
          "Apps, keys & settings"
        ]
      }
    },
    "/v1/apps/{app_id}/live-activities": {
      "post": {
        "description": "Registers an ActivityKit update token so the server can push updates to\none Live Activity on one device. A dedicated route rather than an ingest event type,\nbecause a wrong field here means a lock screen that silently never updates — this route\nnames the field that was wrong.\n\nThe device must already be registered: an unknown push token is a `404`. The platform window is\nreported back in the response — **updates are accepted for 8 hours from `started_at`, and\nan end for 4 hours after that**, whatever the server does.",
        "operationId": "live_activity_register_v1_apps__app_id__live_activities_post",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "activity_id": "delivery-1042",
                    "activity_type": "DeliveryAttributes",
                    "token": "device-push-token",
                    "update_token": "a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1"
                  }
                }
              },
              "schema": {
                "additionalProperties": true,
                "properties": {
                  "activity_id": {
                    "description": "Caller identifier for this activity instance.",
                    "title": "Activity Id",
                    "type": "string"
                  },
                  "activity_type": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "ActivityKit attributes type.",
                    "title": "Activity Type"
                  },
                  "stale_at": {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Unix seconds at which the activity content becomes stale.",
                    "title": "Stale At"
                  },
                  "token": {
                    "description": "Device's registered push token.",
                    "title": "Token",
                    "type": "string"
                  },
                  "update_token": {
                    "description": "ActivityKit update token: even-length hexadecimal, 64–512 characters.",
                    "title": "Update Token",
                    "type": "string"
                  }
                },
                "required": [
                  "token",
                  "activity_id",
                  "update_token"
                ],
                "title": "LiveActivityRegister",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "The stored activity row, its start time, and the active window"
          },
          "400": {
            "description": "activity_id missing, update_token not a hex APNs token, or an unusable stale_at"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-SDK-Key"
          },
          "403": {
            "description": "That activity id already belongs to another device (shared sample app only)"
          },
          "404": {
            "description": "Unknown device token for this app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "SdkKey": []
          }
        ],
        "summary": "Register a Live Activity update token",
        "tags": [
          "Live Activities"
        ]
      }
    },
    "/v1/apps/{app_id}/live-activities/push-to-start": {
      "post": {
        "description": "Registers an iOS 17.2+ push-to-start token, which starts an activity that\ndoes not exist yet. The platform issues one token per activity **type**, so `activity_type` is\nrequired and the token is stored keyed by it — there is no activity id and no window to age\nit out.",
        "operationId": "push_to_start_register_v1_apps__app_id__live_activities_push_to_start_post",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "activity_type": "DeliveryAttributes",
                    "push_to_start_token": "b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2",
                    "token": "device-push-token"
                  }
                }
              },
              "schema": {
                "additionalProperties": true,
                "properties": {
                  "activity_type": {
                    "description": "ActivityKit attributes type this token can start.",
                    "title": "Activity Type",
                    "type": "string"
                  },
                  "push_to_start_token": {
                    "description": "iOS 17.2+ push-to-start token in hexadecimal form.",
                    "title": "Push To Start Token",
                    "type": "string"
                  },
                  "token": {
                    "description": "Device's registered push token.",
                    "title": "Token",
                    "type": "string"
                  }
                },
                "required": [
                  "token",
                  "activity_type",
                  "push_to_start_token"
                ],
                "title": "PushToStartRegister",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "The stored push-to-start row"
          },
          "400": {
            "description": "activity_type missing, or push_to_start_token is not a hex APNs token"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-SDK-Key"
          },
          "404": {
            "description": "Unknown device token for this app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "SdkKey": []
          }
        ],
        "summary": "Register a push-to-start token",
        "tags": [
          "Live Activities"
        ]
      }
    },
    "/v1/apps/{app_id}/live-activities/push-to-start/remove": {
      "post": {
        "description": "Removes this device's push-to-start token for one activity type. A type\nthis device has no token for is a `404`, so a caller can tell a removal from a no-op.",
        "operationId": "push_to_start_remove_v1_apps__app_id__live_activities_push_to_start_remove_post",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "activity_type": "DeliveryAttributes",
                    "token": "device-push-token"
                  }
                }
              },
              "schema": {
                "additionalProperties": true,
                "properties": {
                  "activity_type": {
                    "description": "ActivityKit type whose token should be removed.",
                    "title": "Activity Type",
                    "type": "string"
                  },
                  "token": {
                    "description": "Device's registered push token.",
                    "title": "Token",
                    "type": "string"
                  }
                },
                "required": [
                  "token",
                  "activity_type"
                ],
                "title": "PushToStartRemove",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Confirmation that the token was removed"
          },
          "400": {
            "description": "activity_type is required"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-SDK-Key"
          },
          "404": {
            "description": "Unknown device token, or no push-to-start token for that activity type"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "SdkKey": []
          }
        ],
        "summary": "Remove a push-to-start token",
        "tags": [
          "Live Activities"
        ]
      }
    },
    "/v1/apps/{app_id}/live-activities/{activity_id}/click": {
      "post": {
        "description": "Attributes a tap on a Live Activity back to the push that produced it.\nEvery tap increments the message's click total, while the per-delivery click timestamp is\nkept first-write-wins so distinct-device funnel numbers stay honest.\n\nPass `notification_id` to attribute a specific push; without it the most recent Live\nActivity push delivered to this device for this activity is used. If no such push exists,\nthe click is a `404` rather than being attributed to nothing.",
        "operationId": "live_activity_click_v1_apps__app_id__live_activities__activity_id__click_post",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "activity_id",
            "required": true,
            "schema": {
              "title": "Activity Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "activity_type": "DeliveryAttributes",
                    "notification_id": "msg_9f21c4a70b3d",
                    "token": "device-push-token"
                  }
                }
              },
              "schema": {
                "additionalProperties": true,
                "properties": {
                  "activity_type": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Narrows reused activity ids by attributes type.",
                    "title": "Activity Type"
                  },
                  "notification_id": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Exact Live Activity notification id to attribute.",
                    "title": "Notification Id"
                  },
                  "token": {
                    "description": "Device's registered push token.",
                    "title": "Token",
                    "type": "string"
                  }
                },
                "required": [
                  "token"
                ],
                "title": "LiveActivityClick",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Confirmation that the click was recorded"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-SDK-Key"
          },
          "404": {
            "description": "Unknown device token, or no live activity push to attribute this click to"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "SdkKey": []
          }
        ],
        "summary": "Record a Live Activity click",
        "tags": [
          "Live Activities"
        ]
      }
    },
    "/v1/apps/{app_id}/live-activities/{activity_id}/end": {
      "post": {
        "description": "The device reports that one of **its own** activities is over. An activity\nid that belongs to another device is a `404`, not a silent success — \"we ended it\" and\n\"you do not have one by that name\" are different answers.",
        "operationId": "live_activity_end_v1_apps__app_id__live_activities__activity_id__end_post",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "activity_id",
            "required": true,
            "schema": {
              "title": "Activity Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "token": "device-push-token"
                  }
                }
              },
              "schema": {
                "additionalProperties": true,
                "properties": {
                  "token": {
                    "description": "Device's registered push token.",
                    "title": "Token",
                    "type": "string"
                  }
                },
                "required": [
                  "token"
                ],
                "title": "LiveActivityEnd",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Confirmation that the activity was ended"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-SDK-Key"
          },
          "404": {
            "description": "Unknown device token, or no live activity by that id on this device"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "SdkKey": []
          }
        ],
        "summary": "End a Live Activity",
        "tags": [
          "Live Activities"
        ]
      }
    },
    "/v1/apps/{app_id}/manifest": {
      "get": {
        "operationId": "get_manifest_v1_apps__app_id__manifest_get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Get Manifest",
        "tags": [
          "Apps, keys & settings"
        ]
      },
      "put": {
        "description": "Stores only the consent-filtered manifest produced after OpenPush Scan review.",
        "operationId": "put_manifest_v1_apps__app_id__manifest_put",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "description": "A scanner-produced app manifest. Read /v1/manifest-schema for the versioned field contract.",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "403": {
            "description": "Read-only API key"
          },
          "413": {
            "description": "Manifest exceeds 512 KiB"
          },
          "422": {
            "description": "Manifest validation or redaction failure"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Upload a reviewed app manifest",
        "tags": [
          "Apps, keys & settings"
        ]
      }
    },
    "/v1/apps/{app_id}/manifest/diff": {
      "post": {
        "operationId": "diff_manifest_v1_apps__app_id__manifest_diff_post",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "description": "A scanner-produced app manifest. Read /v1/manifest-schema for the versioned field contract.",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "403": {
            "description": "Read-only API key"
          },
          "422": {
            "description": "Manifest validation or redaction failure"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Diff Manifest",
        "tags": [
          "Apps, keys & settings"
        ]
      }
    },
    "/v1/apps/{app_id}/manifest/history": {
      "get": {
        "operationId": "manifest_history_v1_apps__app_id__manifest_history_get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 10,
              "title": "Limit",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Manifest History",
        "tags": [
          "Apps, keys & settings"
        ]
      }
    },
    "/v1/apps/{app_id}/messages": {
      "get": {
        "description": "The Sent Messages report, newest-created first. Pass `scheduled=1` for the\nscheduled queue instead. Console drafts appear in **neither** list: a draft is not sent and\nnot scheduled either. Test sends are excluded too. `limit` is 1–200; pass `next_cursor` as\n`cursor` for the next page. Optional `status` and `name` are exact filters. A cursor is bound\nto its app, queue and filters and is invalid if any of those change. Rows that leave the\nscheduled queue while paging are absent from later pages.\n\nThe funnel names are deliberately honest and mean different things: Provider Accepted (the\nprovider took it) → Device Received (the SDK got the data) → Confirmed Receipt (it was\ndisplayed) → Clicked.",
        "operationId": "sent_messages_v1_apps__app_id__messages_get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "scheduled",
            "required": false,
            "schema": {
              "default": 0,
              "title": "Scheduled",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 50,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "title": "Cursor",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "title": "Status",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "name",
            "required": false,
            "schema": {
              "title": "Name",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "One report row per message, with the full delivery funnel and next_cursor"
          },
          "400": {
            "description": "Invalid limit, queue selector, filter or cursor"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "List sent or scheduled messages",
        "tags": [
          "Messages"
        ]
      },
      "post": {
        "description": "Creates a message and either sends it immediately or schedules it.\nAccepts content inline or by `template`, per-language content, A/B `variants`, saved\nsegments, generic inline `filters`, bounded direct recipient lists under `target`,\n`platform_options` for iOS/Android presentation, and delivery options (`ttl`, `priority`,\n`collapse_key`, `delayed_option`, `delivery_time_of_day`).\n\n> **Idempotency.** Send an `Idempotency-Key` header (16-128 characters) and a retry is a\n> retry, not a second send: for 24 hours the same key with the same body replays the\n> original response — same status, same message id, nothing sent twice — carrying\n> `Idempotent-Replayed: true`. The same key with a *different* body is a `409`, and so is\n> a key whose first request has not answered yet. A create that is **refused** (a `4xx`\n> raised before anything is sent) hands the key back, so the corrected request on the same\n> key is a real send; once the send has started, whatever the request finally answers —\n> including a `5xx` — is stored and replayed, so a retry after a failure can never become a\n> second push. **Without the header there is no deduplication**: a retried create is a\n> second send, and the way to recover from a timeout is to list messages and match on the\n> campaign `name` before retrying.\n\n> **Collision warnings.** The response carries a `warnings` array. An `audience_collision`\n> entry says this audience already received — or is already scheduled to receive — another\n> message within 24 hours, either because the audience definition is identical or because at\n> least 80% of the devices this send reached also took the other one. It is **advisory**: the\n> send has already happened by the time you read it, and nothing about it is a refusal.\n\n> **Blast-radius warnings.** A `blast_radius` entry in the same array says this send reached\n> at least 500 devices AND more than both three times the median audience of your last ten\n> sends and half of everyone subscribed to the app. It carries the numbers it used\n> (`audience`, `median_recent`, `subscribed`) and which bar was the binding one (`reason`:\n> `3x_median` or `half_of_app`). Advisory in exactly the same way — the console asks an\n> operator to acknowledge a send this size, the API tells a program what it just did.\n\n> **Two-person approval.** When an app admin has turned it on, a create here is a\n> **request**: the response is a `202` with `\"status\": \"pending_approval\"`, the message is\n> created and held, and nothing is sent or scheduled until a manager or admin **other than\n> the requester** approves it in the console under Scheduled Messages. **A request made\n> with an API key needs a person to approve it:** the requester recorded on the message is\n> the key's own name, which is nobody's address, so any manager or admin may be that second\n> person — the key cannot approve what it asked for, and neither can it nominate who does.\n> An OAuth-bound caller records the person behind the grant instead, and that person is\n> then refused as the approver like any other requester. Rejection leaves the message\n> unsent with the reason recorded. With an `Idempotency-Key`, a replay returns the same\n> `202` — it never reports the send as done.\n\nAn immediate send resolves the audience *before* creating the row, so an empty audience is\na `404` and no message row is left behind. A scheduled send is accepted without that check.\n`provider_accepted` in the response means the provider took the push; device receipts\narrive later via `/v1/ingest`. Unknown audience fields are rejected before the message is\nstored.",
        "operationId": "post_message_v1_apps__app_id__messages_post",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "title": "Idempotency-Key",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "actions": [
                      {
                        "id": "open",
                        "label": "Open update"
                      }
                    ],
                    "body": "OpenPush 1.1 is out — see what's new.",
                    "data": {
                      "screen": "changelog"
                    },
                    "filters": [
                      {
                        "field": "tag",
                        "key": "plan",
                        "op": "is",
                        "value": "pro"
                      },
                      {
                        "operator": "or"
                      },
                      {
                        "field": "country",
                        "op": "is",
                        "value": "US"
                      }
                    ],
                    "include_segments": [
                      "Subscribed Users"
                    ],
                    "name": "launch-day",
                    "title": "We are live"
                  }
                }
              },
              "schema": {
                "additionalProperties": false,
                "description": "POST /v1/apps/{app_id}/messages — handler + API handbook 02.",
                "properties": {
                  "ab": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "A/B split and holdback configuration.",
                    "title": "Ab"
                  },
                  "actions": {
                    "description": "One to three mobile notification buttons. Invalid buttons reject the send. The app click callback receives the selected ID; server receipts count clicks without button attribution.",
                    "items": {
                      "additionalProperties": false,
                      "description": "One mobile notification button in a message create request.",
                      "properties": {
                        "icon": {
                          "default": "",
                          "description": "Optional icon resource name used by the mobile renderer.",
                          "maxLength": 256,
                          "title": "Icon",
                          "type": "string"
                        },
                        "id": {
                          "description": "Unique button identifier returned in the app click callback.",
                          "maxLength": 64,
                          "minLength": 1,
                          "pattern": "^[A-Za-z0-9._-]+$",
                          "title": "Id",
                          "type": "string"
                        },
                        "label": {
                          "description": "Visible label; nonblank and rendered per recipient, with a 48-character display cap.",
                          "maxLength": 256,
                          "minLength": 1,
                          "title": "Label",
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "label"
                      ],
                      "title": "MessageAction",
                      "type": "object"
                    },
                    "maxItems": 3,
                    "minItems": 1,
                    "title": "Actions",
                    "type": "array"
                  },
                  "body": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Notification body; Liquid is rendered per subscriber.",
                    "title": "Body"
                  },
                  "collapse_id": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Legacy spelling of collapse_key.",
                    "title": "Collapse Id"
                  },
                  "collapse_key": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Replaces an older pending notification with the same key.",
                    "title": "Collapse Key"
                  },
                  "created_by": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Attribution label; defaults to api.",
                    "title": "Created By"
                  },
                  "custom_data": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Additional message-level values used by preview and rendering.",
                    "title": "Custom Data"
                  },
                  "data": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Custom key/value payload delivered to the SDK.",
                    "title": "Data"
                  },
                  "deep_link": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Destination opened when the notification is tapped.",
                    "title": "Deep Link"
                  },
                  "default_language": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Fallback language code for localized content.",
                    "title": "Default Language"
                  },
                  "delayed_option": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Best-Hour Delivery mode, such as best-hour delivery.",
                    "title": "Delayed Option"
                  },
                  "delivery_policy": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "integer"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Optional frequency_cap and throttle_per_minute that tighten app limits for this message.",
                    "title": "Delivery Policy"
                  },
                  "delivery_time_of_day": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "HH:MM local delivery time for time-of-day delivery.",
                    "title": "Delivery Time Of Day"
                  },
                  "exclude_segments": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Segment names to exclude.",
                    "title": "Exclude Segments"
                  },
                  "filters": {
                    "anyOf": [
                      {
                        "items": {
                          "additionalProperties": true,
                          "type": "object"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Inline audience filter list. Predicates are ANDed; {operator:'or'} starts the next OR group. Supports tag, country, language, app_version, device_type, session, duration, test-user and location fields using the segment rule vocabulary. Intersects with segments and target.",
                    "title": "Filters"
                  },
                  "image_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "HTTPS notification image URL or an OpenPush /media path.",
                    "title": "Image Url"
                  },
                  "include_segments": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Segment names to include.",
                    "title": "Include Segments"
                  },
                  "languages": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Per-language content overrides.",
                    "title": "Languages"
                  },
                  "name": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Campaign name shown in reports and used as the caller's retry handle.",
                    "title": "Name"
                  },
                  "platform_options": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Validated iOS/Android presentation options; stored with the message and applied by the delivery pipeline.",
                    "title": "Platform Options"
                  },
                  "priority": {
                    "anyOf": [
                      {
                        "enum": [
                          "high",
                          "normal"
                        ],
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Provider delivery priority.",
                    "title": "Priority"
                  },
                  "schedule_at": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "ISO-8601 time or epoch seconds; absent sends immediately.",
                    "title": "Schedule At"
                  },
                  "subtitle": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Optional notification subtitle.",
                    "title": "Subtitle"
                  },
                  "target": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "One identity selector: external_id, external_ids, subscription_id, subscription_ids, token, alias:{label,id}, or aliases:{label,ids}. Up to 100 IDs; platforms may intersect it.",
                    "title": "Target"
                  },
                  "template": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Template id or name; inline content overrides template fields.",
                    "title": "Template"
                  },
                  "template_id": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Legacy spelling of template.",
                    "title": "Template Id"
                  },
                  "title": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Notification title.",
                    "title": "Title"
                  },
                  "ttl": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Seconds the provider may retain an undelivered push.",
                    "title": "Ttl"
                  },
                  "ttl_s": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Legacy spelling of ttl, in seconds.",
                    "title": "Ttl S"
                  },
                  "variants": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "A/B variants keyed by variant name.",
                    "title": "Variants"
                  },
                  "vars": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Variables available to Liquid templates for this send.",
                    "title": "Vars"
                  }
                },
                "title": "MessageCreate",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageSendResult"
                }
              }
            },
            "description": "The message id plus the send funnel, or the schedule confirmation"
          },
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageSendResult"
                }
              }
            },
            "description": "This app requires a second person to approve a send. The message was created and is waiting; `status` is `pending_approval` and nothing has been sent or scheduled."
          },
          "400": {
            "description": "Malformed segment rules or target, invalid content, bad schedule, or unknown dynamic-content reference"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "403": {
            "description": "Read-only X-OP-API-Key, or the shared sample app sends from the console only — it has no REST send path"
          },
          "404": {
            "description": "Unknown app, or no matching subscriptions for an immediate send"
          },
          "409": {
            "description": "Idempotency-Key reused for a different request, or reused while the first request is still in flight"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          },
          "503": {
            "description": "Async delivery admission is temporarily unavailable; no message was created"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Create and send a message",
        "tags": [
          "Messages"
        ]
      }
    },
    "/v1/apps/{app_id}/messages/{message_id}": {
      "delete": {
        "description": "Cancels a message that is still `Scheduled`. **Only a scheduled message\ncan be cancelled** — one that is already sending, sent or cancelled is a `409`, and there is\nno unsend. An unknown message id reads as the same `409`, since neither is scheduled.",
        "operationId": "cancel_message_v1_apps__app_id__messages__message_id__delete",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "message_id",
            "required": true,
            "schema": {
              "title": "Message Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "The message id and its Canceled status"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "403": {
            "description": "Read-only X-OP-API-Key"
          },
          "409": {
            "description": "The message is not Scheduled — already sending, sent, cancelled, or unknown"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Cancel a scheduled message",
        "tags": [
          "Messages"
        ]
      },
      "get": {
        "description": "The full report for one message: content as sent, audience and cap\nfigures, the delivery funnel, per-variant numbers for an A/B test, and any render errors\nrecorded at send time.",
        "operationId": "message_report_v1_apps__app_id__messages__message_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "message_id",
            "required": true,
            "schema": {
              "title": "Message Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "The full delivery report for one message"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "404": {
            "description": "Unknown message for this app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Read a message report",
        "tags": [
          "Messages"
        ]
      }
    },
    "/v1/apps/{app_id}/messages/{message_id}/activity-exports": {
      "post": {
        "operationId": "create_activity_export_v1_apps__app_id__messages__message_id__activity_exports_post",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "message_id",
            "required": true,
            "schema": {
              "title": "Message Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "types": [
                      "accepted",
                      "received",
                      "failed"
                    ]
                  }
                }
              },
              "schema": {
                "additionalProperties": true,
                "properties": {
                  "types": {
                    "items": {
                      "enum": [
                        "accepted",
                        "received",
                        "confirmed",
                        "clicked",
                        "failed"
                      ],
                      "type": "string"
                    },
                    "title": "Types",
                    "type": "array"
                  }
                },
                "required": [
                  "types"
                ],
                "title": "ActivityExportCreate",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "403": {
            "description": "Read-only API key or shared sample app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Create Activity Export",
        "tags": [
          "Messages"
        ]
      }
    },
    "/v1/apps/{app_id}/messages/{message_id}/deliveries": {
      "get": {
        "description": "One row per targeted device with its state — **Waiting** (best-hour delivery is\nholding it), **Held** (quiet hours), **Capped**, **Queued**, **Sent**, **Accepted** (provider took it),\n**Retrying**, **Dead-lettered**, **Failed**, **Pending** — and a detail string. `by_state` counts the\nwhole message regardless of paging. Filter with `state`; page with `cursor` (keyset on `sub_id`);\n`limit` is capped at 1000.",
        "operationId": "message_deliveries_route_v1_apps__app_id__messages__message_id__deliveries_get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "message_id",
            "required": true,
            "schema": {
              "title": "Message Id",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "state",
            "required": false,
            "schema": {
              "default": "",
              "title": "State",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 50,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "default": "",
              "title": "Cursor",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Delivery rows with derived state, counts by state, and paging"
          },
          "400": {
            "description": "Unknown state"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "403": {
            "description": "The shared sample app is read from the console only"
          },
          "404": {
            "description": "Unknown message for this app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "List per-device delivery states for a message",
        "tags": [
          "Messages"
        ]
      }
    },
    "/v1/apps/{app_id}/messages/{message_id}/promote": {
      "post": {
        "description": "Sends the winning arm of a finished A/B test to the holdback wave. The\nholdback is device-disjoint from the tested arms, so nobody who saw a variant receives the\npromotion. `winner` names the variant to promote.\n\nA message with no holdback left, no variants, or an already-promoted test is a `409`.",
        "operationId": "promote_message_winner_v1_apps__app_id__messages__message_id__promote_post",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "message_id",
            "required": true,
            "schema": {
              "title": "Message Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "winner": "B"
                  }
                }
              },
              "schema": {
                "additionalProperties": true,
                "properties": {
                  "winner": {
                    "description": "Variant name to send to the A/B holdback audience.",
                    "title": "Winner",
                    "type": "string"
                  }
                },
                "required": [
                  "winner"
                ],
                "title": "MessagePromote",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "The promotion wave and its send funnel"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "403": {
            "description": "Read-only X-OP-API-Key"
          },
          "404": {
            "description": "Unknown message for this app"
          },
          "409": {
            "description": "Not promotable — no variants, no holdback, or already promoted"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Promote an A/B winner",
        "tags": [
          "Messages"
        ]
      }
    },
    "/v1/apps/{app_id}/messages/{message_id}/trace": {
      "get": {
        "description": "Why did — or didn't — one person get this message. Pass exactly one of\n`external_id`, `user_id`, `subscription_id`. Every device the subject owns gets an outcome from a\nclosed vocabulary — `not_in_audience`, `capped`, `held_quiet_hours`, `waiting_best_hour`, `queued`,\n`retrying`, `dead_lettered`, `failed`, `oem_background_restriction_suspected`,\n`accepted_no_receipt`, `received`, `confirmed`, `clicked`, plus `user_not_found`, `no_devices`,\n`no_sendable_device` and `message_not_sent_yet` — and the verdict is the best device, because one\nreached device means the person was reached. `oem_background_restriction_suspected` is the Android\nhandset that was accepted by the provider, never reported a receipt, and is made by a manufacturer\nknown to kill background apps: a suspicion, worded as one. Audience membership is re-evaluated\n**now**, and `notes` says so; a `not_in_audience` detail names the first targeting rule the device\nfails.",
        "operationId": "trace_route_v1_apps__app_id__messages__message_id__trace_get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "message_id",
            "required": true,
            "schema": {
              "title": "Message Id",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "external_id",
            "required": false,
            "schema": {
              "default": "",
              "title": "External Id",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "user_id",
            "required": false,
            "schema": {
              "default": "",
              "title": "User Id",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "subscription_id",
            "required": false,
            "schema": {
              "default": "",
              "title": "Subscription Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Per-device outcomes and a verdict"
          },
          "400": {
            "description": "Not exactly one subject given"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "403": {
            "description": "The shared sample app is read from the console only"
          },
          "404": {
            "description": "Unknown message for this app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Trace one user's delivery of a message",
        "tags": [
          "Messages"
        ]
      }
    },
    "/v1/apps/{app_id}/render-preview": {
      "post": {
        "description": "Renders every personalisation target — `title`, `subtitle`, `body`,\n`image_url` and `deep_link` — against a **caller-supplied** sample device rather than one\ndrawn from the audience, so a variant can be checked without anybody matching it yet.\n\nPer-field render errors come back in `errors` rather than failing the request; the field\nthen holds its unrendered source. Dynamic-content tables referenced by the content are\nresolved and named back in `dynamic_content`, and an unknown one is an error.",
        "operationId": "render_message_preview_v1_apps__app_id__render_preview_post",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "body": "Your score is {{ subscription.tags.score | default: 0 }}.",
                    "external_id": "player-42",
                    "language": "en",
                    "tags": {
                      "score": 1200
                    },
                    "title": "Hello, {{ user.external_id }}"
                  }
                }
              },
              "schema": {
                "additionalProperties": true,
                "properties": {
                  "body": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Body to render.",
                    "title": "Body"
                  },
                  "country": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Sample country code.",
                    "title": "Country"
                  },
                  "custom_data": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Sample custom data available to Liquid.",
                    "title": "Custom Data"
                  },
                  "deep_link": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Deep link to render.",
                    "title": "Deep Link"
                  },
                  "external_id": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Sample external user id.",
                    "title": "External Id"
                  },
                  "image_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Image URL to render.",
                    "title": "Image Url"
                  },
                  "language": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Sample language code.",
                    "title": "Language"
                  },
                  "message_id": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Existing message whose content should be previewed.",
                    "title": "Message Id"
                  },
                  "subscription": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Caller-supplied sample subscription fields.",
                    "title": "Subscription"
                  },
                  "subtitle": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Subtitle to render.",
                    "title": "Subtitle"
                  },
                  "tags": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Sample user tags.",
                    "title": "Tags"
                  },
                  "title": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Title to render.",
                    "title": "Title"
                  }
                },
                "title": "RenderPreview",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "The rendered fields, per-field errors, and the dynamic content used"
          },
          "400": {
            "description": "A referenced dynamic-content table does not exist"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Preview rendered content",
        "tags": [
          "Messages"
        ]
      }
    },
    "/v1/apps/{app_id}/segments": {
      "get": {
        "description": "Every segment for one app — rules, a human-readable rendering of them, and\na **live subscription count evaluated at request time**, so a large app pays for that count\non every call. The default target segment sorts first.\n\nThe response also carries the field catalogue (`fields`): the filterable fields, their\noperators and hints, which is what a rule builder needs.",
        "operationId": "list_segments_v1_apps__app_id__segments_get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Segments with live counts, plus the filterable field catalogue"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "List segments",
        "tags": [
          "Segments"
        ]
      },
      "post": {
        "description": "Creates a segment from a name and a rule list. Rules are compiled before\nanything is written, so a malformed rule is a `400` naming the problem rather than a\nsegment that silently matches everything.\n\nSetting `is_target_default: true` moves the default off whichever segment currently holds\nit — there is exactly one default target per app.",
        "operationId": "create_segment_v1_apps__app_id__segments_post",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "name": "English Android users",
                    "rules": [
                      {
                        "field": "language",
                        "group": "0",
                        "op": "is",
                        "value": "en"
                      },
                      {
                        "field": "device_type",
                        "group": "0",
                        "op": "is",
                        "value": "Android"
                      }
                    ]
                  }
                }
              },
              "schema": {
                "additionalProperties": true,
                "properties": {
                  "is_target_default": {
                    "default": false,
                    "description": "Move the app's default targeting flag to this segment.",
                    "title": "Is Target Default",
                    "type": "boolean"
                  },
                  "name": {
                    "description": "Non-empty segment display name.",
                    "title": "Name",
                    "type": "string"
                  },
                  "rules": {
                    "description": "Filter rows; an empty list matches every subscribed device.",
                    "items": {
                      "additionalProperties": true,
                      "properties": {
                        "field": {
                          "description": "Audience field to compare, such as tag, country, or last_session.",
                          "title": "Field",
                          "type": "string"
                        },
                        "group": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "OR-bucket label; defaults to 0.",
                          "title": "Group"
                        },
                        "key": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "Tag key when field is tag.",
                          "title": "Key"
                        },
                        "lat": {
                          "anyOf": [
                            {
                              "type": "number"
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "Latitude when field is location.",
                          "title": "Lat"
                        },
                        "lng": {
                          "anyOf": [
                            {
                              "type": "number"
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "Longitude when field is location.",
                          "title": "Lng"
                        },
                        "op": {
                          "default": "is",
                          "description": "Comparison operator supported by the chosen field.",
                          "title": "Op",
                          "type": "string"
                        },
                        "value": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "integer"
                            },
                            {
                              "type": "number"
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "Comparison value; omitted for exists/not_exists.",
                          "title": "Value"
                        }
                      },
                      "required": [
                        "field"
                      ],
                      "title": "SegmentRule",
                      "type": "object"
                    },
                    "title": "Rules",
                    "type": "array"
                  },
                  "status": {
                    "default": "Active",
                    "description": "Whether the segment may be targeted.",
                    "enum": [
                      "Active",
                      "Paused"
                    ],
                    "title": "Status",
                    "type": "string"
                  }
                },
                "required": [
                  "name"
                ],
                "title": "SegmentCreate",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "The created segment with its rule text and live count"
          },
          "400": {
            "description": "name missing, malformed rules, or is_target_default is not a boolean"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "403": {
            "description": "Read-only X-OP-API-Key"
          },
          "404": {
            "description": "Unknown app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Create a segment",
        "tags": [
          "Segments"
        ]
      }
    },
    "/v1/apps/{app_id}/segments/{seg_id}": {
      "delete": {
        "description": "Deletes a segment. **Managed segments cannot be deleted** — the built-in\nones an app is created with are a `409`.\n\nIf the deleted segment held the default target, the default falls back to Total\nSubscriptions, or to the oldest remaining segment, so an app is never left without one.",
        "operationId": "delete_segment_v1_apps__app_id__segments__seg_id__delete",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "seg_id",
            "required": true,
            "schema": {
              "title": "Seg Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "The segment id and confirmation of deletion"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "403": {
            "description": "Read-only X-OP-API-Key"
          },
          "404": {
            "description": "Unknown segment for this app"
          },
          "409": {
            "description": "Managed segments cannot be deleted"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Delete a segment",
        "tags": [
          "Segments"
        ]
      },
      "get": {
        "operationId": "get_segment_v1_apps__app_id__segments__seg_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "seg_id",
            "required": true,
            "schema": {
              "title": "Seg Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "404": {
            "description": "Unknown segment for this app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Get a segment",
        "tags": [
          "Segments"
        ]
      },
      "patch": {
        "description": "Updates a segment's `name`, `status` (`Active` or `Paused`), `rules`, or\nits default-target flag. Replacement rules are compiled before they are stored.\n\nThe default target can only be **moved**, never cleared: `is_target_default: false` is a\n`400` telling you to make another segment the default instead. A patch that changes nothing\nis also a `400`.",
        "operationId": "update_segment_v1_apps__app_id__segments__seg_id__patch",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "seg_id",
            "required": true,
            "schema": {
              "title": "Seg Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "status": "Paused"
                  }
                }
              },
              "schema": {
                "additionalProperties": true,
                "properties": {
                  "is_target_default": {
                    "anyOf": [
                      {
                        "type": "boolean"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Only true is accepted; move the default rather than clearing it.",
                    "title": "Is Target Default"
                  },
                  "name": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Replacement display name.",
                    "title": "Name"
                  },
                  "rules": {
                    "anyOf": [
                      {
                        "items": {
                          "additionalProperties": true,
                          "properties": {
                            "field": {
                              "description": "Audience field to compare, such as tag, country, or last_session.",
                              "title": "Field",
                              "type": "string"
                            },
                            "group": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ],
                              "description": "OR-bucket label; defaults to 0.",
                              "title": "Group"
                            },
                            "key": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ],
                              "description": "Tag key when field is tag.",
                              "title": "Key"
                            },
                            "lat": {
                              "anyOf": [
                                {
                                  "type": "number"
                                },
                                {
                                  "type": "null"
                                }
                              ],
                              "description": "Latitude when field is location.",
                              "title": "Lat"
                            },
                            "lng": {
                              "anyOf": [
                                {
                                  "type": "number"
                                },
                                {
                                  "type": "null"
                                }
                              ],
                              "description": "Longitude when field is location.",
                              "title": "Lng"
                            },
                            "op": {
                              "default": "is",
                              "description": "Comparison operator supported by the chosen field.",
                              "title": "Op",
                              "type": "string"
                            },
                            "value": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "integer"
                                },
                                {
                                  "type": "number"
                                },
                                {
                                  "type": "null"
                                }
                              ],
                              "description": "Comparison value; omitted for exists/not_exists.",
                              "title": "Value"
                            }
                          },
                          "required": [
                            "field"
                          ],
                          "title": "SegmentRule",
                          "type": "object"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Replacement filter rows.",
                    "title": "Rules"
                  },
                  "status": {
                    "anyOf": [
                      {
                        "enum": [
                          "Active",
                          "Paused"
                        ],
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Replacement lifecycle status.",
                    "title": "Status"
                  }
                },
                "title": "SegmentUpdate",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "The segment id and confirmation of the update"
          },
          "400": {
            "description": "Nothing to update, an unknown status, malformed rules, or an attempt to clear the default target"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "403": {
            "description": "Read-only X-OP-API-Key"
          },
          "404": {
            "description": "Unknown segment for this app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Update a segment",
        "tags": [
          "Segments"
        ]
      }
    },
    "/v1/apps/{app_id}/send-test": {
      "post": {
        "description": "Sends to this app's **test subscriptions only** and never creates a Sent\nMessages row, so a test cannot pollute campaign reporting.\n\nTest devices deliberately ignore the frequency cap and quiet hours, so a test send arrives\neven inside a window a real send would be held for. An app with no test subscriptions is a\n`404` rather than a silent no-op.",
        "operationId": "send_test_v1_apps__app_id__send_test_post",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "body": "Only registered test devices receive this.",
                    "name": "Release candidate",
                    "title": "A test notification"
                  }
                }
              },
              "schema": {
                "additionalProperties": false,
                "description": "POST /v1/apps/{app_id}/send-test — message content sent only to test devices.",
                "properties": {
                  "ab": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "A/B split and holdback configuration.",
                    "title": "Ab"
                  },
                  "actions": {
                    "description": "One to three mobile notification buttons. Invalid buttons reject the send. The app click callback receives the selected ID; server receipts count clicks without button attribution.",
                    "items": {
                      "additionalProperties": false,
                      "description": "One mobile notification button in a message create request.",
                      "properties": {
                        "icon": {
                          "default": "",
                          "description": "Optional icon resource name used by the mobile renderer.",
                          "maxLength": 256,
                          "title": "Icon",
                          "type": "string"
                        },
                        "id": {
                          "description": "Unique button identifier returned in the app click callback.",
                          "maxLength": 64,
                          "minLength": 1,
                          "pattern": "^[A-Za-z0-9._-]+$",
                          "title": "Id",
                          "type": "string"
                        },
                        "label": {
                          "description": "Visible label; nonblank and rendered per recipient, with a 48-character display cap.",
                          "maxLength": 256,
                          "minLength": 1,
                          "title": "Label",
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "label"
                      ],
                      "title": "MessageAction",
                      "type": "object"
                    },
                    "maxItems": 3,
                    "minItems": 1,
                    "title": "Actions",
                    "type": "array"
                  },
                  "body": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Notification body; Liquid is rendered per subscriber.",
                    "title": "Body"
                  },
                  "collapse_id": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Legacy spelling of collapse_key.",
                    "title": "Collapse Id"
                  },
                  "collapse_key": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Replaces an older pending notification with the same key.",
                    "title": "Collapse Key"
                  },
                  "created_by": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Attribution label; defaults to api.",
                    "title": "Created By"
                  },
                  "custom_data": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Additional message-level values used by preview and rendering.",
                    "title": "Custom Data"
                  },
                  "data": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Custom key/value payload delivered to the SDK.",
                    "title": "Data"
                  },
                  "deep_link": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Destination opened when the notification is tapped.",
                    "title": "Deep Link"
                  },
                  "default_language": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Fallback language code for localized content.",
                    "title": "Default Language"
                  },
                  "delayed_option": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Best-Hour Delivery mode, such as best-hour delivery.",
                    "title": "Delayed Option"
                  },
                  "delivery_policy": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "integer"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Optional frequency_cap and throttle_per_minute that tighten app limits for this message.",
                    "title": "Delivery Policy"
                  },
                  "delivery_time_of_day": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "HH:MM local delivery time for time-of-day delivery.",
                    "title": "Delivery Time Of Day"
                  },
                  "exclude_segments": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Segment names to exclude.",
                    "title": "Exclude Segments"
                  },
                  "filters": {
                    "anyOf": [
                      {
                        "items": {
                          "additionalProperties": true,
                          "type": "object"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Inline audience filter list. Predicates are ANDed; {operator:'or'} starts the next OR group. Supports tag, country, language, app_version, device_type, session, duration, test-user and location fields using the segment rule vocabulary. Intersects with segments and target.",
                    "title": "Filters"
                  },
                  "image_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "HTTPS notification image URL or an OpenPush /media path.",
                    "title": "Image Url"
                  },
                  "include_segments": {
                    "anyOf": [
                      {
                        "items": {
                          "type": "string"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Segment names to include.",
                    "title": "Include Segments"
                  },
                  "languages": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Per-language content overrides.",
                    "title": "Languages"
                  },
                  "name": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Campaign name shown in reports and used as the caller's retry handle.",
                    "title": "Name"
                  },
                  "platform_options": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Validated iOS/Android presentation options; stored with the message and applied by the delivery pipeline.",
                    "title": "Platform Options"
                  },
                  "priority": {
                    "anyOf": [
                      {
                        "enum": [
                          "high",
                          "normal"
                        ],
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Provider delivery priority.",
                    "title": "Priority"
                  },
                  "schedule_at": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "ISO-8601 time or epoch seconds; absent sends immediately.",
                    "title": "Schedule At"
                  },
                  "subtitle": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Optional notification subtitle.",
                    "title": "Subtitle"
                  },
                  "target": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "One identity selector: external_id, external_ids, subscription_id, subscription_ids, token, alias:{label,id}, or aliases:{label,ids}. Up to 100 IDs; platforms may intersect it.",
                    "title": "Target"
                  },
                  "template": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Template id or name; inline content overrides template fields.",
                    "title": "Template"
                  },
                  "template_id": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Legacy spelling of template.",
                    "title": "Template Id"
                  },
                  "title": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Notification title.",
                    "title": "Title"
                  },
                  "ttl": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Seconds the provider may retain an undelivered push.",
                    "title": "Ttl"
                  },
                  "ttl_s": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Legacy spelling of ttl, in seconds.",
                    "title": "Ttl S"
                  },
                  "variants": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "A/B variants keyed by variant name.",
                    "title": "Variants"
                  },
                  "vars": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Variables available to Liquid templates for this send.",
                    "title": "Vars"
                  }
                },
                "title": "SendTest",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "The test message id, the device count and the send funnel"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "403": {
            "description": "Read-only X-OP-API-Key, or the shared sample app sends from the console only — it has no REST send path"
          },
          "404": {
            "description": "Unknown app, or no test subscriptions to send to"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Send a test push",
        "tags": [
          "Messages"
        ]
      }
    },
    "/v1/apps/{app_id}/sessions": {
      "post": {
        "description": "Records a foreground observation or completed foreground duration without\ninventing a receipt —\nreceipts belong to a message and a delivery row, and an app session has neither.\n\nThe **server** decides whether this counts as a new session: an observation inside the\nconfigured session gap updates `last_seen` only and comes back `{\"counted\": false}`. SDKs\nthrottle their calls for battery etiquette, but that gap is the authoritative definition of\na session. Duration reports are idempotent and do not open another session.",
        "operationId": "session_ping_v1_apps__app_id__sessions_post",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "duration_seconds": 83.4,
                    "idempotency_key": "session-0b836ab7",
                    "token": "device-push-token"
                  }
                }
              },
              "schema": {
                "additionalProperties": true,
                "properties": {
                  "duration_seconds": {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Completed foreground time. Omit for a foreground observation.",
                    "title": "Duration Seconds"
                  },
                  "idempotency_key": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Stable event key required with duration_seconds.",
                    "title": "Idempotency Key"
                  },
                  "token": {
                    "description": "Registered device push token observed in the foreground.",
                    "title": "Token",
                    "type": "string"
                  }
                },
                "required": [
                  "token"
                ],
                "title": "SessionCreate",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Whether a session or duration was newly recorded"
          },
          "400": {
            "description": "token required"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-SDK-Key"
          },
          "404": {
            "description": "Unknown app, or unknown subscription for this token"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          },
          "503": {
            "description": "Request body deadline exceeded or safe database retries exhausted; retry after the Retry-After delay"
          }
        },
        "security": [
          {
            "SdkKey": []
          }
        ],
        "summary": "Record an app session",
        "tags": [
          "Subscriptions & users"
        ]
      }
    },
    "/v1/apps/{app_id}/settings": {
      "get": {
        "description": "Quiet hours, frequency caps, link tracking, delivery pacing, and Android\nchannel configuration, plus\nthree things a settings page always needs next: **per-app** platform readiness (which of\nFCM, APNs and web push this app can actually send on), which optional data categories the\napp collects and how many rows of each are already stored, and the server-wide IP storage\nmode (`full`, `truncated` or `off`).\n\n`identity_verification` is reported here but **cannot be changed through the API** — see the\nPATCH route.",
        "operationId": "get_settings_v1_apps__app_id__settings_get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Settings, per-app platform readiness, and collection state"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Read app settings",
        "tags": [
          "Apps, keys & settings"
        ]
      },
      "patch": {
        "description": "Updates quiet hours, frequency caps, link tracking and initial delivery\npacing. Collection switches are accepted either flat\n(`collect_ad_id`) or nested (`collection: {ad_id: true}`), because a console form posts one\nshape and an integration posts back the object it read.\n\n> **Turning a collection switch off erases what it collected.** The purge runs in the same\n> call and the response reports the row counts under `purged`. There is no undo.\n\n`identity_verification` is deliberately **not** accepted here — changing it is a console\naction. A patch that touches none of the accepted fields is a `400`.",
        "operationId": "patch_settings_v1_apps__app_id__settings_patch",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "collection": {
                      "ad_id": false,
                      "email": false,
                      "location": false
                    },
                    "freq_cap": 10,
                    "freq_window_h": 24,
                    "link_tracking_enabled": true,
                    "quiet_enabled": true,
                    "quiet_end": "21:00",
                    "quiet_start": "08:00",
                    "throttle_enabled": false,
                    "throttle_per_minute": 1000,
                    "utm_medium": "push",
                    "utm_source": "openpush"
                  }
                }
              },
              "schema": {
                "additionalProperties": true,
                "properties": {
                  "collect_ad_id": {
                    "anyOf": [
                      {
                        "type": "boolean"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Advertising-id collection switch.",
                    "title": "Collect Ad Id"
                  },
                  "collect_email": {
                    "anyOf": [
                      {
                        "type": "boolean"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Email collection switch.",
                    "title": "Collect Email"
                  },
                  "collect_location": {
                    "anyOf": [
                      {
                        "type": "boolean"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Location collection switch.",
                    "title": "Collect Location"
                  },
                  "collection": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "boolean"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Nested ad_id, location, and email collection switches.",
                    "title": "Collection"
                  },
                  "freq_cap": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Provider-accepted sends per device per window; 0 disables.",
                    "title": "Freq Cap"
                  },
                  "freq_window_h": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Frequency-cap window in hours.",
                    "title": "Freq Window H"
                  },
                  "link_tracking_enabled": {
                    "anyOf": [
                      {
                        "type": "boolean"
                      },
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Add UTM tags to HTTP(S) launch URLs.",
                    "title": "Link Tracking Enabled"
                  },
                  "quiet_enabled": {
                    "anyOf": [
                      {
                        "type": "boolean"
                      },
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Turn quiet hours on or off.",
                    "title": "Quiet Enabled"
                  },
                  "quiet_end": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "End of the allowed daily window, HH:MM device-local.",
                    "title": "Quiet End"
                  },
                  "quiet_start": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Start of the allowed daily window, HH:MM device-local.",
                    "title": "Quiet Start"
                  },
                  "throttle_enabled": {
                    "anyOf": [
                      {
                        "type": "boolean"
                      },
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Pace initial delivery in minute-sized waves.",
                    "title": "Throttle Enabled"
                  },
                  "throttle_per_minute": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Maximum initial deliveries queued each minute.",
                    "title": "Throttle Per Minute"
                  },
                  "utm_campaign": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Fixed campaign value; blank uses the message name.",
                    "title": "Utm Campaign"
                  },
                  "utm_medium": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "UTM medium value.",
                    "title": "Utm Medium"
                  },
                  "utm_source": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "UTM source value.",
                    "title": "Utm Source"
                  }
                },
                "title": "SettingsPatch",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "The settings after the update, with any purge counts"
          },
          "400": {
            "description": "Nothing to update — no recognised settings field in the body"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "403": {
            "description": "Read-only X-OP-API-Key"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Update app settings",
        "tags": [
          "Apps, keys & settings"
        ]
      }
    },
    "/v1/apps/{app_id}/subscriptions": {
      "get": {
        "description": "Subscriptions for one app. `search` matches on token, external id or\nsubscription id; `test=1` restricts the list to test devices.\n\n**Push tokens are truncated to their first 20 characters here** — a list route is for\nlooking, and nobody can migrate a device from a token prefix. `GET /export.ndjson` is the\nroute that returns them whole. Paging works exactly as on the users route: newest-first and\nuncursored by default, `?order=id` for a stable keyset walk, `limit` capped at 1000, and\n`total` is the length of this page.",
        "operationId": "list_subs_v1_apps__app_id__subscriptions_get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "search",
            "required": false,
            "schema": {
              "default": "",
              "title": "Search",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "test",
            "required": false,
            "schema": {
              "default": 0,
              "title": "Test",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 200,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "default": "",
              "title": "Cursor",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "order",
            "required": false,
            "schema": {
              "default": "",
              "title": "Order",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "A page of subscriptions with truncated tokens and paging metadata"
          },
          "400": {
            "description": "Malformed or unreadable cursor"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "403": {
            "description": "The shared sample app is listed from the console only"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "List subscriptions",
        "tags": [
          "Subscriptions & users"
        ]
      },
      "post": {
        "description": "Registers a push token, or updates the row that already holds it. The\nupsert key is `(app, token)`, so calling this on every cold start is the intended usage —\nit is idempotent.\n\n**Absent, present-and-empty, and present-with-a-value are three different claims.** A key\nthe body omits is not a claim and leaves the stored column alone; `external_id: null`\n(or `\"\"`) is an explicit detach. If the app has identity verification on, an\n`external_id`, `tags` or `aliases` claim without a valid `external_id_auth_hash` is\n**downgraded, not rejected**: the device still registers, and the response carries an\n`identity_rejected` note. Values for a data-collection category the app has switched off\nare silently dropped and named back in `not_collected`.",
        "operationId": "register_v1_apps__app_id__subscriptions_post",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "external_id": "player-42",
                    "language": "en",
                    "os_version": "16",
                    "platform": "android",
                    "sdk_version": "1.1.2",
                    "tags": {
                      "plan": "free"
                    },
                    "timezone": "Asia/Kolkata",
                    "token": "device-push-token"
                  }
                }
              },
              "schema": {
                "additionalProperties": true,
                "properties": {
                  "ad_id": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Advertising id; stored only when collection is enabled.",
                    "title": "Ad Id"
                  },
                  "aliases": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Alias label to id.",
                    "title": "Aliases"
                  },
                  "app_version": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Installed app version.",
                    "title": "App Version"
                  },
                  "country": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Country code.",
                    "title": "Country"
                  },
                  "device": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Device model or family.",
                    "title": "Device"
                  },
                  "device_name": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Human-readable device name.",
                    "title": "Device Name"
                  },
                  "email": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Email; stored only when collection is enabled.",
                    "title": "Email"
                  },
                  "external_id": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Your user id; explicit null or empty detaches identity.",
                    "title": "External Id"
                  },
                  "external_id_auth_hash": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Identity-verification hash when the app requires it.",
                    "title": "External Id Auth Hash"
                  },
                  "language": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Language code.",
                    "title": "Language"
                  },
                  "lat": {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Latitude; stored only when collection is enabled.",
                    "title": "Lat"
                  },
                  "link_token": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Single-use link token for the shared sample app.",
                    "title": "Link Token"
                  },
                  "lon": {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Longitude; stored only when collection is enabled.",
                    "title": "Lon"
                  },
                  "os_version": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Operating-system version.",
                    "title": "Os Version"
                  },
                  "platform": {
                    "anyOf": [
                      {
                        "enum": [
                          "ios",
                          "android",
                          "web"
                        ],
                        "type": "string"
                      },
                      {
                        "type": "string"
                      }
                    ],
                    "default": "android",
                    "description": "Push platform.",
                    "title": "Platform"
                  },
                  "rooted": {
                    "anyOf": [
                      {
                        "type": "boolean"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Rooted or jailbroken device signal, when available.",
                    "title": "Rooted"
                  },
                  "sandbox": {
                    "anyOf": [
                      {
                        "type": "boolean"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Whether the APNs token targets the sandbox environment.",
                    "title": "Sandbox"
                  },
                  "sdk_version": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "OpenPush SDK version.",
                    "title": "Sdk Version"
                  },
                  "status": {
                    "anyOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Explicit device subscription status; omitted preserves it.",
                    "title": "Status"
                  },
                  "tags": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "User tags; omitted leaves stored tags unchanged.",
                    "title": "Tags"
                  },
                  "timezone": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "IANA timezone reported by the device.",
                    "title": "Timezone"
                  },
                  "token": {
                    "description": "Device push token; the upsert key within the app.",
                    "title": "Token",
                    "type": "string"
                  }
                },
                "required": [
                  "token"
                ],
                "title": "SubscriptionRegister",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "The subscription id, its resolved status, and any downgrade notes"
          },
          "400": {
            "description": "token missing, a status code a device may not claim, or aliases that are not an object"
          },
          "401": {
            "description": "Bad X-OP-SDK-Key, or (shared sample app only) a missing device link credential"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          },
          "503": {
            "description": "Request body deadline exceeded or safe database retries exhausted; retry after the Retry-After delay"
          }
        },
        "security": [
          {
            "SdkKey": []
          }
        ],
        "summary": "Register or update a device",
        "tags": [
          "Subscriptions & users"
        ]
      }
    },
    "/v1/apps/{app_id}/subscriptions/by-token": {
      "patch": {
        "operationId": "patch_subscription_by_token_admin_v1_apps__app_id__subscriptions_by_token_patch",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "consent": false,
                    "token": "current-token"
                  }
                }
              },
              "schema": {
                "additionalProperties": true,
                "properties": {
                  "app_version": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "App Version"
                  },
                  "consent": {
                    "anyOf": [
                      {
                        "type": "boolean"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Consent"
                  },
                  "device_name": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Device Name"
                  },
                  "new_token": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Replacement push token.",
                    "title": "New Token"
                  },
                  "os_version": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Os Version"
                  },
                  "sandbox": {
                    "anyOf": [
                      {
                        "type": "boolean"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Sandbox"
                  },
                  "sdk_version": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Sdk Version"
                  },
                  "token": {
                    "description": "Current push token; kept out of the URL.",
                    "title": "Token",
                    "type": "string"
                  }
                },
                "required": [
                  "token"
                ],
                "title": "PushSubscriptionUpdateByToken",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "403": {
            "description": "Read-only API key or shared sample app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Patch Subscription By Token Admin",
        "tags": [
          "Subscriptions & users"
        ]
      }
    },
    "/v1/apps/{app_id}/subscriptions/{sub_id}": {
      "delete": {
        "operationId": "delete_subscription_admin_v1_apps__app_id__subscriptions__sub_id__delete",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "sub_id",
            "required": true,
            "schema": {
              "title": "Sub Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "403": {
            "description": "Read-only API key or shared sample app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Delete Subscription Admin",
        "tags": [
          "Subscriptions & users"
        ]
      },
      "get": {
        "description": "One device: its status with the operator-facing `status_ui`/`status_help`, the\nuser behind it, that user's tags, which **active** segments it matches right now, and its delivery\nhistory with derived states. The push token is masked.",
        "operationId": "subscription_profile_route_v1_apps__app_id__subscriptions__sub_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "sub_id",
            "required": true,
            "schema": {
              "title": "Sub Id",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 25,
              "title": "Limit",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "One device profile with matching segments and deliveries"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "403": {
            "description": "The shared sample app is read from the console only"
          },
          "404": {
            "description": "Unknown subscription for this app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Read one subscription",
        "tags": [
          "Subscriptions & users"
        ]
      },
      "patch": {
        "operationId": "patch_subscription_admin_v1_apps__app_id__subscriptions__sub_id__patch",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "sub_id",
            "required": true,
            "schema": {
              "title": "Sub Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "consent": false
                  }
                }
              },
              "schema": {
                "additionalProperties": true,
                "properties": {
                  "app_version": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "App Version"
                  },
                  "consent": {
                    "anyOf": [
                      {
                        "type": "boolean"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Consent"
                  },
                  "device_name": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Device Name"
                  },
                  "new_token": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Replacement push token.",
                    "title": "New Token"
                  },
                  "os_version": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Os Version"
                  },
                  "sandbox": {
                    "anyOf": [
                      {
                        "type": "boolean"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Sandbox"
                  },
                  "sdk_version": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Sdk Version"
                  }
                },
                "title": "PushSubscriptionUpdate",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "403": {
            "description": "Read-only API key or shared sample app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Patch Subscription Admin",
        "tags": [
          "Subscriptions & users"
        ]
      }
    },
    "/v1/apps/{app_id}/subscriptions/{sub_id}/iams": {
      "get": {
        "description": "The in-app message definitions eligible for one device at the start of a\nsession — stable ids, placement, triggers, duration and redisplay rules, with either\nresolved structured blocks or an `html_path` to fetch. Capped at the active definitions the\ndevice qualifies for.\n\nCalled with the SDK key. On the shared sample app a bound device credential is required as\nwell, and a subscription that is not this device's reads as a `404`.",
        "operationId": "iam_fetch_v1_apps__app_id__subscriptions__sub_id__iams_get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "sub_id",
            "required": true,
            "schema": {
              "title": "Sub Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "The in-app message definitions this device is eligible for"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-SDK-Key"
          },
          "404": {
            "description": "Unknown app, or unknown subscription for this app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "SdkKey": []
          }
        ],
        "summary": "Fetch in-app messages for a device",
        "tags": [
          "In-app messages"
        ]
      }
    },
    "/v1/apps/{app_id}/subscriptions/{sub_id}/transfer": {
      "post": {
        "operationId": "transfer_subscription_admin_v1_apps__app_id__subscriptions__sub_id__transfer_post",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "sub_id",
            "required": true,
            "schema": {
              "title": "Sub Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "user_id": "usr_0123456789ab"
                  }
                }
              },
              "schema": {
                "additionalProperties": true,
                "properties": {
                  "user_id": {
                    "description": "Existing user ID in the same app.",
                    "title": "User Id",
                    "type": "string"
                  }
                },
                "required": [
                  "user_id"
                ],
                "title": "SubscriptionTransfer",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "403": {
            "description": "Read-only API key or shared sample app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Transfer Subscription Admin",
        "tags": [
          "Subscriptions & users"
        ]
      }
    },
    "/v1/apps/{app_id}/suggestions": {
      "get": {
        "operationId": "list_suggestions_v1_apps__app_id__suggestions_get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "default": "proposed",
              "title": "Status",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "kind",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Kind"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 50,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "offset",
            "required": false,
            "schema": {
              "default": 0,
              "title": "Offset",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "List Suggestions",
        "tags": [
          "Apps, keys & settings"
        ]
      }
    },
    "/v1/apps/{app_id}/suggestions/generate": {
      "post": {
        "operationId": "generate_suggestions_v1_apps__app_id__suggestions_generate_post",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {}
                }
              },
              "schema": {
                "additionalProperties": true,
                "description": "No request fields.",
                "properties": {},
                "title": "EmptyBody",
                "type": "object"
              }
            }
          },
          "required": false
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "403": {
            "description": "Read-only API key"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Generate Suggestions",
        "tags": [
          "Apps, keys & settings"
        ]
      }
    },
    "/v1/apps/{app_id}/suggestions/{suggestion_id}/accept": {
      "post": {
        "operationId": "accept_suggestion_v1_apps__app_id__suggestions__suggestion_id__accept_post",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "suggestion_id",
            "required": true,
            "schema": {
              "title": "Suggestion Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "as_template": false
                  }
                }
              },
              "schema": {
                "additionalProperties": true,
                "description": "Optional creation mode when accepting a recommendation.",
                "properties": {
                  "as_template": {
                    "anyOf": [
                      {
                        "type": "boolean"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "default": false,
                    "description": "For in-app recommendations, create a reusable template instead of a draft message.",
                    "title": "As Template"
                  }
                },
                "title": "SuggestionDecision",
                "type": "object"
              }
            }
          },
          "required": false
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "403": {
            "description": "Read-only API key"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Accept Suggestion",
        "tags": [
          "Apps, keys & settings"
        ]
      }
    },
    "/v1/apps/{app_id}/suggestions/{suggestion_id}/dismiss": {
      "post": {
        "operationId": "dismiss_suggestion_v1_apps__app_id__suggestions__suggestion_id__dismiss_post",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "suggestion_id",
            "required": true,
            "schema": {
              "title": "Suggestion Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {}
                }
              },
              "schema": {
                "additionalProperties": true,
                "description": "No request fields.",
                "properties": {},
                "title": "EmptyBody",
                "type": "object"
              }
            }
          },
          "required": false
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "403": {
            "description": "Read-only API key"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Dismiss Suggestion",
        "tags": [
          "Apps, keys & settings"
        ]
      }
    },
    "/v1/apps/{app_id}/templates": {
      "get": {
        "description": "Every saved template for one app, newest first, with its data payload\nexpanded — plus the names of the built-in starter templates the console offers.",
        "operationId": "list_templates_v1_apps__app_id__templates_get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Saved templates and the built-in template names"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "List templates",
        "tags": [
          "Templates & dynamic content"
        ]
      },
      "post": {
        "description": "Saves a reusable push template. `name`, `title` and `body` are\nrequired. Optional fields include `image_url`, `deep_link`, `data`, localized\n`languages`, `default_language`, and validated `platform_options`.\n\nLiquid in every field is validated up front, and any dynamic-content table it references\nmust already exist — an unknown table is a `400` rather than a template that fails at send\ntime. **There is no API route that uploads an image**: `image_url` must be an HTTPS URL, or\na `/media/...` path produced by uploading through the console.",
        "operationId": "create_template_v1_apps__app_id__templates_post",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "body": "Thanks for joining us.",
                    "deep_link": "myapp://home",
                    "name": "Welcome",
                    "title": "Welcome, {{ user.external_id | default: 'there' }}"
                  }
                }
              },
              "schema": {
                "additionalProperties": true,
                "properties": {
                  "body": {
                    "description": "Notification body; Liquid is supported.",
                    "title": "Body",
                    "type": "string"
                  },
                  "data": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Custom payload object.",
                    "title": "Data"
                  },
                  "deep_link": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Tap destination.",
                    "title": "Deep Link"
                  },
                  "default_language": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Fallback language; defaults to en.",
                    "title": "Default Language"
                  },
                  "image_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "HTTPS image URL or an OpenPush /media path.",
                    "title": "Image Url"
                  },
                  "languages": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Localized title and body by language code.",
                    "title": "Languages"
                  },
                  "name": {
                    "description": "Template display name.",
                    "title": "Name",
                    "type": "string"
                  },
                  "platform_options": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Default iOS and Android presentation options.",
                    "title": "Platform Options"
                  },
                  "title": {
                    "description": "Notification title; Liquid is supported.",
                    "title": "Title",
                    "type": "string"
                  }
                },
                "required": [
                  "name",
                  "title",
                  "body"
                ],
                "title": "TemplateCreate",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "The stored template row"
          },
          "400": {
            "description": "name, title or body missing; data is not an object; an unusable image URL; or invalid Liquid or an unknown dynamic-content table"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "403": {
            "description": "Read-only X-OP-API-Key"
          },
          "404": {
            "description": "Unknown app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Create a template",
        "tags": [
          "Templates & dynamic content"
        ]
      }
    },
    "/v1/apps/{app_id}/templates/{tpl_id}": {
      "delete": {
        "description": "Deletes a saved template. Messages already sent from it keep the content\nthey were sent with, but a scheduled message that still resolves this template by id will\nfail when it comes to send.",
        "operationId": "delete_template_v1_apps__app_id__templates__tpl_id__delete",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "tpl_id",
            "required": true,
            "schema": {
              "title": "Tpl Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "The template id and confirmation of deletion"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "403": {
            "description": "Read-only X-OP-API-Key"
          },
          "404": {
            "description": "Unknown template for this app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Delete a template",
        "tags": [
          "Templates & dynamic content"
        ]
      },
      "get": {
        "operationId": "get_template_v1_apps__app_id__templates__tpl_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "tpl_id",
            "required": true,
            "schema": {
              "title": "Tpl Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "404": {
            "description": "Unknown template for this app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Get a template",
        "tags": [
          "Templates & dynamic content"
        ]
      },
      "patch": {
        "description": "Updates content, localized languages, default language or platform\npresentation defaults on a saved template. The **merged** result is revalidated, so a Liquid reference that only breaks\nonce combined with the untouched fields is caught here. A patch with none of those keys is a\n`400`.\n\nMessages already created from this template retain their content snapshot, including scheduled\nmessages.",
        "operationId": "update_template_v1_apps__app_id__templates__tpl_id__patch",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "tpl_id",
            "required": true,
            "schema": {
              "title": "Tpl Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "body": "Welcome back, {{ user.external_id }}."
                  }
                }
              },
              "schema": {
                "additionalProperties": true,
                "properties": {
                  "body": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Replacement body.",
                    "title": "Body"
                  },
                  "data": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Replacement custom payload.",
                    "title": "Data"
                  },
                  "deep_link": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Replacement tap destination.",
                    "title": "Deep Link"
                  },
                  "default_language": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Replacement fallback language.",
                    "title": "Default Language"
                  },
                  "image_url": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Replacement image URL.",
                    "title": "Image Url"
                  },
                  "languages": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Replacement localized content map.",
                    "title": "Languages"
                  },
                  "name": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Replacement display name.",
                    "title": "Name"
                  },
                  "platform_options": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Replacement platform presentation defaults.",
                    "title": "Platform Options"
                  },
                  "title": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Replacement title.",
                    "title": "Title"
                  }
                },
                "title": "TemplateUpdate",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "The template id and confirmation of the update"
          },
          "400": {
            "description": "Nothing to update, data is not an object, an unusable image URL, or invalid Liquid or an unknown dynamic-content table"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "403": {
            "description": "Read-only X-OP-API-Key"
          },
          "404": {
            "description": "Unknown template for this app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Update a template",
        "tags": [
          "Templates & dynamic content"
        ]
      }
    },
    "/v1/apps/{app_id}/test-subscriptions": {
      "get": {
        "description": "The app's test devices with the label each was given. Tokens are truncated\nhere exactly as on the subscriptions list.",
        "operationId": "list_test_subs_v1_apps__app_id__test_subscriptions_get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "The app's test devices"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "List test subscriptions",
        "tags": [
          "Subscriptions & users"
        ]
      },
      "post": {
        "description": "Marks a device as a test device, by `subscription_id` or by `token`. A\ntoken that is not registered yet is registered first, exactly as the SDK would. Calling it\nagain for the same device renames rather than duplicating.\n\n**A test device ignores the frequency cap and quiet hours on every send** — this is a\ndevice-level guard bypass, not a label. Anything quiet hours was holding for this device is\nreleased immediately.",
        "operationId": "add_test_sub_v1_apps__app_id__test_subscriptions_post",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "name": "QA iPhone",
                    "platform": "ios",
                    "token": "test-device-token"
                  }
                }
              },
              "schema": {
                "additionalProperties": true,
                "properties": {
                  "external_id": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "External id used when a new token is registered.",
                    "title": "External Id"
                  },
                  "name": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Human label for the test device.",
                    "title": "Name"
                  },
                  "platform": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Platform used when a new token is registered.",
                    "title": "Platform"
                  },
                  "subscription_id": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Existing subscription id; supply this or token.",
                    "title": "Subscription Id"
                  },
                  "token": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Existing or new push token; supply this or subscription_id.",
                    "title": "Token"
                  }
                },
                "title": "TestSubscriptionCreate",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "The test device's label and subscription id"
          },
          "400": {
            "description": "token or subscription_id required"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "403": {
            "description": "Read-only X-OP-API-Key"
          },
          "404": {
            "description": "Unknown app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Add a test subscription",
        "tags": [
          "Subscriptions & users"
        ]
      }
    },
    "/v1/apps/{app_id}/test-subscriptions/{sub_id}": {
      "delete": {
        "description": "Removes the test-device marking from one subscription. The subscription\nitself is untouched and keeps receiving ordinary sends — what it loses is the cap and\nquiet-hours bypass.",
        "operationId": "del_test_sub_v1_apps__app_id__test_subscriptions__sub_id__delete",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "sub_id",
            "required": true,
            "schema": {
              "title": "Sub Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Confirmation that the marking was removed"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "403": {
            "description": "Read-only X-OP-API-Key"
          },
          "404": {
            "description": "Not a test subscription on this app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Remove a test subscription",
        "tags": [
          "Subscriptions & users"
        ]
      }
    },
    "/v1/apps/{app_id}/users": {
      "get": {
        "description": "Users for one app with their tags, aliases and subscription count.\n`search` matches on external id or tags.\n\n**Two orderings, named.** A bare call returns the newest sessions first, `limit` rows, with\nno cursor — that ordering is not unique or stable, so it cannot be walked. Pass `?order=id`\n(or any `?cursor=`) to switch to a stable keyset walk that emits `next_cursor`. `limit` is\ncapped at 1000, and `total` has always meant the length of *this page*, not of the table.",
        "operationId": "list_users_v1_apps__app_id__users_get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "search",
            "required": false,
            "schema": {
              "default": "",
              "title": "Search",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 100,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "default": "",
              "title": "Cursor",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "order",
            "required": false,
            "schema": {
              "default": "",
              "title": "Order",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "A page of users with paging metadata"
          },
          "400": {
            "description": "Malformed or unreadable cursor"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "403": {
            "description": "The shared sample app is listed from the console only"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "List users",
        "tags": [
          "Subscriptions & users"
        ]
      },
      "post": {
        "operationId": "create_user_admin_v1_apps__app_id__users_post",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "aliases": {
                      "account": "42"
                    },
                    "external_id": "player-42",
                    "subscriptions": [
                      {
                        "consent": true,
                        "platform": "android",
                        "token": "device-token"
                      }
                    ]
                  }
                }
              },
              "schema": {
                "additionalProperties": true,
                "properties": {
                  "aliases": {
                    "anyOf": [
                      {
                        "additionalProperties": {
                          "type": "string"
                        },
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Aliases"
                  },
                  "country": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Country"
                  },
                  "email": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Email"
                  },
                  "external_id": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "External Id"
                  },
                  "language": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Language"
                  },
                  "subscriptions": {
                    "anyOf": [
                      {
                        "items": {
                          "additionalProperties": true,
                          "properties": {
                            "app_version": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ],
                              "title": "App Version"
                            },
                            "consent": {
                              "description": "Explicit current permission or opt-in state.",
                              "title": "Consent",
                              "type": "boolean"
                            },
                            "device_name": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ],
                              "title": "Device Name"
                            },
                            "os_version": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ],
                              "title": "Os Version"
                            },
                            "platform": {
                              "enum": [
                                "ios",
                                "android"
                              ],
                              "title": "Platform",
                              "type": "string"
                            },
                            "sandbox": {
                              "anyOf": [
                                {
                                  "type": "boolean"
                                },
                                {
                                  "type": "null"
                                }
                              ],
                              "description": "iOS sandbox environment only.",
                              "title": "Sandbox"
                            },
                            "sdk_version": {
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "null"
                                }
                              ],
                              "title": "Sdk Version"
                            },
                            "token": {
                              "description": "Push token. Accepted only in a request body.",
                              "title": "Token",
                              "type": "string"
                            }
                          },
                          "required": [
                            "token",
                            "platform",
                            "consent"
                          ],
                          "title": "PushSubscriptionCreate",
                          "type": "object"
                        },
                        "type": "array"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Subscriptions"
                  },
                  "tags": {
                    "anyOf": [
                      {
                        "additionalProperties": true,
                        "type": "object"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Tags"
                  },
                  "timezone": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Timezone"
                  }
                },
                "title": "UserCreate",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "403": {
            "description": "Read-only API key or shared sample app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Create User Admin",
        "tags": [
          "Subscriptions & users"
        ]
      }
    },
    "/v1/apps/{app_id}/users/by-alias/{label}/{value}": {
      "get": {
        "operationId": "user_by_alias_admin_v1_apps__app_id__users_by_alias__label___value__get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "label",
            "required": true,
            "schema": {
              "title": "Label",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "value",
            "required": true,
            "schema": {
              "title": "Value",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "User By Alias Admin",
        "tags": [
          "Subscriptions & users"
        ]
      }
    },
    "/v1/apps/{app_id}/users/by-external-id/{external_id}": {
      "get": {
        "description": "Same profile as `GET /users/{user_id}`, looked up by the app's own external id.",
        "operationId": "user_profile_by_external_id_v1_apps__app_id__users_by_external_id__external_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "external_id",
            "required": true,
            "schema": {
              "title": "External Id",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 25,
              "title": "Limit",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "One user profile with devices and recent deliveries"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "403": {
            "description": "The shared sample app is read from the console only"
          },
          "404": {
            "description": "No user with that external_id"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Read one user by external id",
        "tags": [
          "Subscriptions & users"
        ]
      }
    },
    "/v1/apps/{app_id}/users/{user_id}": {
      "delete": {
        "operationId": "delete_user_admin_v1_apps__app_id__users__user_id__delete",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "user_id",
            "required": true,
            "schema": {
              "title": "User Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "403": {
            "description": "Read-only API key or shared sample app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Delete User Admin",
        "tags": [
          "Subscriptions & users"
        ]
      },
      "get": {
        "description": "Identity, tags, aliases, every device (tokens masked), the sendable device\ncount, and the most recent deliveries across all of this person's devices with their derived\nstate. Answers \"what did this person actually receive?\" — then\n`GET /messages/{message_id}/trace` says why for one message.",
        "operationId": "user_profile_route_v1_apps__app_id__users__user_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "user_id",
            "required": true,
            "schema": {
              "title": "User Id",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 25,
              "title": "Limit",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "One user profile with devices and recent deliveries"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "403": {
            "description": "The shared sample app is read from the console only"
          },
          "404": {
            "description": "Unknown user for this app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Read one user",
        "tags": [
          "Subscriptions & users"
        ]
      },
      "patch": {
        "operationId": "patch_user_admin_v1_apps__app_id__users__user_id__patch",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "user_id",
            "required": true,
            "schema": {
              "title": "User Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "language": "fr"
                  }
                }
              },
              "schema": {
                "additionalProperties": true,
                "properties": {
                  "country": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Country"
                  },
                  "email": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Email"
                  },
                  "language": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Language"
                  },
                  "timezone": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Timezone"
                  }
                },
                "title": "UserUpdate",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "403": {
            "description": "Read-only API key or shared sample app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Patch User Admin",
        "tags": [
          "Subscriptions & users"
        ]
      }
    },
    "/v1/apps/{app_id}/users/{user_id}/aliases": {
      "patch": {
        "description": "Server-side alias writes: `{\"set\": {label: value}, \"delete\": [label]}`. Labels\nfollow the tag charset and the 60-character cap, values are at most 300 characters, and the\nper-user alias cap is the same one the SDK identity call and the CSV importer are held to —\nan eleventh alias is a `400`, not a silent drop.\n\n`external_id` is not an alias: it is set by the SDK identity call, and naming it here is a\n`400`. Returns the resulting alias map.",
        "operationId": "patch_user_aliases_v1_apps__app_id__users__user_id__aliases_patch",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "user_id",
            "required": true,
            "schema": {
              "title": "User Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "delete": [
                      "legacy_id"
                    ],
                    "set": {
                      "crm_id": "CRM-90210",
                      "loyalty_no": "LP-4417"
                    }
                  }
                }
              },
              "schema": {
                "additionalProperties": true,
                "properties": {
                  "delete": {
                    "description": "Alias labels to remove; `external_id` is refused here too. Removing a label the user does not have is not an error. `set` and `delete` together are capped at 100 changes per call.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Delete",
                    "type": "array"
                  },
                  "set": {
                    "additionalProperties": {
                      "type": "string"
                    },
                    "description": "Alias label to id. Labels follow the tag charset — `[A-Za-z0-9_-.]` with no empty segment, at most 60 characters — and an alias needs a value, of at most 300 characters. A label in both `set` and `delete` is set, not deleted. `external_id` is reserved: it is set by the SDK identity call, so naming it here is a 400. An eleventh alias on one user is a 400, not a silent drop.",
                    "title": "Set",
                    "type": "object"
                  }
                },
                "title": "UserAliasesPatch",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "The user's aliases after the change"
          },
          "400": {
            "description": "Reserved label, bad label or value, or the alias cap is reached"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "403": {
            "description": "Read-only key, or the shared sample app"
          },
          "404": {
            "description": "Unknown user for this app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Set or delete user aliases",
        "tags": [
          "Subscriptions & users"
        ]
      }
    },
    "/v1/apps/{app_id}/users/{user_id}/subscriptions": {
      "post": {
        "operationId": "create_subscription_admin_v1_apps__app_id__users__user_id__subscriptions_post",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "user_id",
            "required": true,
            "schema": {
              "title": "User Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "consent": true,
                    "platform": "android",
                    "token": "device-token"
                  }
                }
              },
              "schema": {
                "additionalProperties": true,
                "properties": {
                  "app_version": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "App Version"
                  },
                  "consent": {
                    "description": "Explicit current permission or opt-in state.",
                    "title": "Consent",
                    "type": "boolean"
                  },
                  "device_name": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Device Name"
                  },
                  "os_version": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Os Version"
                  },
                  "platform": {
                    "enum": [
                      "ios",
                      "android"
                    ],
                    "title": "Platform",
                    "type": "string"
                  },
                  "sandbox": {
                    "anyOf": [
                      {
                        "type": "boolean"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "iOS sandbox environment only.",
                    "title": "Sandbox"
                  },
                  "sdk_version": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "title": "Sdk Version"
                  },
                  "token": {
                    "description": "Push token. Accepted only in a request body.",
                    "title": "Token",
                    "type": "string"
                  }
                },
                "required": [
                  "token",
                  "platform",
                  "consent"
                ],
                "title": "PushSubscriptionCreate",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "403": {
            "description": "Read-only API key or shared sample app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Create Subscription Admin",
        "tags": [
          "Subscriptions & users"
        ]
      }
    },
    "/v1/apps/{app_id}/users/{user_id}/tags": {
      "patch": {
        "description": "Server-side tag writes: `{\"set\": {key: value}, \"delete\": [key]}`. Keys are\n`[A-Za-z0-9_-.]` with no empty segment and at most 60 characters, values at most 300, and at\nmost 100 changes per call. `set` wins over `delete` for a key in both; deleting a key the user\ndoes not have is not an error. Returns the resulting tag map.\n\nUntil now only the device SDK could write a tag, which meant a server that knew something about\na person (a purchase, a plan change) had no way to say so. The rules are the console's own —\none enforcement point for the form, this route and the MCP tools.",
        "operationId": "patch_user_tags_v1_apps__app_id__users__user_id__tags_patch",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "user_id",
            "required": true,
            "schema": {
              "title": "User Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "delete": [
                      "trial_expires_at"
                    ],
                    "set": {
                      "last_purchase_at": "2026-09-01",
                      "plan": "pro"
                    }
                  }
                }
              },
              "schema": {
                "additionalProperties": true,
                "properties": {
                  "delete": {
                    "description": "Tag keys to remove. Deleting a key the user does not have is not an error. `set` and `delete` together are capped at 100 changes per call.",
                    "items": {
                      "type": "string"
                    },
                    "title": "Delete",
                    "type": "array"
                  },
                  "set": {
                    "additionalProperties": {
                      "type": "string"
                    },
                    "description": "Tag key to value. Keys are `[A-Za-z0-9_-.]` with no empty segment and at most 60 characters; values are at most 300 characters. A key in both `set` and `delete` is set, not deleted.",
                    "title": "Set",
                    "type": "object"
                  }
                },
                "title": "UserTagsPatch",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "The user's tags after the change"
          },
          "400": {
            "description": "Bad key or value, or more than 100 changes in one call"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-API-Key"
          },
          "403": {
            "description": "Read-only key, or the shared sample app"
          },
          "404": {
            "description": "Unknown user for this app"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "ApiKey": []
          }
        ],
        "summary": "Set or delete user tags",
        "tags": [
          "Subscriptions & users"
        ]
      }
    },
    "/v1/apps/{app_id}/webpush-config": {
      "get": {
        "description": "Everything a browser needs to subscribe to web push for this app: the\n**public** half of the VAPID pair, the browser push configuration, the app's ingest-only SDK\nkey, the site URL, and whether devices on this app need a link code.\n\n**This route is deliberately unauthenticated**, and that list is the whole of what it\npublishes. The service-account JSON and the VAPID private key are never read by it. The\nSDK key it returns can register a device and post a receipt; it can never read an audience,\nsend a push or rotate anything.",
        "operationId": "webpush_config_v1_apps__app_id__webpush_config_get",
        "parameters": [
          {
            "in": "path",
            "name": "app_id",
            "required": true,
            "schema": {
              "title": "App Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "VAPID public key, browser push config, SDK key and site URL"
          },
          "404": {
            "description": "Unknown app, or the app has no web push credential"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Fetch the web push configuration",
        "tags": [
          "Subscriptions & users"
        ]
      }
    },
    "/v1/ingest": {
      "post": {
        "description": "The SDK receipt route. Each item in `events` carries `type`, `app`,\n`message_id` and `token`; `type` is one of `received`, `confirmed`, `clicked`,\n`iam_impression`, `iam_click` or `iam_page_impression`. The SDK key is checked against\n**every** app named in the batch, so receipts can never cross tenants.\n\nThis is a counter, not a validator: it answers `{accepted, dropped}`. A malformed item, an\nunknown message, an unknown token, or a receipt that was already recorded is counted in\n`dropped` rather than failing the request — so a `200` here does not mean every item\nlanded.\n\n`iam_page_impression` is accepted but **no shipping SDK emits it**; do not build a report\non those rows.",
        "operationId": "ingest_v1_ingest_post",
        "parameters": [],
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "default": {
                  "value": {
                    "events": [
                      {
                        "app": "runner-club",
                        "message_id": "msg_9f21c4a70b3d",
                        "surface": "notification",
                        "token": "device-push-token",
                        "type": "confirmed"
                      }
                    ]
                  }
                }
              },
              "schema": {
                "additionalProperties": true,
                "properties": {
                  "events": {
                    "description": "SDK receipt items; invalid items are counted as dropped.",
                    "items": {
                      "additionalProperties": true,
                      "properties": {
                        "app": {
                          "description": "App id; the supplied SDK key must be valid for it.",
                          "title": "App",
                          "type": "string"
                        },
                        "message_id": {
                          "description": "Message id carried in the push or in-app payload.",
                          "title": "Message Id",
                          "type": "string"
                        },
                        "surface": {
                          "anyOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "Free-form analytics label.",
                          "title": "Surface"
                        },
                        "token": {
                          "description": "Registered device push token.",
                          "title": "Token",
                          "type": "string"
                        },
                        "type": {
                          "description": "Receipt stage or in-app engagement event.",
                          "enum": [
                            "received",
                            "confirmed",
                            "clicked",
                            "iam_impression",
                            "iam_click",
                            "iam_page_impression"
                          ],
                          "title": "Type",
                          "type": "string"
                        }
                      },
                      "required": [
                        "type",
                        "app",
                        "message_id",
                        "token"
                      ],
                      "title": "ReceiptEvent",
                      "type": "object"
                    },
                    "title": "Events",
                    "type": "array"
                  }
                },
                "required": [
                  "events"
                ],
                "title": "ReceiptBatch",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Counts of accepted and dropped receipts"
          },
          "401": {
            "description": "Missing, wrong, disabled or wrong-app X-OP-SDK-Key for an app named in the batch"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "SdkKey": []
          }
        ],
        "summary": "Post SDK delivery receipts",
        "tags": [
          "Events & ingest"
        ]
      }
    },
    "/v1/manifest-schema": {
      "get": {
        "description": "Returns the versioned JSON contract produced by `openpush-scan`.\nNo authentication is required; clients may cache this public contract for one hour.",
        "operationId": "manifest_schema_v1_manifest_schema_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "The current OpenPush app manifest JSON Schema"
          }
        },
        "summary": "Read the app manifest schema",
        "tags": [
          "Apps, keys & settings"
        ]
      }
    }
  },
  "servers": [
    {
      "description": "Production",
      "url": "https://app.openpush.ai"
    },
    {
      "description": "Local (uvicorn main:app --port 8080)",
      "url": "http://localhost:8080"
    }
  ],
  "tags": [
    {
      "description": "Unauthenticated liveness and status, so an uptime checker needs no credential. `GET /healthz` returns a capability snapshot (provider readiness, queue depth, row counts); `/status.json` and `/status` render a wider operational picture with every probe wrapped independently.",
      "name": "Health"
    },
    {
      "description": "Create and list apps, read and update per-app settings and platform credentials, and rotate REST and SDK keys. Rotation has no grace window — the old value stops working on the very next request.",
      "name": "Apps, keys & settings"
    },
    {
      "description": "Create, list, read, cancel and promote campaigns, plus `send-test` to registered test devices only. Create is not idempotent: a retried request is a second send.",
      "name": "Messages"
    },
    {
      "description": "The audience — device subscriptions and the users behind them, with external ids, aliases, tags, language and timezone. Registration is an SDK-key route; reading and editing the audience is admin.",
      "name": "Subscriptions & users"
    },
    {
      "description": "Named, reusable filters over user and subscription facts. A segment is resolved at send time, so a campaign reaches the audience as it stands when it goes out.",
      "name": "Segments"
    },
    {
      "description": "Reusable message content with Liquid rendering, and the dynamic-content tables a send looks values up in. Both are resolved per device at send time.",
      "name": "Templates & dynamic content"
    },
    {
      "description": "SDK-key ingest from your apps: sessions, delivery receipts, custom events and the batching `/v1/ingest` route, plus the two admin reads over what arrived — recent events and the event catalogue. Custom events are the only ingest path with a rate limit (500 per app per 5 seconds).",
      "name": "Events & ingest"
    },
    {
      "description": "Multi-step automated flows with their nodes and stats. These are the only routes that reject unknown body keys outright, and the only ones that answer with the structured `{\"errors\": [...]}` envelope.",
      "name": "Journeys"
    },
    {
      "description": "iOS ActivityKit. SDK-key device routes register update and push-to-start tokens, report an end and report a tap; two migration admin routes start, update and end activities across an audience. Those two are the only send path — no native `/v1` route sends a Live Activity.",
      "name": "Live Activities"
    },
    {
      "description": "Messages rendered inside your app rather than by the OS: definitions and their lifecycle actions on the admin side, and the per-subscription fetch the SDK calls.",
      "name": "In-app messages"
    },
    {
      "description": "Daily subscriber and delivery history for one app: a dense series for charting where a missing day is an explicit null rather than a zero, and the same window summed.",
      "name": "Analytics"
    },
    {
      "description": "Bulk audience import with import status reads, and CSV/NDJSON export of the audience. Upload routes carry their own 150 MB body ceiling.",
      "name": "Import & export"
    }
  ]
}
