Appio documentation

Overview

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!

Getting Started

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.

Option 1

Preview

Mobile APP

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>

Appio

service
Use your service ID, which was assigned to you during registration.
Replace svc_**YOUR*SERVICE*ID** with your service id.
eventCallback
optional
Callback function to receive events from Appio. function (type, data)

Appio.open

user
A unique identifier for your user. For security, use a non-sequential, non-predictable string.
Suggestion: Hash the customer’s unique ID and registration date using a function like SHA-256 or MD5.
service
optional
Use your service ID, which was assigned to you during registration.

Option 2

Preview

Mobile APP

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>
data-appio
Activates Appio. The field is required, but its value is optional and can be omitted.
data-service
Use your service ID, which was assigned to you during registration.
Replace svc_**YOUR*SERVICE*ID** with your service id.
data-user
A unique identifier for your user. For security, use a non-sequential, non-predictable string.
Suggestion: Hash the customer’s unique ID and registration date using a function like SHA-256 or MD5.

API Overview

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.

Authentication

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
👋

API Services

View service details

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"
}

API Devices

List devices subscribed to service

Returns a paginated list of devices subscribed to the service.
platform is one of ios, android or watchos.

Pagination parameters

limit
optional
Integer. Default: 50. Min: 1, Max: 100.
Maximum number of items to return.
after
optional
String. Cursor ID for pagination — returns items after this ID.

Path

GET /v1/devices

Request

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"
    }
}

View device details

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 device

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 user devices

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"
    },
    ...
]

API Notifications

Notification request

payload
Notification payload
scheduled_at
optional
String. RFC 3339 format.
Specifies the date and time to schedule the notification for future delivery, up to 30 days in advance. Must be in the future.
Empty value means immediate delivery.

Notification payload

title
String. Max 50 characters.
message
String. Max 200 characters.
link
optional
String. Valid URL.
image_url
optional
String. Image url.
Image dimension ratio 16/9, up to 3MB.
Allowed formats: .gif, .jpg, .png, .webp

Notification status

created
The notification exists but hasn’t been assigned to any devices yet.
queued
All device deliveries exist and are waiting to be sent.
completed
The notification has been processed and no delivery is pending.
failed
The notification could not be processed.
skipped
The notification was not sent out.

Filter options

status
optional
String. Filter notifications by status: created, queued, completed, failed, skipped
device_id
optional
String. Filter notifications for a specific device.
user_id
optional
String. Filter notifications for a specific user.

If both device_id and user_id are provided, only device_id is used.

Pagination parameters

limit
optional
Integer. Default: 50. Min: 1, Max: 100.
Maximum number of items to return.
after
optional
String. Cursor ID for pagination — returns items after this ID.

List notifications

Path

GET /v1/notifications

Request

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"
    }
}

List delivered notifications

Path

GET /v1/notifications?status=completed

Request

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"
    }
}

List notifications for a device

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"
    }
}

List notifications for a user

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 notification details

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
    }
}

Target options

The audience of POST /v1/notifications is chosen by two optional query parameters:

device_id
optional
String. Deliver to that single device.
user_id
optional
String. Deliver to all devices of that user.

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.


Send a notification to all subscribed devices

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/notifications

Request

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"
}

Send a scheduled notification to a user

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"
}

Send a notification to a single device

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"
}

API Errors

400
Bad Request
The request contains invalid or missing data.
Please double-check the API endpoint URL and ensure the request body is correctly formatted and complete.
401
Unauthorized
Authentication is required.
Ensure that a valid access token is included in the request headers.
402
Payment Required
Your organization has no active subscription.
Every endpoint except GET /v1/services/{id} requires one. Subscribe at the URL in data.url of the error response, my.appio.so/pricing.
403
Forbidden
You do not have permission to perform this action.
Check that your account has the necessary permissions or roles for this operation.
404
Not Found
The requested entity doesn't exist.
Verify that the resource identifier is correct, exists, and is currently active.
500
Internal Error
Something went wrong while processing your request.
Try again later or contact support if the issue persists.

Error response

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"
                }
            ]
        }
    }
}
message
String. Human-readable description of the error.
data
optional
Object. Extra context when available, e.g. doc_url, entity, validation_errors, url.

AI Instructions

LLM-friendly content for AI agents is available at /llms.txt.
OpenAPI definition is available at /openapi-v1.yaml.