API reference

Push

Send push notifications through APNs and FCM with your own credentials.

get/v1/push/apps

List push apps

Requires push:r.

Parameters

ParameterTypeDescription
limitquerystring

1 to 100. Default 50.

cursorquerystring

next_cursor from the previous page.

Responses

  • 200A page of push apps, newest first.
    FieldTypeDescription
    data[]requiredobject[]
    idrequiredstring

    papp_…

    namerequiredstring
    apnsrequiredobject

    The APNs key's identifiers and health. The key itself is never returned. Null when the app has no APNs key.

    • Can be null
    key_idrequiredstring
    • Can be null
    team_idrequiredstring
    • Can be null
    bundle_idrequiredstring
    • Can be null
    sandbox_statusrequiredstring

    The key against the APNs sandbox: valid once a send or check succeeds, invalid once Apple rejects the key itself.

    • One of: unverified | valid | invalid
    production_statusrequiredstring

    The key against APNs production.

    • One of: unverified | valid | invalid
    sandbox_coveredrequiredboolean

    Whether the key covered the sandbox at upload (verified valid, or Apple could not be asked). An uncovered environment's invalid is the key's scope, not a fault.

    production_coveredrequiredboolean

    Whether the key covered production at upload.

    fcmrequiredobject

    The FCM service account's project and health. The service account itself is never returned. Null when the app has none.

    • Can be null
    project_idrequiredstring
    • Can be null
    statusrequiredstring

    The service account against FCM.

    • One of: unverified | valid | invalid
    webrequiredobject

    Web push: the app's VAPID key pair, generated with the app or imported. The private key is never returned. Null for an app made before web push that has no pair yet.

    • Can be null
    vapid_public_keyrequiredstring

    The VAPID public key (P-256, uncompressed, base64url): pass it to pushManager.subscribe() as applicationServerKey.

    subjectrequiredstring

    The contact set for browser push services (VAPID subject): https://honkio.ca by default, or a mailto: of the account's verified email, or a mailto: address or https: URL on one of its verified sending domains. A push goes out with the default while the set one no longer qualifies (its domain was removed or lapsed).

    importedrequiredboolean

    True when you imported the pair, false when HonkIO generated it.

    created_atrequiredstring

    When the pair was generated or imported.

    • Format: date-time
    • Can be null
    require_encryptionrequiredboolean

    True: every iOS and Android delivery is encrypted to the device's own key, and a device registered without encryption_public_key is refused (ENCRYPTION_KEY_MISSING), never sent in plaintext and never charged. Browsers (web) are never refused for it: web push is always encrypted to the browser (RFC 8291). False: devices with a key get encrypted pushes, the rest plaintext.

    placeholder_titlerequiredstring

    The title Apple and Google see on an encrypted push, shown if the device cannot decrypt it.

    • Can be null
    placeholder_bodyrequiredstring

    The body Apple and Google see on an encrypted push, shown if the device cannot decrypt it.

    • Can be null
    created_atrequiredstring
    • Format: date-time
    has_morerequiredboolean
    next_cursorrequiredstring

    Pass it as cursor for the next page. Null on the last page.

    • Can be null
  • 401Missing, invalid, revoked or expired API key.The standard error body.
  • 402The account has no balance, or a LIVE key was used before the first top-up.The standard error body.
  • 403The API key lacks the permission this operation requires, or the account is suspended or closed.The standard error body.
  • 429Rate limit reached: 100 requests per second per account, or a route-specific limit (Retry-After set where one applies).The standard error body.
  • 500Unexpected server error.The standard error body.

Example

const { data, error } = await honkio.push.apps.list({ limit: 20 })
if (error) throw new Error(error.message)
for (const app of data.data) console.log(app.id, app.name)
post/v1/push/apps

Create a push app

Requires push:w.

Request body

A name, and an APNs key, an FCM service account or both (either can be added later with PATCH).

FieldTypeDescription
namerequiredstring

Your name for the app, up to 100 characters, with no link in it.

  • At least 1 characters
  • At most 100 characters
apnsobject

The APNs .p8 key (EC P-256, as Apple issues it) with its key_id, team_id and bundle_id. Checked against the sandbox and production before it is saved; never returned.

key_p8requiredstring

The .p8 file's contents, BEGIN and END lines included.

  • At least 1 characters
  • At most 8192 characters
key_idrequiredstring

The 10-character Key ID Apple shows for the key.

  • At least 1 characters
  • At most 32 characters
team_idrequiredstring

Your Apple Developer Team ID.

  • At least 1 characters
  • At most 32 characters
bundle_idrequiredstring

The app's bundle identifier, sent as apns-topic.

  • At least 1 characters
  • At most 255 characters
fcmobject

The Firebase service account that sends for the app. Checked with Google before it is saved; never returned.

service_account_jsonrequiredstring

The service account's JSON key file, as a string.

  • At least 1 characters
  • At most 20000 characters
placeholder_titlestring

The title Apple and Google see on an encrypted push, shown if the device cannot decrypt it.

  • At most 200 characters
placeholder_bodystring

The body Apple and Google see on an encrypted push, shown if the device cannot decrypt it.

  • At most 500 characters
require_encryptionboolean

True refuses any iOS or Android delivery that cannot be encrypted: a device registered without encryption_public_key is skipped with ENCRYPTION_KEY_MISSING, never sent in plaintext and never charged. False (the default) encrypts for each device that has a key and sends plaintext to the rest. Browsers (web) are never refused for it: web push is always encrypted to the browser (RFC 8291) and needs no device key. It applies to pushes already scheduled or queued too. A dashboard session turning it off steps up first.

