Webhook payload structure for work_order.status_changed

Need the exact payload structure for work_order.status_changed. Docs show an example but no schema. Specifically:

  • Is previous_status always present?
  • What's the timestamp format — ISO 8601 with millis or no?
  • Are custom fields included or do I need a follow-up API call?

Current handler is breaking on null assignee_id when status goes from assignedunassigned. Need to know what else can be null.

// What I'm receiving (sanitized):
{
  "event": "work_order.status_changed",
  "timestamp": "2025-09-28T14:32:17.842Z",
  "data": {
    "work_order_id": "wo_...",
    "status": "in_progress",
    "previous_status": "assigned",
    "assignee_id": "usr_...",
    "changed_at": "2025-09-28T14:32:15.000Z"
  }
}

Show me the full schema or point me to OpenAPI/Swagger.

Parents
  • Hey Carlos — yeah this one tripped me up too when I first looked at it. The docs example is incomplete and I keep meaning to push for a proper JSON Schema. Here's what I can confirm from our side:

    Nullable fields (can be null or omitted):

    • previous_status — omitted entirely on new work orders (no prior state)
    • assignee_id — null when unassigned
    • team_id — null when not assigned to a team
    • scheduled_start / scheduled_end — null when no scheduling

    Timestamp format: Always ISO 8601 with milliseconds and Zulu offset (2025-09-28T14:32:17.842Z). The changed_at in your payload is the DB commit time; timestamp is when we fired the webhook (usually 50–200ms later).

    Custom fields: Not included in this event. You need to hit GET /v1/work_orders/{id} with ?include=custom_fields if you need them. There's a feature request to optionally include them in webhooks (API v2.1 added it for work_order.created but not status changes yet).

    Full schema I'm aware of:

    {
      "event": "work_order.status_changed",
      "webhook_id": "wh_...",
      "timestamp": string,  // ISO 8601 with ms
      "data": {
        "work_order_id": string,
        "status": string,           // new status
        "previous_status": string?, // omitted if no prior
        "assignee_id": string?,     // null if unassigned
        "team_id": string?,         // null if no team
        "customer_id": string,
        "location_id": string?,
        "scheduled_start": string?, // ISO 8601
        "scheduled_end": string?,   // ISO 8601
        "changed_at": string,       // when status actually changed
        "changed_by": {             // user or system
          "type": "user" | "system" | "api",
          "id": string?             // null for system
        }
      }
    }

    The ? denotes optional/nullable. Let me know if you're seeing fields not in that list — we had a brief regression in August where location_id was missing.

Reply
  • Hey Carlos — yeah this one tripped me up too when I first looked at it. The docs example is incomplete and I keep meaning to push for a proper JSON Schema. Here's what I can confirm from our side:

    Nullable fields (can be null or omitted):

    • previous_status — omitted entirely on new work orders (no prior state)
    • assignee_id — null when unassigned
    • team_id — null when not assigned to a team
    • scheduled_start / scheduled_end — null when no scheduling

    Timestamp format: Always ISO 8601 with milliseconds and Zulu offset (2025-09-28T14:32:17.842Z). The changed_at in your payload is the DB commit time; timestamp is when we fired the webhook (usually 50–200ms later).

    Custom fields: Not included in this event. You need to hit GET /v1/work_orders/{id} with ?include=custom_fields if you need them. There's a feature request to optionally include them in webhooks (API v2.1 added it for work_order.created but not status changes yet).

    Full schema I'm aware of:

    {
      "event": "work_order.status_changed",
      "webhook_id": "wh_...",
      "timestamp": string,  // ISO 8601 with ms
      "data": {
        "work_order_id": string,
        "status": string,           // new status
        "previous_status": string?, // omitted if no prior
        "assignee_id": string?,     // null if unassigned
        "team_id": string?,         // null if no team
        "customer_id": string,
        "location_id": string?,
        "scheduled_start": string?, // ISO 8601
        "scheduled_end": string?,   // ISO 8601
        "changed_at": string,       // when status actually changed
        "changed_by": {             // user or system
          "type": "user" | "system" | "api",
          "id": string?             // null for system
        }
      }
    }

    The ? denotes optional/nullable. Let me know if you're seeing fields not in that list — we had a brief regression in August where location_id was missing.

Children
No Data