Appio helps businesses add widgets and notifications to their products, without building or maintaining mobile apps, hiring developers, or dealing with app stores.
Learn more about Appio, try our interactive demo, or explore our case studies.
Found an issue or have feedback? Let us know!
Before getting started, you'll need to create an account and obtain your service_id.
There are two integration options for Appio, both functionally identical.
Preview
Install code
<script src="https://cdn.appio.so/v1/appio.js"></script>
<script>
const appio = Appio({
service: "svc_00dddddd000000ccccccssssss"
})
function mobileApp() {
appio.open({
user: "23d0e9848fe0ad06272dea39a03679ff"
})
}
</script>
<a href="#" onclick="mobileApp()">Mobile APP</a>Preview
Install code
<script src="https://cdn.appio.so/v1/appio.js"></script>
<a
data-appio="on"
data-service="svc_00dddddd000000ccccccssssss"
data-user="23d0e9848fe0ad06272dea39a03679ff"
href="#"
>
Mobile APP
</a>All commands in this documentation are live and ready for testing.
NOTE:
Data is automatically reset every 15 minutes.
This will deactivate the "Appio Docs" service on your device.
All API requests must include an authentication token.
Each registered service is issued a unique authentication token.
You can validate your token by calling the testing endpoint:
Request
curl https://api.appio.so/hi \
-H "Authorization: Bearer docs_g3psUMsuKZ7NGGJvuk1csf47pvJfukz97cS5ZrOuHnY98yhY5A"Response
HTTP Code: 200👋Returns the details of a single service.
The X-Service-Id header must match the {id} path parameter.
Path
GET /v1/services/{id}Request
curl -X GET https://api.appio.so/v1/services/svc_00dddddd000000ccccccssssss \
-H "Authorization: Bearer docs_g3psUMsuKZ7NGGJvuk1csf47pvJfukz97cS5ZrOuHnY98yhY5A" \
-H "X-Service-Id: svc_00dddddd000000ccccccssssss"Response
HTTP Code: 200{
"id": "svc_00dddddd000000ccccccssssss",
"title": "Appio Docs",
"description": "Try out the functionality of Appio by downloading the app.",
"logo_url": "https://cdn.appio.so/app/docs.appio.so/logo.png",
"banner_url": "https://cdn.appio.so/app/docs.appio.so/banner.jpg",
"url": "https://docs.appio.so",
"text_color": "#000000",
"background_color": "#ffffff",
"accent_color": "#0066cc"
}Returns a paginated list of devices subscribed to the service.
platform is one of ios, android or watchos.
Path
GET /v1/devicesRequest
curl -X GET https://api.appio.so/v1/devices \
-H "Authorization: Bearer docs_g3psUMsuKZ7NGGJvuk1csf47pvJfukz97cS5ZrOuHnY98yhY5A" \
-H "X-Service-Id: svc_00dddddd000000ccccccssssss"Response
HTTP Code: 200{
"data": [
{
"id": "dvc_01jmpmh9fvxgyym44sqanjr9hs",
"user_id": "23d0e9848fe0ad06272dea39a03679ff",
"name": "iPhone 13",
"platform": "ios",
"os_version": "18.3",
"model": "iPhone",
"device_token": "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"notifications_enabled": true,
"device_identifier": "iPhone14,5",
"marketing_name": "iPhone 13"
},
...
],
"pagination": {
"next": "https://api.appio.so/v1/devices?after=dvc_01jmpmh9fvxgyym44sqanjr9hs"
}
}Path
GET /v1/devices/{id}Request
curl -X GET https://api.appio.so/v1/devices/dvc_01jmpmh9fvxgyym44sqanjr9hs \
-H "Authorization: Bearer docs_g3psUMsuKZ7NGGJvuk1csf47pvJfukz97cS5ZrOuHnY98yhY5A" \
-H "X-Service-Id: svc_00dddddd000000ccccccssssss"Response
HTTP Code: 200{
"id": "dvc_01jmpmh9fvxgyym44sqanjr9hs",
"user_id": "23d0e9848fe0ad06272dea39a03679ff",
"name": "iPhone 13",
"platform": "ios",
"os_version": "18.3",
"model": "iPhone",
"device_token": "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"notifications_enabled": true,
"device_identifier": "iPhone14,5",
"marketing_name": "iPhone 13"
}Deactivate a device when it should no longer receive notifications or when its associated user has been deactivated.
Path
DELETE /v1/devices/{id}Request
curl -X DELETE https://api.appio.so/v1/devices/dvc_01jmpmh9fvxgyym44sqanjr9hs \
-H "Authorization: Bearer docs_g3psUMsuKZ7NGGJvuk1csf47pvJfukz97cS5ZrOuHnY98yhY5A" \
-H "X-Service-Id: svc_00dddddd000000ccccccssssss"Response
HTTP Code: 200{
"id": "dvc_01jmpmh9fvxgyym44sqanjr9hs"
}Deactivate all of a user’s devices when they should no longer receive notifications or when the user has been deactivated.
Path
DELETE /v1/devices?user_id={user_id}Request
curl -X DELETE https://api.appio.so/v1/devices?user_id=23d0e9848fe0ad06272dea39a03679ff \
-H "Authorization: Bearer docs_g3psUMsuKZ7NGGJvuk1csf47pvJfukz97cS5ZrOuHnY98yhY5A" \
-H "X-Service-Id: svc_00dddddd000000ccccccssssss"Response
HTTP Code: 200[
{
"id": "dvc_01jmpmh9fvxgyym44sqanjr9hs"
},
...
]If both device_id and user_id are provided, only device_id is used.
Path
GET /v1/notificationsRequest
curl -X GET https://api.appio.so/v1/notifications \
-H "Authorization: Bearer docs_g3psUMsuKZ7NGGJvuk1csf47pvJfukz97cS5ZrOuHnY98yhY5A" \
-H "X-Service-Id: svc_00dddddd000000ccccccssssss"Response
HTTP Code: 200{
"data": [
{
"id": "ntf_01jmpmgb6my0s57c960q1s862v",
"service_id": "svc_00dddddd000000ccccccssssss",
"status": "completed",
"payload": {
"link": "https://docs.appio.so",
"title": "Notification",
"message": "Hello from Appio Docs",
"image_url": "https://cdn.appio.so/app/docs.appio.so/banner.jpg"
},
"scheduled_at": "2025-03-24T14:23:37.016526Z"
},
...
],
"pagination": {
"next": "https://api.appio.so/v1/notifications?after=ntf_01jmpmgb6my0s57c960q1s862v"
}
}Path
GET /v1/notifications?status=completedRequest
curl -X GET https://api.appio.so/v1/notifications?status=completed \
-H "Authorization: Bearer docs_g3psUMsuKZ7NGGJvuk1csf47pvJfukz97cS5ZrOuHnY98yhY5A" \
-H "X-Service-Id: svc_00dddddd000000ccccccssssss"Response
HTTP Code: 200{
"data": [
{
"id": "ntf_01jmpmgb6my0s57c960q1s862v",
"service_id": "svc_00dddddd000000ccccccssssss",
"status": "completed",
"payload": {
"link": "https://docs.appio.so",
"title": "Notification",
"message": "Hello from Appio Docs",
"image_url": "https://cdn.appio.so/app/docs.appio.so/banner.jpg"
},
"scheduled_at": "2025-03-24T14:23:37.016526Z"
},
...
],
"pagination": {
"next": "https://api.appio.so/v1/notifications?status=completed&after=ntf_01jmpmgb6my0s57c960q1s862v"
}
}Path
GET /v1/notifications?device_id={device_id}Request
curl -X GET https://api.appio.so/v1/notifications?device_id=dvc_01jmpmh9fvxgyym44sqanjr9hs \
-H "Authorization: Bearer docs_g3psUMsuKZ7NGGJvuk1csf47pvJfukz97cS5ZrOuHnY98yhY5A" \
-H "X-Service-Id: svc_00dddddd000000ccccccssssss"Response
HTTP Code: 200{
"data": [
{
"id": "ntf_01jmpmgb6my0s57c960q1s862v",
"service_id": "svc_00dddddd000000ccccccssssss",
"status": "completed",
"payload": {
"link": "https://docs.appio.so",
"title": "Notification",
"message": "Hello from Appio Docs",
"image_url": "https://cdn.appio.so/app/docs.appio.so/banner.jpg"
},
"scheduled_at": "2025-03-24T14:23:37.016526Z"
},
...
],
"pagination": {
"next": "https://api.appio.so/v1/notifications?device_id=dvc_01jmpmh9fvxgyym44sqanjr9hs&after=ntf_01jmpmgb6my0s57c960q1s862v"
}
}Path
GET /v1/notifications?user_id={user_id}Request
curl -X GET https://api.appio.so/v1/notifications?user_id=23d0e9848fe0ad06272dea39a03679ff \
-H "Authorization: Bearer docs_g3psUMsuKZ7NGGJvuk1csf47pvJfukz97cS5ZrOuHnY98yhY5A" \
-H "X-Service-Id: svc_00dddddd000000ccccccssssss"Response
HTTP Code: 200{
"data": [
{
"id": "ntf_01jmpmgb6my0s57c960q1s862v",
"service_id": "svc_00dddddd000000ccccccssssss",
"status": "completed",
"payload": {
"link": "https://docs.appio.so",
"title": "Notification",
"message": "Hello from Appio Docs",
"image_url": "https://cdn.appio.so/app/docs.appio.so/banner.jpg"
},
"scheduled_at": "2025-03-24T14:23:37.016526Z"
},
...
],
"pagination": {
"next": "https://api.appio.so/v1/notifications?user_id=23d0e9848fe0ad06272dea39a03679ff&after=ntf_01jmpmgb6my0s57c960q1s862v"
}
}View a notification's details, including its sending status.
Each notification may be delivered to multiple devices.
Path
GET /v1/notifications/{id}Request
curl -X GET https://api.appio.so/v1/notifications/ntf_01jmpmgb6my0s57c960q1s862v \
-H "Authorization: Bearer docs_g3psUMsuKZ7NGGJvuk1csf47pvJfukz97cS5ZrOuHnY98yhY5A" \
-H "X-Service-Id: svc_00dddddd000000ccccccssssss"Response
HTTP Code: 200{
"id": "ntf_01jmpmgb6my0s57c960q1s862v",
"service_id": "svc_00dddddd000000ccccccssssss",
"status": "completed",
"payload": {
"link": "https://docs.appio.so",
"title": "Notification",
"message": "Hello from Appio Docs",
"image_url": "https://cdn.appio.so/app/docs.appio.so/banner.jpg"
},
"scheduled_at": "2025-03-24T14:23:37.016526Z",
"delivery_stats": {
"total": 1,
"created": 0,
"queued": 0,
"completed": 1,
"failed": 0,
"skipped": 0
}
}The audience of POST /v1/notifications is chosen by two optional query parameters:
Omitting both sends the notification to every device. This is the default behaviour.
If both are given, device_id is used and user_id is ignored.
Notification is delivered only to eligible devices: devices that are linked to the service, have notifications enabled, and have a push token.
Targeted notification (device_id / user_id) sent to an empty audience returns 404 and creates nothing.
A notification sent to a service with no eligible devices is still created and completes with zero deliveries.
Sent to every eligible device linked to the service.
A broadcast is fanned out by the queueing cron, which does not pick the notification up before scheduled_at has passed. Until then it reports status: created and has no deliveries; it becomes queued once every per-device delivery exists.
Path
POST /v1/notificationsRequest
curl -X POST https://api.appio.so/v1/notifications \
-H "Authorization: Bearer docs_g3psUMsuKZ7NGGJvuk1csf47pvJfukz97cS5ZrOuHnY98yhY5A" \
-H "Content-Type: application/json" \
-H "X-Service-Id: svc_00dddddd000000ccccccssssss" \
-d '{"payload":{"title":"Notification","message":"Hello from Appio Docs"}}'Request body
{
"payload": {
"title": "Notification",
"message": "Hello from Appio Docs"
}
}Response
HTTP Code: 201{
"id": "ntf_01jv7938vhvsccakmeq7c1hcy8"
}Sends a notification to all eligible devices belonging to this user.
Returns 404, and creates nothing, if the user is unknown to the service or none of their devices can receive a push.
The per-device deliveries are created immediately, so the notification reports status: queued from creation onwards; the deliveries are simply held back until scheduled_at.
Path
POST /v1/notifications?user_id={user_id}Request
curl -X POST https://api.appio.so/v1/notifications?user_id=23d0e9848fe0ad06272dea39a03679ff \
-H "Authorization: Bearer docs_g3psUMsuKZ7NGGJvuk1csf47pvJfukz97cS5ZrOuHnY98yhY5A" \
-H "Content-Type: application/json" \
-H "X-Service-Id: svc_00dddddd000000ccccccssssss" \
-d '{"payload":{"title":"Notification","message":"Hello from Appio Docs"},"scheduled_at":""}'Request body
{
"payload": {
"title": "Notification",
"message": "Hello from Appio Docs"
},
"scheduled_at": ""
}Response
HTTP Code: 201{
"id": "ntf_01jv7akwwbj47rf3je11jgpvvf"
}Sends a notification to one device.
Returns 404, and creates nothing, if the device is unknown to the service or cannot receive a push (notifications disabled, no push token).
The delivery is created immediately, so the notification reports status: queued from creation onwards.
Path
POST /v1/notifications?device_id={device_id}Request
curl -X POST https://api.appio.so/v1/notifications?device_id=dvc_01jmpmh9fvxgyym44sqanjr9hs \
-H "Authorization: Bearer docs_g3psUMsuKZ7NGGJvuk1csf47pvJfukz97cS5ZrOuHnY98yhY5A" \
-H "Content-Type: application/json" \
-H "X-Service-Id: svc_00dddddd000000ccccccssssss" \
-d '{"payload":{"title":"Notification","message":"Hello from Appio Docs"}}'Request body
{
"payload": {
"title": "Notification",
"message": "Hello from Appio Docs"
}
}Response
HTTP Code: 201{
"id": "ntf_01jmpmgb6my0s57c960q1s862v"
}GET /v1/services/{id} requires one. Subscribe at the URL in data.url of the error response, my.appio.so/pricing.Every error uses the same body shape.
{
"error": {
"message": "Invalid input data",
"data": {
"doc_url": "https://docs.appio.so/#api-services",
"entity": "service",
"validation_errors": [
{
"field": "title",
"reason": "title is required"
}
]
}
}
}LLM-friendly content for AI agents is available at /llms.txt.
OpenAPI definition is available at /openapi-v1.yaml.