Notifications
Picklayer’s notification system lets you define automations — rules that trigger notification jobs on a schedule or event — and inspect the resulting runs and jobs for observability.
All notification management operations go through the Management API GraphQL endpoint (https://api.picklayer.ai/v1/graphql) using a builder organization token.
Automations
An automation defines when and how notifications are triggered. Each automation has a trigger_type, trigger_config, and a status.
List automations
query ListAutomations($orgId: uuid!, $appId: uuid!) {
notification_automations(
where: {
organization_id: { _eq: $orgId }
application_id: { _eq: $appId }
}
order_by: { created_at: desc }
) {
id name trigger_type trigger_config status next_run_at created_at updated_at
}
}Create an automation
mutation CreateAutomation($object: notification_automations_insert_input!) {
insert_notification_automations_one(object: $object) {
id name trigger_type status created_at
}
}Variables:
{
"object": {
"organization_id": "org-uuid",
"application_id": "app-uuid",
"name": "Daily digest",
"trigger_type": "schedule",
"trigger_config": {
"cron": "0 9 * * *",
"timezone": "America/New_York"
},
"status": "active"
}
}| Field | Type | Required | Description |
|---|---|---|---|
organization_id | uuid | yes | Your organization ID |
application_id | uuid | yes | The application this automation belongs to |
name | string | yes | Display name |
trigger_type | string | yes | How the automation fires (e.g., schedule, event) |
trigger_config | object | yes | Configuration specific to the trigger type |
status | string | yes | active, paused, or archived |
Update automation status
Pause, resume, or reschedule an automation:
mutation UpdateAutomationStatus($id: uuid!, $status: String!, $nextRunAt: timestamptz) {
update_notification_automations_by_pk(
pk_columns: { id: $id }
_set: { status: $status, next_run_at: $nextRunAt }
) {
id status next_run_at updated_at
}
}{
"id": "automation-uuid",
"status": "paused",
"nextRunAt": null
}Status values:
| Status | Description |
|---|---|
active | Automation fires on schedule or event trigger |
paused | Automation is temporarily disabled; resumes when set back to active |
archived | Automation is permanently disabled |
Runs
A run represents one execution of an automation — it tracks start time, completion, and any errors.
List runs
query ListRuns($orgId: uuid!, $appId: uuid!) {
notification_runs(
where: {
automation: {
organization_id: { _eq: $orgId }
application_id: { _eq: $appId }
}
}
order_by: { started_at: desc }
limit: 40
) {
id automation_id status started_at finished_at error_message
automation { name }
}
}Jobs
A job is an individual notification task within a run (e.g., sending an email to one recipient). Each run may produce many jobs.
List jobs
query ListJobs($orgId: uuid!, $appId: uuid!) {
notification_jobs(
where: {
organization_id: { _eq: $orgId }
application_id: { _eq: $appId }
}
order_by: { created_at: desc }
limit: 40
) {
id run_id status channel recipient_ref error_message created_at updated_at
}
}Python Example
import requests
HASURA_URL = "https://api.picklayer.ai/v1/graphql"
def get_headers(token):
return {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
}
def list_automations(token, org_id, app_id):
resp = requests.post(HASURA_URL, json={
"query": """
query($orgId: uuid!, $appId: uuid!) {
notification_automations(where: {
organization_id: {_eq: $orgId},
application_id: {_eq: $appId}
}, order_by: {created_at: desc}) {
id name trigger_type status next_run_at
}
}
""",
"variables": {"orgId": org_id, "appId": app_id},
}, headers=get_headers(token))
return resp.json()["data"]["notification_automations"]
def pause_automation(token, automation_id):
resp = requests.post(HASURA_URL, json={
"query": """
mutation($id: uuid!) {
update_notification_automations_by_pk(
pk_columns: {id: $id},
_set: {status: "paused"}
) { id status }
}
""",
"variables": {"id": automation_id},
}, headers=get_headers(token))
return resp.json()["data"]["update_notification_automations_by_pk"]
def list_recent_runs(token, org_id, app_id, limit=20):
resp = requests.post(HASURA_URL, json={
"query": """
query($orgId: uuid!, $appId: uuid!, $limit: Int!) {
notification_runs(
where: {automation: {
organization_id: {_eq: $orgId},
application_id: {_eq: $appId}
}},
order_by: {started_at: desc},
limit: $limit
) {
id automation_id status started_at finished_at error_message
}
}
""",
"variables": {"orgId": org_id, "appId": app_id, "limit": limit},
}, headers=get_headers(token))
return resp.json()["data"]["notification_runs"]