Responses

  • 201The app, with each credential's status.
    FieldTypeDescription
    idrequiredstring

    papp_…

    namerequiredstring
    apnsrequiredobject

    The APNs key's identifiers and health. The key itself is never returned. Null when the app has no APNs key.

    • Can be null
    key_idrequiredstring
    • Can be null
    team_idrequiredstring
    • Can be null
    bundle_idrequiredstring
    • Can be null
    sandbox_statusrequiredstring

    The key against the APNs sandbox: valid once a send or check succeeds, invalid once Apple rejects the key itself.

    • One of: unverified | valid | invalid
    production_statusrequiredstring

    The key against APNs production.

    • One of: unverified | valid | invalid
    sandbox_coveredrequiredboolean

    Whether the key covered the sandbox at upload (verified valid, or Apple could not be asked). An uncovered environment's invalid is the key's scope, not a fault.

    production_coveredrequiredboolean

    Whether the key covered production at upload.

    fcmrequiredobject

    The FCM service account's project and health. The service account itself is never returned. Null when the app has none.

    • Can be null
    project_idrequiredstring
    • Can be null
    statusrequiredstring

    The service account against FCM.

    • One of: unverified | valid | invalid
    webrequiredobject

    Web push: the app's VAPID key pair, generated with the app or imported. The private key is never returned. Null for an app made before web push that has no pair yet.

    • Can be null
    vapid_public_keyrequiredstring

    The VAPID public key (P-256, uncompressed, base64url): pass it to pushManager.subscribe() as applicationServerKey.

    subjectrequiredstring

    The contact set for browser push services (VAPID subject): https://honkio.ca by default, or a mailto: of the account's verified email, or a mailto: address or https: URL on one of its verified sending domains. A push goes out with the default while the set one no longer qualifies (its domain was removed or lapsed).

    importedrequiredboolean

    True when you imported the pair, false when HonkIO generated it.

    created_atrequiredstring

    When the pair was generated or imported.

    • Format: date-time
    • Can be null
    require_encryptionrequiredboolean

    True: every iOS and Android delivery is encrypted to the device's own key, and a device registered without encryption_public_key is refused (ENCRYPTION_KEY_MISSING), never sent in plaintext and never charged. Browsers (web) are never refused for it: web push is always encrypted to the browser (RFC 8291). False: devices with a key get encrypted pushes, the rest plaintext.

    placeholder_titlerequiredstring

    The title Apple and Google see on an encrypted push, shown if the device cannot decrypt it.

    • Can be null
    placeholder_bodyrequiredstring

    The body Apple and Google see on an encrypted push, shown if the device cannot decrypt it.

    • Can be null
    created_atrequiredstring
    • Format: date-time
  • 401Missing, invalid, revoked or expired API key.The standard error body.
  • 402The account has no balance, or a LIVE key was used before the first top-up.The standard error body.
  • 403LIVE_KEY_REQUIRED: a push app is shared by test and live traffic, so a test key can read apps and register test devices but not create, change or delete them. Also FORBIDDEN when the key lacks the permission this operation requires, or the account is suspended or closed.The standard error body.
  • 409DPA_PUSH_ACCEPTANCE_REQUIRED: the account accepted the data processing agreement before it covered push notifications. Accept the current version in the dashboard (Settings, Data processing agreement) first. An account that never accepted the agreement is not asked.The standard error body.
  • 422PUSH_CREDENTIAL_INVALID: Apple or Google rejected the credential (details carry provider, environment and reason), or VALIDATION_ERROR.The standard error body.
  • 429RATE_LIMITED: at most 20 credential uploads and changes an hour per account (creating an app, or a PATCH that carries apns or fcm). Retry-After says when.The standard error body.
  • 500Unexpected server error.The standard error body.
  • 503PUSH_PROVIDER_UNAVAILABLE: Apple or Google could not be reached to check the credential; nothing was saved. Try again shortly.The standard error body.

Example

const { data: pushApp, error } = await honkio.push.apps.create({
  name: 'Acme mobile',
  apns: {
    keyP8: process.env.APNS_KEY_P8 ?? '',
    keyId: 'ABC123DEFG',
    teamId: 'TEAM123456',
    bundleId: 'ca.acme.app',
  },
  fcm: { serviceAccountJson: process.env.FCM_SERVICE_ACCOUNT_JSON ?? '' },
})
if (error) throw new Error(error.message)
console.log(pushApp.id)
get/v1/push/apps/{id}

Get a push app

Requires push:r.

Parameters

ParameterTypeDescription
idrequiredpathstring

Responses

  • 200The app.
    FieldTypeDescription
    idrequiredstring

    papp_…

    namerequiredstring
    apnsrequiredobject

    The APNs key's identifiers and health. The key itself is never returned. Null when the app has no APNs key.

    • Can be null
    key_idrequiredstring
    • Can be null
    team_idrequiredstring
    • Can be null
    bundle_idrequiredstring
    • Can be null
    sandbox_statusrequiredstring

    The key against the APNs sandbox: valid once a send or check succeeds, invalid once Apple rejects the key itself.

    • One of: unverified | valid | invalid
    production_statusrequiredstring

    The key against APNs production.

    • One of: unverified | valid | invalid
    sandbox_coveredrequiredboolean

    Whether the key covered the sandbox at upload (verified valid, or Apple could not be asked). An uncovered environment's invalid is the key's scope, not a fault.

    production_coveredrequiredboolean

    Whether the key covered production at upload.

    fcmrequiredobject

    The FCM service account's project and health. The service account itself is never returned. Null when the app has none.

    • Can be null
    project_idrequiredstring
    • Can be null
    statusrequiredstring

    The service account against FCM.

    • One of: unverified | valid | invalid
    webrequiredobject

    Web push: the app's VAPID key pair, generated with the app or imported. The private key is never returned. Null for an app made before web push that has no pair yet.

    • Can be null
    vapid_public_keyrequiredstring

    The VAPID public key (P-256, uncompressed, base64url): pass it to pushManager.subscribe() as applicationServerKey.

    subjectrequiredstring

    The contact set for browser push services (VAPID subject): https://honkio.ca by default, or a mailto: of the account's verified email, or a mailto: address or https: URL on one of its verified sending domains. A push goes out with the default while the set one no longer qualifies (its domain was removed or lapsed).

    importedrequiredboolean

    True when you imported the pair, false when HonkIO generated it.

    created_atrequiredstring

    When the pair was generated or imported.

    • Format: date-time
    • Can be null
    require_encryptionrequiredboolean

    True: every iOS and Android delivery is encrypted to the device's own key, and a device registered without encryption_public_key is refused (ENCRYPTION_KEY_MISSING), never sent in plaintext and never charged. Browsers (web) are never refused for it: web push is always encrypted to the browser (RFC 8291). False: devices with a key get encrypted pushes, the rest plaintext.

    placeholder_titlerequiredstring

    The title Apple and Google see on an encrypted push, shown if the device cannot decrypt it.

    • Can be null
    placeholder_bodyrequiredstring

    The body Apple and Google see on an encrypted push, shown if the device cannot decrypt it.

    • Can be null
    created_atrequiredstring
    • Format: date-time
  • 401Missing, invalid, revoked or expired API key.The standard error body.
  • 402The account has no balance, or a LIVE key was used before the first top-up.The standard error body.
  • 403The API key lacks the permission this operation requires, or the account is suspended or closed.The standard error body.
  • 404PUSH_APP_NOT_FOUND: no push app with that id on this account.The standard error body.
  • 429Rate limit reached: 100 requests per second per account, or a route-specific limit (Retry-After set where one applies).The standard error body.
  • 500Unexpected server error.The standard error body.

Example

const { data: pushApp, error } = await honkio.push.apps.get('APP_ID')
if (error) throw new Error(error.message)
console.log(pushApp.name, pushApp.apns?.sandbox_status, pushApp.fcm?.status)
patch/v1/push/apps/{id}

