Integration Keys
Scoped keys for external services like CI/CD, monitoring, and home automation. Integration keys have configurable scope -- activity:update (default) for read and update access, or activity:manage for full activity lifecycle management.
Overview
Integration keys use the hlk_ prefix and can be optionally restricted to specific activity slugs or prefix patterns (trailing *). Use them to give external services limited access to your PushWard account.
When you sign in, a default integration key is automatically created with activity:manage scope and no slug restrictions. You can copy it from the iOS app's settings screen to get started quickly.
Create separate integration keys for each service. If a key is compromised, you can revoke it without affecting other integrations.
Default Integration Key
/integrations/default-keyCreate or retrieve the default integration key. Idempotent -- returns the existing key's metadata if one already exists, or creates a new one and returns the plaintext key.
The default key always has activity:manage scope with no slug restrictions. It cannot be modified (scope/slug changes are blocked). If revoked, calling this endpoint again creates a new default key.
curl -X POST https://api.pushward.app/integrations/default-key \
-H "Authorization: Bearer hla_YOUR_TOKEN"Response (201 -- new key created):
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Default",
"scope": "activity:manage",
"key": "hlk_aBcDeFgHiJkLmNoPqRsTuVwXyZ012345",
"is_default": true,
"created": true,
"created_at": "2025-06-15T10:30:00Z"
}Response (200 -- key already exists):
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Default",
"scope": "activity:manage",
"is_default": true,
"created": false,
"created_at": "2025-06-15T10:30:00Z"
}The key value is only returned when created is true. If the key already exists, only metadata is returned -- the plaintext cannot be retrieved again.
Create Integration Key
/integrations/keysCreate a scoped integration key. The key is returned once in the response -- store it securely.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Human-readable label for the key |
scope | string | No | "activity:update" (default) or "activity:manage". Manage scope adds create and delete activity access. |
activity_slugs | string[] | No | Restrict key to specific activity slugs or prefix patterns (trailing *). Omit for all activities. |
curl -X POST https://api.pushward.app/integrations/keys \
-H "Authorization: Bearer hla_YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Relay",
"scope": "activity:manage",
"activity_slugs": ["grafana-*", "sabnzbd-*"]
}'Response (201):
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Relay",
"scope": "activity:manage",
"key": "hlk_aBcDeFgHiJkLmNoPqRsTuVwXyZ012345",
"activity_slugs": ["grafana-*", "sabnzbd-*"],
"created_at": "2025-06-15T10:30:00Z"
}The key value is only returned on creation. Store it immediately -- it cannot be retrieved later.
Each user can have at most 25 integration keys. Exceeding this limit returns 409 Conflict.
List Integration Keys
/integrations/keysList all integration keys for the current user. Key values are not returned -- only metadata.
curl https://api.pushward.app/integrations/keys \
-H "Authorization: Bearer hla_YOUR_TOKEN"Response:
[
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Home Assistant",
"scope": "activity:update",
"activity_slugs": ["dishwasher", "3dprinter"],
"last_used_at": "2025-06-16T08:00:00Z",
"created_at": "2025-06-15T10:30:00Z"
}
]Update Integration Key
/integrations/keys/{keyID}Update an integration key's scope or activity slug restrictions. At least one field must be provided.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
scope | string | No | "activity:update" or "activity:manage" |
activity_slugs | string[] | No | New slug restrictions. Pass an empty array to remove all restrictions. |
curl -X PATCH https://api.pushward.app/integrations/keys/KEY_ID \
-H "Authorization: Bearer hla_YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"scope": "activity:manage",
"activity_slugs": ["grafana-*", "argocd-*"]
}'Response (200):
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Relay",
"scope": "activity:manage",
"activity_slugs": ["grafana-*", "argocd-*"],
"created_at": "2025-06-15T10:30:00Z"
}Roll Integration Key
/integrations/keys/{keyID}/rollRegenerate the secret for an integration key. The old key is immediately invalidated and a new one is returned. Name, scope, and slug restrictions are preserved.
curl -X POST https://api.pushward.app/integrations/keys/KEY_ID/roll \
-H "Authorization: Bearer hla_YOUR_TOKEN"Response (200):
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Relay",
"scope": "activity:manage",
"key": "hlk_NewKeyValueHere012345678901234",
"activity_slugs": ["grafana-*", "argocd-*"],
"created_at": "2025-06-15T10:30:00Z"
}The new key value is only returned once. Update all services using this key immediately after rolling.
Revoke Integration Key
/integrations/keys/{keyID}Permanently revoke an integration key. The key will immediately stop working.
curl -X DELETE https://api.pushward.app/integrations/keys/KEY_ID \
-H "Authorization: Bearer hla_YOUR_TOKEN"Response: 204 No Content
Scoping Rules
Integration keys with activity_slugs can only update the listed activities. Attempting to access an activity outside the scope returns 403 Forbidden.
| Key Configuration | Access |
|---|---|
No activity_slugs | Can access any activity |
activity_slugs: ["dishwasher"] | Can only access the dishwasher activity |
activity_slugs: ["grafana-*"] | Can access any activity with slug starting with grafana- |
scope: "activity:update" | Can update and read activities (default) |
scope: "activity:manage" | Can create, update, read, and delete activities |
Allowed Endpoints
Endpoints accessible by integration keys (hlk_) depend on scope:
activity:update (default)
PATCH /activity/{slug}-- update activity state and content (owned activities only)GET /activities-- list activitiesGET /activities/{slug}-- get activity detailsPOST /notifications-- create notificationGET /notifications-- list notificationsGET /notifications/unread-count-- get unread countGET /auth/me-- get user profile
Integration keys cannot update activities shared with you by other users. Use a full-access hla_ token to update shared activities.
activity:manage
All of the above, plus:
POST /activities-- create activitiesDELETE /activities/{slug}-- delete activities