Update a push app

Requires push:m.

Parameters

ParameterTypeDescription
idrequiredpathstring

Request body

The fields to change. An apns or fcm block replaces that credential whole and is checked again.

FieldTypeDescription
namestring

Your name for the app, up to 100 characters, with no link in it.

  • At least 1 characters
  • At most 100 characters
apnsobject

The APNs .p8 key (EC P-256, as Apple issues it) with its key_id, team_id and bundle_id. Checked against the sandbox and production before it is saved; never returned.

key_p8requiredstring

The .p8 file's contents, BEGIN and END lines included.

  • At least 1 characters
  • At most 8192 characters
key_idrequiredstring

The 10-character Key ID Apple shows for the key.

  • At least 1 characters
  • At most 32 characters
team_idrequiredstring

Your Apple Developer Team ID.

  • At least 1 characters
  • At most 32 characters
bundle_idrequiredstring

The app's bundle identifier, sent as apns-topic.

  • At least 1 characters
  • At most 255 characters
fcmobject

The Firebase service account that sends for the app. Checked with Google before it is saved; never returned.

service_account_jsonrequiredstring

The service account's JSON key file, as a string.

  • At least 1 characters
  • At most 20000 characters
placeholder_titlestring

The title Apple and Google see on an encrypted push, shown if the device cannot decrypt it. Null clears it.

  • At most 200 characters
  • Can be null
placeholder_bodystring

The body Apple and Google see on an encrypted push, shown if the device cannot decrypt it. Null clears it.

  • At most 500 characters
  • Can be null
web_push_subjectstring

The contact sent to browser push services with each web push (VAPID subject): a mailto: of the account's verified email, or a mailto: address or https: URL on one of your verified sending domains (or a name under one); anything else is 422 VALIDATION_ERROR. Null goes back to the default, https://honkio.ca. If the domain stops being verified, pushes go out with the default until it is again. The key pair stays, so no browser has to subscribe again.

  • At least 1 characters
  • At most 255 characters
  • Can be null
require_encryptionboolean

True refuses any iOS or Android delivery that cannot be encrypted: a device registered without encryption_public_key is skipped with ENCRYPTION_KEY_MISSING, never sent in plaintext and never charged. False (the default) encrypts for each device that has a key and sends plaintext to the rest. Browsers (web) are never refused for it: web push is always encrypted to the browser (RFC 8291) and needs no device key. It applies to pushes already scheduled or queued too. A dashboard session turning it off steps up first.

Responses

  • 200The updated app.
    FieldTypeDescription
    idrequiredstring

    papp_…

    namerequiredstring
    apnsrequiredobject

    The APNs key's identifiers and health. The key itself is never returned. Null when the app has no APNs key.

    • Can be null
    key_idrequiredstring
    • Can be null
    team_idrequiredstring
    • Can be null
    bundle_idrequiredstring
    • Can be null
    sandbox_statusrequiredstring

    The key against the APNs sandbox: valid once a send or check succeeds, invalid once Apple rejects the key itself.

    • One of: unverified | valid | invalid
    production_statusrequiredstring

    The key against APNs production.

    • One of: unverified | valid | invalid
    sandbox_coveredrequiredboolean

    Whether the key covered the sandbox at upload (verified valid, or Apple could not be asked). An uncovered environment's invalid is the key's scope, not a fault.

    production_coveredrequiredboolean

    Whether the key covered production at upload.

    fcmrequiredobject

    The FCM service account's project and health. The service account itself is never returned. Null when the app has none.

    • Can be null
    project_idrequiredstring
    • Can be null
    statusrequiredstring

    The service account against FCM.

    • One of: unverified | valid | invalid
    webrequiredobject

    Web push: the app's VAPID key pair, generated with the app or imported. The private key is never returned. Null for an app made before web push that has no pair yet.

    • Can be null
    vapid_public_keyrequiredstring

    The VAPID public key (P-256, uncompressed, base64url): pass it to pushManager.subscribe() as applicationServerKey.

    subjectrequiredstring

    The contact set for browser push services (VAPID subject): https://honkio.ca by default, or a mailto: of the account's verified email, or a mailto: address or https: URL on one of its verified sending domains. A push goes out with the default while the set one no longer qualifies (its domain was removed or lapsed).

    importedrequiredboolean

    True when you imported the pair, false when HonkIO generated it.

    created_atrequiredstring

    When the pair was generated or imported.

    • Format: date-time
    • Can be null
    require_encryptionrequiredboolean

    True: every iOS and Android delivery is encrypted to the device's own key, and a device registered without encryption_public_key is refused (ENCRYPTION_KEY_MISSING), never sent in plaintext and never charged. Browsers (web) are never refused for it: web push is always encrypted to the browser (RFC 8291). False: devices with a key get encrypted pushes, the rest plaintext.

    placeholder_titlerequiredstring

    The title Apple and Google see on an encrypted push, shown if the device cannot decrypt it.

    • Can be null
    placeholder_bodyrequiredstring

    The body Apple and Google see on an encrypted push, shown if the device cannot decrypt it.

    • Can be null
    created_atrequiredstring
    • Format: date-time
  • 401Missing, invalid, revoked or expired API key.The standard error body.
  • 402The account has no balance, or a LIVE key was used before the first top-up.The standard error body.
  • 403LIVE_KEY_REQUIRED for a test key; STEP_UP_REQUIRED when a dashboard session turns require_encryption off without an api_keys:elevate step-up; FORBIDDEN when the key lacks push modify permission, or the account is suspended or closed.The standard error body.
  • 404PUSH_APP_NOT_FOUND: no push app with that id on this account.The standard error body.
  • 422PUSH_CREDENTIAL_INVALID: Apple or Google rejected the credential (details carry provider, environment and reason), or VALIDATION_ERROR (including a web_push_subject that is not the account's own: its verified email, or on one of its verified sending domains).The standard error body.
  • 429RATE_LIMITED: at most 20 credential uploads and changes an hour per account (creating an app, or a PATCH that carries apns or fcm). Retry-After says when.The standard error body.
  • 500Unexpected server error.The standard error body.
  • 503PUSH_PROVIDER_UNAVAILABLE: Apple or Google could not be reached to check the credential; nothing was saved. Try again shortly.The standard error body.

Example

// requireEncryption: refuse (and never charge) a device that registered no encryption key.
const { error } = await honkio.push.apps.update('APP_ID', { name: 'Acme mobile (prod)', requireEncryption: true })
if (error) throw new Error(error.message)
delete/v1/push/apps/{id}

Delete a push app

Requires push:d.

Parameters

ParameterTypeDescription
idrequiredpathstring

Responses

  • 204Deleted.
  • 401Missing, invalid, revoked or expired API key.The standard error body.
  • 402The account has no balance, or a LIVE key was used before the first top-up.The standard error body.
  • 403LIVE_KEY_REQUIRED: a push app is shared by test and live traffic, so a test key can read apps and register test devices but not create, change or delete them. Also FORBIDDEN when the key lacks the permission this operation requires, or the account is suspended or closed.The standard error body.
  • 404PUSH_APP_NOT_FOUND: no push app with that id on this account.The standard error body.
  • 429Rate limit reached: 100 requests per second per account, or a route-specific limit (Retry-After set where one applies).The standard error body.
  • 500Unexpected server error.The standard error body.

Example

const { error } = await honkio.push.apps.delete('APP_ID')
if (error) throw new Error(error.message)
post/v1/push/apps/{id}/web/vapid-keys

Generate or import the web push key pair

Requires push:m.

Parameters

ParameterTypeDescription
idrequiredpathstring

Request body

Replace the app's web push (VAPID) key pair: send nothing to generate a new one, or both keys to import your own. A new public key retires every browser registered on the app, in both modes (push_device.deactivated, reason VAPID_KEY_REPLACED), until it subscribes again; importing the pair already in place retires none.

FieldTypeDescription
public_keystring

To import: the P-256 public key, uncompressed, base64url (the applicationServerKey your site subscribed with).

  • At least 1 characters
  • At most 200 characters
private_keystring

To import: the matching 32-byte private key, base64url. Encrypted at rest and never returned.

  • At least 1 characters
  • At most 100 characters
subjectstring

The VAPID subject, as web_push_subject on PATCH: a mailto: of the account's verified email, or a mailto: address or https: URL on one of your verified sending domains. Left out keeps the current one; null goes back to the default.

  • At least 1 characters
  • At most 255 characters
  • Can be null

Responses

  • 200The app, with its new web push public key (web.vapid_public_key). The private key is never returned. When the public key changed, every browser registered on the app (both modes) was retired with VAPID_KEY_REPLACED, and one push_app.vapid_key_replaced webhook reports how many in each mode (no push_device.deactivated per browser).
    FieldTypeDescription
    idrequiredstring

    papp_…

    namerequiredstring
    apnsrequiredobject

    The APNs key's identifiers and health. The key itself is never returned. Null when the app has no APNs key.

    • Can be null
    key_idrequiredstring
    • Can be null
    team_idrequiredstring
    • Can be null
    bundle_idrequiredstring
    • Can be null
    sandbox_statusrequiredstring

    The key against the APNs sandbox: valid once a send or check succeeds, invalid once Apple rejects the key itself.

    • One of: unverified | valid | invalid
    production_statusrequiredstring

    The key against APNs production.

    • One of: unverified | valid | invalid
    sandbox_coveredrequiredboolean

    Whether the key covered the sandbox at upload (verified valid, or Apple could not be asked). An uncovered environment's invalid is the key's scope, not a fault.

    production_coveredrequiredboolean

    Whether the key covered production at upload.

    fcmrequiredobject

    The FCM service account's project and health. The service account itself is never returned. Null when the app has none.

    • Can be null
    project_idrequiredstring
    • Can be null
    statusrequiredstring

    The service account against FCM.

    • One of: unverified | valid | invalid
    webrequiredobject

    Web push: the app's VAPID key pair, generated with the app or imported. The private key is never returned. Null for an app made before web push that has no pair yet.

    • Can be null
    vapid_public_keyrequiredstring

    The VAPID public key (P-256, uncompressed, base64url): pass it to pushManager.subscribe() as applicationServerKey.

    subjectrequiredstring

    The contact set for browser push services (VAPID subject): https://honkio.ca by default, or a mailto: of the account's verified email, or a mailto: address or https: URL on one of its verified sending domains. A push goes out with the default while the set one no longer qualifies (its domain was removed or lapsed).

    importedrequiredboolean

    True when you imported the pair, false when HonkIO generated it.

    created_atrequiredstring

    When the pair was generated or imported.

    • Format: date-time
    • Can be null
    require_encryptionrequiredboolean

    True: every iOS and Android delivery is encrypted to the device's own key, and a device registered without encryption_public_key is refused (ENCRYPTION_KEY_MISSING), never sent in plaintext and never charged. Browsers (web) are never refused for it: web push is always encrypted to the browser (RFC 8291). False: devices with a key get encrypted pushes, the rest plaintext.

    placeholder_titlerequiredstring

    The title Apple and Google see on an encrypted push, shown if the device cannot decrypt it.

    • Can be null
    placeholder_bodyrequiredstring

    The body Apple and Google see on an encrypted push, shown if the device cannot decrypt it.

    • Can be null
    created_atrequiredstring
    • Format: date-time
  • 401Missing, invalid, revoked or expired API key.The standard error body.
  • 402The account has no balance, or a LIVE key was used before the first top-up.The standard error body.
  • 403LIVE_KEY_REQUIRED for a test key; STEP_UP_REQUIRED for a dashboard session without an api_keys:elevate step-up; FORBIDDEN when the key lacks push modify permission, or the account is suspended or closed.The standard error body.
  • 404PUSH_APP_NOT_FOUND: no push app with that id on this account.The standard error body.
  • 422VALIDATION_ERROR: only one of the two keys, a key not on P-256, a private key that does not match the public key, or a subject that is not an https: URL or a mailto: address, or not the account's own (its verified email, or on one of its verified sending domains).The standard error body.
  • 429RATE_LIMITED: at most 20 credential uploads and changes an hour per account (creating an app, or a PATCH that carries apns or fcm). Retry-After says when.The standard error body.
  • 500Unexpected server error.The standard error body.

Example

// No keys: generate a new pair. Both keys: import yours.
const { data: pushApp, error } = await honkio.push.web.setVapidKeys('APP_ID')
if (error) throw new Error(error.message)
console.log(pushApp.web?.vapid_public_key)
get/v1/push/devices

List registered devices

Requires push:r.

Parameters

ParameterTypeDescription
app_idquerystring
user_idquerystring
activequerystring

true or false.

limitquerystring

1 to 100. Default 50.

cursorquerystring

next_cursor from the previous page.

Responses

  • 200A page of devices in the calling key's mode, newest first.
    FieldTypeDescription
    data[]requiredobject[]
    idrequiredstring

    pdev_…

    app_idrequiredstring
    user_idrequiredstring

    Your own id for the person.

    platformrequiredstring

    web is a browser's push subscription.

    • One of: ios | android | web
    apns_environmentrequiredstring

    The APNs environment of an iOS device; null for Android and web.

    • One of: sandbox | production
    • Can be null
    encryption_key_idrequiredstring

    The id of the encryption key the device registered (the first 16 characters of base64url(SHA-256(public key))), sent as kid in each push encrypted to it. Null when it registered none, and always null for web. The key itself is never returned.

    • Can be null
    activerequiredboolean

    False once the device was retired; a retired device is never sent to.

    deactivated_reasonrequiredstring

    Why it was retired: UNREGISTERED or INVALID_TOKEN (Apple or Google; INVALID_TOKEN too for a browser subscription its push service no longer knows, or that HonkIO can no longer read), APP_MISMATCH (a token for another app, on a credential that has worked), DEVICE_LIMIT (the per-user limit), APP_DELETED (its app was deleted), VAPID_KEY_REPLACED (a browser, when the app's web push key pair was replaced), VAPID_KEY_MISMATCH (a browser whose push service refused the app's key five times in a row over at least a day), DUPLICATE (a second row for the same browser subscription, left by an encryption key rotation; the other row stays active), DELETED (you unregistered it) or RECIPIENT_DELETED (you deleted the recipient profile for its user_id). Null while active.

    • Can be null
    last_seen_atrequiredstring

    When the token was last registered.

    • Format: date-time
    created_atrequiredstring
    • Format: date-time
    has_morerequiredboolean
    next_cursorrequiredstring

    Pass it as cursor for the next page. Null on the last page.

    • Can be null
  • 401Missing, invalid, revoked or expired API key.The standard error body.
  • 402The account has no balance, or a LIVE key was used before the first top-up.The standard error body.
  • 403The API key lacks the permission this operation requires, or the account is suspended or closed.The standard error body.
  • 429Rate limit reached: 100 requests per second per account, or a route-specific limit (Retry-After set where one applies).The standard error body.
  • 500Unexpected server error.The standard error body.

Example

const { data, error } = await honkio.push.devices.list({ userId: 'user_1042' })
if (error) throw new Error(error.message)
for (const device of data.data) console.log(device.id, device.platform, device.active)
put/v1/push/devices

Register a device token

Requires push_devices:w.

Request body

A device token, or a browser's push subscription, for one of your users. Registering a known token or subscription refreshes it, and moves it to user_id if that changed.

FieldTypeDescription
app_idrequiredstring

The push app the device belongs to.

  • At least 1 characters
  • At most 100 characters
tokenstring

The APNs or FCM device token, as the platform gives it to your app. Required for iOS and Android; not sent for web.

  • At least 1 characters
  • At most 512 characters
platformrequiredstring

ios, android or web.

  • One of: ios | android | web
user_idrequiredstring

Your own id for the person, up to 255 characters. A send to this user_id reaches each of their active devices and browsers.

  • At least 1 characters
  • At most 255 characters
apns_environmentstring

sandbox or production, required for iOS: the APNs environment the build registered with (debug builds use the sandbox).

  • One of: sandbox | production
subscriptionobject

Web only, and required there: the browser's PushSubscription as its toJSON() gives it. The endpoint must be a browser push service (Google, Mozilla, Apple or Microsoft) over HTTPS.

endpointrequiredstring

The push service URL the browser was given.

  • At least 1 characters
  • At most 2048 characters
expirationTimenumber

As the browser gives it; not stored.

  • Can be null
keysrequiredobject

The browser's keys the payload is encrypted to (RFC 8291).

p256dhrequiredstring

The browser's P-256 public key, base64url.

  • At least 1 characters
  • At most 200 characters
authrequiredstring

The 16-byte auth secret, base64url.

  • At least 1 characters
  • At most 100 characters
encryption_public_keystring

iOS and Android only (refused for web: web push is already encrypted to the browser, RFC 8291, and needs no device key). The public key the HonkIO push package generated on the device: base64url (no padding) of the 65-byte uncompressed P-256 point. Pushes to this device are then encrypted to it, so Apple and Google never see their content. Devices are matched by token: registering the same token again without this field keeps its stored key, but a new token (an APNs or FCM token refresh) is a new device with no key, so send the key with every token (the packages give it with the token). A new key replaces the old one. null removes it: on an app with require_encryption the device then gets no pushes until it registers a key again; without require_encryption its pushes go in plaintext, which is why require_encryption is the guard against a key being removed.

  • At most 100 characters
  • Can be null

Responses

  • 200The device, registered or refreshed.
    FieldTypeDescription
    idrequiredstring

    pdev_…

    app_idrequiredstring
    user_idrequiredstring

    Your own id for the person.

    platformrequiredstring

    web is a browser's push subscription.

    • One of: ios | android | web
    apns_environmentrequiredstring

    The APNs environment of an iOS device; null for Android and web.

    • One of: sandbox | production
    • Can be null
    encryption_key_idrequiredstring

    The id of the encryption key the device registered (the first 16 characters of base64url(SHA-256(public key))), sent as kid in each push encrypted to it. Null when it registered none, and always null for web. The key itself is never returned.

    • Can be null
    activerequiredboolean

    False once the device was retired; a retired device is never sent to.

    deactivated_reasonrequiredstring

    Why it was retired: UNREGISTERED or INVALID_TOKEN (Apple or Google; INVALID_TOKEN too for a browser subscription its push service no longer knows, or that HonkIO can no longer read), APP_MISMATCH (a token for another app, on a credential that has worked), DEVICE_LIMIT (the per-user limit), APP_DELETED (its app was deleted), VAPID_KEY_REPLACED (a browser, when the app's web push key pair was replaced), VAPID_KEY_MISMATCH (a browser whose push service refused the app's key five times in a row over at least a day), DUPLICATE (a second row for the same browser subscription, left by an encryption key rotation; the other row stays active), DELETED (you unregistered it) or RECIPIENT_DELETED (you deleted the recipient profile for its user_id). Null while active.

    • Can be null
    last_seen_atrequiredstring

    When the token was last registered.

    • Format: date-time
    created_atrequiredstring
    • Format: date-time
  • 401Missing, invalid, revoked or expired API key.The standard error body.
  • 402The account has no balance, or a LIVE key was used before the first top-up.The standard error body.
  • 403The API key lacks the permission this operation requires, or the account is suspended or closed.The standard error body.
  • 404PUSH_APP_NOT_FOUND: no push app with that id on this account.The standard error body.
  • 409PUSH_DEVICE_LIMIT: the app already has its maximum of active devices in this mode (1,000,000 live, 1,000 test).The standard error body.
  • 422VALIDATION_ERROR: the request failed validation; details names the fields.The standard error body.
  • 429Rate limit reached: 100 requests per second per account, or a route-specific limit (Retry-After set where one applies).The standard error body.
  • 500Unexpected server error.The standard error body.

Example

const { data: device, error } = await honkio.push.devices.register({
  appId: 'APP_ID',
  token: 'DEVICE_TOKEN',
  platform: 'ios',
  userId: 'user_1042',
  apnsEnvironment: 'production',
  encryptionPublicKey: 'DEVICE_PUBLIC_KEY', // the key the HonkIO push package made on the device
})
if (error) throw new Error(error.message)
console.log(device.id, device.active, device.encryption_key_id)
delete/v1/push/devices/{id}

Unregister a device

Requires push_devices:d.

Parameters

ParameterTypeDescription
idrequiredpathstring

Responses

  • 204Unregistered.
  • 401Missing, invalid, revoked or expired API key.The standard error body.
  • 402The account has no balance, or a LIVE key was used before the first top-up.The standard error body.
  • 403The API key lacks the permission this operation requires, or the account is suspended or closed.The standard error body.
  • 404PUSH_DEVICE_NOT_FOUND: no device with that id in this key's mode.The standard error body.
  • 429Rate limit reached: 100 requests per second per account, or a route-specific limit (Retry-After set where one applies).The standard error body.
  • 500Unexpected server error.The standard error body.

Example

const { error } = await honkio.push.devices.delete('DEVICE_ID')
if (error) throw new Error(error.message)
get/v1/push

List pushes

Newest first. Each push carries accepted_count, the devices Apple or Google accepted it for (the per-device results are on GET /v1/push/{id}).

Requires push:r.

Parameters

ParameterTypeDescription
app_idquerystring
user_idquerystring
statusquerystring

One of queued, sending, sent, failed, fell_back.

created_afterquerystring

ISO 8601 date-time with an offset: created at or after.

created_beforequerystring

ISO 8601 date-time with an offset: created at or before.

limitquerystring

1 to 100. Default 50.

cursorquerystring

next_cursor from the previous page.

Responses

  • 200A page of pushes in the calling key's mode, newest first, each with accepted_count.
    FieldTypeDescription
    data[]requiredobject[]
    idrequiredstring
    app_idrequiredstring
    statusrequiredstring

    scheduled: accepted with scheduled_at and waiting for it. cancelled: a scheduled push cancelled before it went out; what it reserved was given back.

    • One of: scheduled | queued | sending | sent | failed | fell_back | cancelled
    torequiredobject
    user_idrequiredstring
    • Can be null
    device_idrequiredstring
    • Can be null
    titlerequiredstring
    • Can be null
    bodyrequiredstring
    • Can be null
    datarequiredobject

    Null once purged.

    • Can be null
    badgerequiredinteger
    • Can be null
    soundrequiredstring
    • Can be null
    thread_idrequiredstring
    • Can be null
    ttlrequiredinteger

    Seconds.

    • Can be null
    priorityrequiredstring
    • One of: high | normal
    • Can be null
    collapse_keyrequiredstring
    • Can be null
    encryptedrequiredboolean

    The app's require_encryption when the push was sent: true means every delivery was encrypted or refused with ENCRYPTION_KEY_MISSING. Each delivery's encrypted says what it got (false for a browser: web push is encrypted to it by RFC 8291, not with a device key).

    device_countrequiredinteger

    Devices the push was sent to (and charged for) at intake; devices refused for a missing encryption key are not counted.

    accepted_countinteger

    Devices and browsers whose push service (Apple, Google, Mozilla or Microsoft) accepted the push. On GET /v1/push and GET /v1/push/{id}; not on the send response.

    free_countrequiredinteger

    Deliveries covered by the monthly free allotment, net of refunds.

    charge_millicentsrequiredinteger

    What the push cost, exactly, in CAD millicents, net of refunds.

    cost_centsrequiredinteger

    Whole cents this push debited from the balance.

    fallbackrequiredobject
    • Can be null
    smsrequiredobject
    torequiredstring
    • Can be null
    fromrequiredstring
    • Can be null
    bodyrequiredstring
    • Can be null
    fallback_message_idrequiredstring
    • Can be null
    fallback_reasonrequiredstring
    • Can be null
    failure_coderequiredstring
    • Can be null
    failure_messagerequiredstring
    • Can be null
    body_purged_atrequiredstring
    • Format: date-time
    • Can be null
    livemoderequiredboolean
    sent_atrequiredstring
    • Format: date-time
    • Can be null
    scheduled_atrequiredstring

    When a scheduled push is (or was) due to go out. Null on a push sent at once.

    • Format: date-time
    • Can be null
    expires_atrequiredstring

    The expires_at a scheduled push was given: the latest it may go out. Null when none was given, which means scheduled_at plus 24 hours. One that cannot go out by then fails with failure_code SCHEDULED_SEND_EXPIRED and is refunded.

    • Format: date-time
    • Can be null
    created_atrequiredstring
    • Format: date-time
    updated_atrequiredstring
    • Format: date-time
    deliveries[]object[]

    Each device's delivery result. On GET /v1/push/{id} only.

    idrequiredstring
    device_idrequiredstring

    Null once the device is deleted (30 days after it was deactivated); the delivery result stays.

    • Can be null
    providerrequiredstring

    webpush: a browser's push service.

    • One of: apns | fcm | webpush
    provider_message_idrequiredstring
    • Can be null
    statusrequiredstring
    • One of: pending | accepted | rejected | retrying
    billedrequiredboolean
    encryptedrequiredboolean

    Whether it was sent encrypted to the device's own key.

    error_coderequiredstring

    Why it was rejected, e.g. DEVICE_TOKEN_INVALID, APP_MISMATCH, CREDENTIAL_INVALID, NO_CREDENTIAL, ENCRYPTION_KEY_MISSING (the app requires encryption and the device registered no key: not sent, not charged), PAYLOAD_REJECTED or PROVIDER_ERROR.

    • Can be null
    attemptsrequiredinteger
    created_atrequiredstring
    • Format: date-time
    updated_atrequiredstring
    • Format: date-time
    has_morerequiredboolean
    next_cursorrequiredstring

    Pass it as cursor for the next page. Null on the last page.

    • Can be null
  • 401Missing, invalid, revoked or expired API key.The standard error body.
  • 402The account has no balance, or a LIVE key was used before the first top-up.The standard error body.
  • 403The API key lacks the permission this operation requires, or the account is suspended or closed.The standard error body.
  • 422VALIDATION_ERROR: the request failed validation; details names the fields.The standard error body.
  • 429Rate limit reached: 100 requests per second per account, or a route-specific limit (Retry-After set where one applies).The standard error body.
  • 500Unexpected server error.The standard error body.

Example

const { data, error } = await honkio.push.list({ status: 'failed', limit: 20 })
if (error) throw new Error(error.message)
for (const push of data.data) console.log(push.id, push.status)
post/v1/push

Send a push notification

Sends to every active device of to.user_id, or to one to.device_id. Answers 202 with the push queued and the number of devices targeted. Each accepted live delivery costs $5.00 per 1,000 after the first 2,500 each calendar month (Toronto time), which are free; rejected deliveries are refunded. With fallback.sms, a push that no device accepts is sent as a text instead, under every rule POST /v1/messages applies; the key needs messages:w for that (403 FORBIDDEN otherwise), and still needs it when the fallback fires. data is at most 4096 bytes serialized and 64 keys. collapse_key (1 to 64 visible ASCII characters) lets a newer push replace an older one with the same key. 403 PUSH_DISABLED when push is turned off for the account; 422 PUSH_PAYLOAD_TOO_LARGE when the final provider payload, after encryption, is over 4096 bytes; 429 PUSH_DAILY_CAP over the daily push limit. The same Idempotency-Key returns the original push; with a different body it is 409 IDEMPOTENCY_KEY_REUSED. A key starting with notify: is reserved for HonkIO: 422 IDEMPOTENCY_KEY_RESERVED. With scheduled_at (1 minute to 30 days ahead) the push is accepted with status scheduled and charged now for the devices targeted now, and counts against the daily limit of the day it is due. When it is due it is sent like any other push: an account suspended or with push turned off since fails it and refunds it, a device deactivated since is a rejected (refunded) delivery, and the fallback text runs every /v1/messages rule at that moment. Until then PATCH /v1/push/{id} moves it and DELETE /v1/push/{id} cancels it and refunds the charge. In place of title and body, template (a template's id or alias), variables and language (en or fr) send that template's push part, rendered: a live key the published version, a test key the draft. A language without a push part uses the default language's; a template with no push part answers 422 TEMPLATE_CHANNEL_MISSING. fallback.sms.body stays inline text: a fallback from a template comes with Notify.

Requires push:w.

Parameters

ParameterTypeDescription
Idempotency-Keyheaderstring
  • At most 255 characters

Request body

One push: an app, a target, and a title, a body, data or a template.

FieldTypeDescription
app_idrequiredstring

The push app to send with.

  • At least 1 characters
  • At most 100 characters
torequiredobject

Exactly one of user_id (every active device of that user) or device_id (one device).

user_idstring

Your own id for the person.

  • At least 1 characters
  • At most 255 characters
device_idstring

One registered device (pdev_…).

  • At least 1 characters
  • At most 100 characters
titlestring

The notification title, up to 1000 characters. Not with a template.

  • At least 1 characters
  • At most 1000 characters
bodystring

The notification text, up to 4000 characters. Required unless you send data or a template; not with a template.

  • At least 1 characters
  • At most 4000 characters
templatestring

A template's id or alias (/v1/templates): its push part is rendered and sent in place of title and body, held to their limits. A live key sends the published version, a test key the draft. 422 TEMPLATE_CHANNEL_MISSING when it has no push part.

  • At least 1 characters
  • At most 200 characters
variablesobject

Values for the template's variables. One with neither a value nor a fallback refuses the send (422 EMAIL_TEMPLATE_VARIABLE_MISSING, details.keys). Only with template.

languagestring

en or fr: the template's language version. When it has no push part, the default language's is sent. Only with template; left out, the default language.

  • One of: en | fr
dataobject

String values for your app, at most 64 keys and 4096 bytes as JSON. With no title and no body the push is a silent background push, without badge or sound, to each device that gets it unencrypted; a device with an encryption key gets the placeholder alert instead.

badgeinteger

The iOS badge number to show, 0 to clear it.

  • Minimum: 0
  • Maximum: 99999
soundstring

The sound to play: a sound file bundled in the app, or default.

  • At least 1 characters
  • At most 255 characters
thread_idstring

Groups notifications on iOS (thread-id) and Android (tag).

  • At least 1 characters
  • At most 255 characters
ttlinteger

Seconds Apple or Google keeps trying to deliver while the device is offline, up to 28 days. 0 means now or never.

  • Minimum: 0
  • Maximum: 2419200
prioritystring

high (the default) or normal. Normal lets the device save power and may delay delivery.

  • One of: high | normal
collapse_keystring

1 to 64 visible ASCII characters, no spaces: a newer push with the same key replaces an older one not yet shown.

fallbackobject

A text to send instead when no device accepts the push. The key needs messages:w.

smsrequiredobject
torequiredstring

The mobile number to text, E.164.

  • At least 1 characters
  • At most 32 characters
fromrequiredstring

One of your numbers, E.164.

  • At least 1 characters
  • At most 32 characters
bodyrequiredstring

The text, up to 1600 characters.

  • At least 1 characters
  • At most 1600 characters
scheduled_atstring

Send later: an ISO 8601 date-time with an offset, 1 minute to 30 days ahead.

  • Format: date-time
  • Default: null
  • Can be null
expires_atstring

The latest the scheduled send may go out: 1 minute to 24 hours after scheduled_at, and only with it. Without it, scheduled_at plus 24 hours. A send that cannot go out by then fails with SCHEDULED_SEND_EXPIRED and is refunded.

  • Format: date-time
  • Default: null
  • Can be null

Responses

  • 202Default Response
    FieldTypeDescription
    idstring
    statusstring

    scheduled, queued, sending, sent, failed, fell_back or cancelled. scheduled: accepted with scheduled_at and waiting for it; cancelled: a scheduled push cancelled before it went out, its charge refunded.

    scheduled_atstring

    When a scheduled push is (or was) due to go out. Null on a push sent at once.

    • Format: date-time
    • Can be null
    expires_atstring

    The expires_at a scheduled push was given: the latest it may go out. Null when none was given, which means scheduled_at plus 24 hours.

    • Format: date-time
    • Can be null
    livemodeboolean
    device_countinteger

    Devices targeted at intake.

    collapse_keystring

    Sent as APNs apns-collapse-id and FCM android.collapse_key: a newer push with the same key replaces an older one not yet shown. Null when none was given.

    • Can be null
    free_countinteger

    Deliveries covered by the monthly free allotment, net of refunds.

    charge_millicentsinteger

    What the push cost, exactly, in CAD millicents (1/1000 of a cent): accepted billed deliveries times the price, net of refunds for rejected ones.

    cost_centsinteger

    Whole cents this push debited from the balance, often 0 because prepaid credit is spent first. Approximate once rejected deliveries are refunded (the refund returns millicents to a pool shared with email); charge_millicents is the exact figure.

  • 401Missing, invalid, revoked or expired API key.The standard error body.
  • 402The account has no balance, or a LIVE key was used before the first top-up.The standard error body.
  • 403The API key lacks the permission this operation requires, or the account is suspended or closed.The standard error body.
  • 429Rate limit reached: 100 requests per second per account, or a route-specific limit (Retry-After set where one applies).The standard error body.
  • 500Unexpected server error.The standard error body.
  • 4XXDefault Response
  • 5XXDefault Response

Example

const { data: push, error } = await honkio.push.send({
  appId: 'APP_ID',
  to: { userId: 'user_1042' },
  title: 'Your code',
  body: '123456',
}, { idempotencyKey: 'login-code-1042-2026-11-03' })
if (error) throw new Error(error.message)
console.log(push.id, push.status, push.device_count)
get/v1/push/usage

Free pushes used this month

Requires push:r.

Responses

  • 200This month's free allotment and use.
    FieldTypeDescription
    monthrequiredstring

    The calendar month, Toronto time: YYYY-MM.

    free_monthlyrequiredinteger

    Free live deliveries each month.

    free_usedrequiredinteger

    Free live deliveries used this month. Always 0 for a test key: test sends are free and never count.

  • 401Missing, invalid, revoked or expired API key.The standard error body.
  • 402The account has no balance, or a LIVE key was used before the first top-up.The standard error body.
  • 403The API key lacks the permission this operation requires, or the account is suspended or closed.The standard error body.
  • 429Rate limit reached: 100 requests per second per account, or a route-specific limit (Retry-After set where one applies).The standard error body.
  • 500Unexpected server error.The standard error body.

Example

const { data, error } = await honkio.push.usage()
if (error) throw new Error(error.message)
console.log(data)
get/v1/push/{id}

Get a push by id

Requires push:r.

Parameters

ParameterTypeDescription
idrequiredpathstring

Responses

  • 200Default Response
    FieldTypeDescription
    idstring
    statusstring

    scheduled, queued, sending, sent, failed, fell_back or cancelled. scheduled: accepted with scheduled_at and waiting for it; cancelled: a scheduled push cancelled before it went out, its charge refunded.

    scheduled_atstring

    When a scheduled push is (or was) due to go out. Null on a push sent at once.

    • Format: date-time
    • Can be null
    expires_atstring

    The expires_at a scheduled push was given: the latest it may go out. Null when none was given, which means scheduled_at plus 24 hours.

    • Format: date-time
    • Can be null
    livemodeboolean
    device_countinteger

    Devices targeted at intake.

    collapse_keystring

    Sent as APNs apns-collapse-id and FCM android.collapse_key: a newer push with the same key replaces an older one not yet shown. Null when none was given.

    • Can be null
    free_countinteger

    Deliveries covered by the monthly free allotment, net of refunds.

    charge_millicentsinteger

    What the push cost, exactly, in CAD millicents (1/1000 of a cent): accepted billed deliveries times the price, net of refunds for rejected ones.

    cost_centsinteger

    Whole cents this push debited from the balance, often 0 because prepaid credit is spent first. Approximate once rejected deliveries are refunded (the refund returns millicents to a pool shared with email); charge_millicents is the exact figure.

  • 401Missing, invalid, revoked or expired API key.The standard error body.
  • 402The account has no balance, or a LIVE key was used before the first top-up.The standard error body.
  • 403The API key lacks the permission this operation requires, or the account is suspended or closed.The standard error body.
  • 429Rate limit reached: 100 requests per second per account, or a route-specific limit (Retry-After set where one applies).The standard error body.
  • 500Unexpected server error.The standard error body.
  • 4XXDefault Response

Example

const { data: push, error } = await honkio.push.get('PUSH_ID')
if (error) throw new Error(error.message)
for (const delivery of push.deliveries ?? []) console.log(delivery.device_id, delivery.status, delivery.error_code)
patch/v1/push/{id}

Reschedule a scheduled push

Only while the push is scheduled (otherwise 422 PUSH_NOT_SCHEDULED). The charge is unchanged. The push counts against the daily limit of its new day: 429 PUSH_DAILY_CAP when that day is full. Sends push.rescheduled.

Requires push:m.

Parameters

ParameterTypeDescription
idrequiredpathstring

Request body

The new send time of a scheduled push.

FieldTypeDescription
scheduled_atrequiredstring

An ISO 8601 date-time with an offset, 1 minute to 30 days ahead.

  • Format: date-time
expires_atstring

The latest it may go out: 1 minute to 24 hours after the new scheduled_at, or null for scheduled_at plus 24 hours. Left out, the stored expires_at is kept if it still fits the new scheduled_at, and dropped (back to the 24 hour default) if it does not.

  • Format: date-time
  • Can be null

Responses

  • 200The push's new send time.
    FieldTypeDescription
    idrequiredstring
    statusrequiredstring
    • One of: scheduled
    scheduled_atrequiredstring
    • Format: date-time
    expires_atrequiredstring

    The expires_at now stored, or null for scheduled_at plus 24 hours.

    • Format: date-time
    • Can be null
  • 401Missing, invalid, revoked or expired API key.The standard error body.
  • 402The account has no balance, or a LIVE key was used before the first top-up.The standard error body.
  • 403The API key lacks the permission this operation requires, or the account is suspended or closed.The standard error body.
  • 404NOT_FOUND (details.resource "push"): no push with that id in the calling key's mode.The standard error body.
  • 422PUSH_NOT_SCHEDULED (only a scheduled push can be moved; details.current_status says what it is now) or VALIDATION_ERROR (scheduled_at must be 1 minute to 30 days ahead; expires_at 1 minute to 24 hours after it).The standard error body.
  • 429PUSH_DAILY_CAP: the day the push would move to is already at the daily push limit. The details show the limit and when it resets.The standard error body.
  • 500Unexpected server error.The standard error body.
  • 4XXDefault Response

Example

const { data, error } = await honkio.push.update('PUSH_ID', { scheduledAt: '2026-10-01T14:00:00Z' })
if (error) throw new Error(error.message)
console.log(data.scheduled_at, data.expires_at) // expires_at: null means scheduled_at plus 24 hours
delete/v1/push/{id}

Cancel a scheduled push

Only while the push is scheduled (otherwise 422 PUSH_NOT_SCHEDULED). What it reserved is given back (the charge refunded, free deliveries returned to the month) and push.cancelled is sent. Cannot be undone.

Requires push:d.

Parameters

ParameterTypeDescription
idrequiredpathstring

Responses

  • 204Cancelled: the charge refunded and free deliveries returned to the month.
  • 401Missing, invalid, revoked or expired API key.The standard error body.
  • 402The account has no balance, or a LIVE key was used before the first top-up.The standard error body.
  • 403The API key lacks the permission this operation requires, or the account is suspended or closed.The standard error body.
  • 404NOT_FOUND (details.resource "push"): no push with that id in the calling key's mode.The standard error body.
  • 422PUSH_NOT_SCHEDULED: only a scheduled push can be cancelled; details.current_status says what it is now.The standard error body.
  • 429Rate limit reached: 100 requests per second per account, or a route-specific limit (Retry-After set where one applies).The standard error body.
  • 500Unexpected server error.The standard error body.
  • 4XXDefault Response

Example

const { error } = await honkio.push.cancel('PUSH_ID')
if (error) throw new Error(error.message)