v3 → v4 Migration Guide
This guide covers the breaking changes and new features when migrating from ProWorkflow API v3 (classic) to v4 (Nexus). The most significant change is the replacement of simple status booleans with the richer activeworkstate enum across all entities.
Breaking Changes
The status parameter values have changed for Projects, Items, Invoices, and Quotes. Your integration may need to be updated to use the new enum values.
Quick Summary
| Change | Impact | Effort |
|---|---|---|
| Base URL | Breaking | Find & replace |
| Status values | Breaking | Update filter values |
| Company address fields | Breaking | Update to use Company Locations |
| Work Stages | New | Optional adoption |
| Company Locations | New | Optional adoption |
| New fields & filters | New | Optional |
| Authentication | Changed | Minimal |
GET /api/v3/projects?status=active GET /api/v3/invoices?status=unpaid GET /api/v3/quotes?status=approved
GET /api/v4/projects?status=active GET /api/v4/invoices?status=submitted GET /api/v4/quotes?status=accepted
Base URL Change Breaking
The API base URL has been updated from v3 to v4.
| Version | Base URL |
|---|---|
| v3 | https://api.proworkflow.net |
| v4 | https://api.proworkflow.com/api/v4/ |
Tip
Store the base URL in a configuration variable so updating is a single change.
// Before const BASE_URL = "https://api.proworkflow.net/"; // After const BASE_URL = "https://api.proworkflow.com/api/v4";
Response Format Changed
All v4 responses use a uniform envelope. v3 returned resource-keyed payloads (e.g. "projects": [...], "invoices": [...]); v4 always uses data regardless of resource.
List Responses
| Key | Description |
|---|---|
status | Always lowercase "success" or "error" |
data | Array of result objects |
meta | Object containing count, total, page, pagesize (when paginated) |
Single-Item Responses
Single-resource endpoints (GET /projects/{id}) return data as an object instead of an array.
Error Responses
Handler-level errors (validation, permission, not-found) use the same envelope, with data populated as an array of message strings:
{"status": "error", "data": ["msg1", "msg2"]}
Middleware-level errors (authentication failures, rate limiting) bypass the envelope and return the framework default:
{"message": "Invalid bearer token"}
Client code should handle both shapes.
Migration Required
Replace any v3 client code that reads response.projects, response.invoices, response.count, or response.totalcount with response.data and response.meta.count / response.meta.total.
{
"status": "success",
"data": [
{ "id": 1, "name": "Acme Corp" },
{ "id": 2, "name": "Globex" }
],
"meta": {
"count": 2,
"total": 145,
"page": 1,
"pagesize": 50
}
}
{
"status": "success",
"data": {
"id": 42,
"name": "Website Redesign",
"activeworkstate": "active"
}
}
{
"status": "error",
"data": [
"Invalid status value",
"pagesize must be a positive integer"
]
}
// 401 Unauthorized, 429 Too Many Requests, etc.
{
"message": "Invalid bearer token"
}
Status → activeworkstate Breaking
The v3 API used simple boolean or limited string status fields (JobComplete, Paid, QuoteStatus). The v4 API introduces activeworkstate — a richer enum system with more granular states per entity.
As a query filter, the parameter is named status (an alias for activeworkstate — both work). In response bodies, the field is named activeworkstate.
Important
The v3 value active still works for Projects and Items. However, Invoice and Quote status values have changed completely.
Full Status Mapping
| Entity | v3 Values | v4 Values (activeworkstate) |
|---|---|---|
| Projects | active, complete, all | active, complete, deleted, all |
| Items/Tasks | active, complete, all | active, complete, deleted, all |
| Invoices | paid, unpaid, all | draft, submitted, authorised, paid, voided, deleted, all |
| Quotes | pending, approved, declined, all | pending, sent, accepted, addedtoproject, declined, expired, deleted, all |
{
"status": "success",
"data": [
{
"id": 123,
"title": "Website Redesign",
"activeworkstate": "active"
}
],
"meta": {
"count": 1,
"total": 1
}
}
Projects
Project status is derived from Jobs.activeworkstate. When status is omitted, only active projects are returned. Pass status=all to include completed projects.
| v4 Status | Description | v3 Equivalent |
|---|---|---|
active | Active, in-progress project | active |
complete | Completed project | complete |
deleted | Soft-deleted project | Not available |
all | All non-deleted, non-proposal projects | all |
Proposals
Proposal projects are not exposed via the /projects endpoint. Use a dedicated proposals endpoint if available, or filter by work stage.
Backwards Compatible
The v3 values active, complete, and all work identically in v4.
# List active projects (default) curl 'https://api.proworkflow.com/api/v4/projects?status=active' \ -H 'apikey: xxxx-xxxx-xxxx-xxxx-PWFxxxx' # List all non-deleted projects curl 'https://api.proworkflow.com/api/v4/projects?status=all' \ -H 'apikey: xxxx-xxxx-xxxx-xxxx-PWFxxxx'
Items / Tasks
Item (task) status is derived from Item.activeworkstate. Uses the same enum as Projects. When status is omitted, only active items are returned. Pass status=all to include completed items.
| v4 Status | Description | v3 Equivalent |
|---|---|---|
active | Active task | active |
complete | Completed task | complete |
deleted | Soft-deleted task | Not available |
all | All non-deleted tasks | all |
# List active tasks assigned to me curl 'https://api.proworkflow.com/api/v4/items?status=active&contacts=me' \ -H 'apikey: xxxx-xxxx-xxxx-xxxx-PWFxxxx' # List completed tasks with project info curl 'https://api.proworkflow.com/api/v4/items?status=complete&fields=title,project,dates' \ -H 'apikey: xxxx-xxxx-xxxx-xxxx-PWFxxxx'
Invoices Breaking
Invoice status has changed significantly. The v3 binary paid/unpaid model is replaced by a workflow-based state machine.
| v4 Status | Description | v3 Equivalent |
|---|---|---|
draft | Invoice created, not yet sent | Not available |
submitted | Sent to client | unpaid |
authorised | Approved / authorized for payment | unpaid |
paid | Payment received | paid |
voided | Cancelled / voided | Not available |
deleted | Soft-deleted | Not available |
unpaid | Convenience filter — matches submitted + authorised | unpaid |
all | All non-deleted invoices | all |
Default
When status is omitted, all non-deleted invoices are returned (equivalent to status=all).
"unpaid" Behavior Difference
v4 retains status=unpaid as a convenience filter, but it now maps to submitted + authorised only — it does not include draft. v3 typically counted drafts as unpaid. If your integration depends on drafts being included, use status=all and filter client-side, or make a separate status=draft request.
// v3 GET /api/v3/invoices?status=unpaid // v4 — single call works (excludes drafts) GET /api/v4/invoices?status=unpaid // v4 — include drafts as well: combine results GET /api/v4/invoices?status=draft GET /api/v4/invoices?status=unpaid
draft → submitted → authorised → paid ↘ voided (any state) ──────────────→ deleted
Quotes Breaking
Quote status values have expanded from the v3 set. The v3 value approved maps to accepted in v4.
| v4 Status | Description | v3 Equivalent |
|---|---|---|
pending | Created, awaiting review | pending |
sent | Sent to client | Not available |
accepted | Client accepted the quote | approved |
addedtoproject | Quote converted to project | Not available |
declined | Client declined the quote | declined |
expired | Quote expired | Not available |
deleted | Soft-deleted | Not available |
all | All non-deleted quotes | all |
Renamed Value
The v3 approved status is now accepted in v4. Update any code that checks for or filters by approved.
Default
When status is omitted, all non-deleted quotes are returned (equivalent to status=all). This differs from Projects/Items, which default to active only.
// v3 GET /api/v3/quotes?status=approved // v4 — "approved" is now "accepted" GET /api/v4/quotes?status=accepted // v4 — new states available GET /api/v4/quotes?status=sent GET /api/v4/quotes?status=addedtoproject GET /api/v4/quotes?status=expired
pending → sent → accepted → addedtoproject ↘ declined (any) → expired (any) → deleted
Work Stages New
Work Stages are custom workflow steps within each work state. Each account can define named stages per work state (e.g., "In Review" stage within the "active" state, or "Awaiting Approval" within "submitted").
How It Works
Each entity (project, item, invoice, quote) has an optional work stage field representing its current position within the broader activeworkstate. The JSON field name differs by entity:
| Entity | Response Field | Description |
|---|---|---|
| Projects | workstageid | Active work stage ID (0 / omitted = no stage set) |
| Items, Quotes, Invoices | activeworkstageid | Active work stage ID (0 / omitted = no stage set) |
Filtering
All four entities (projects, items, quotes, invoices) support a workstageid query parameter to filter by a specific work stage ID.
Managing Stages
Work stages are configured per account via the settings endpoints:
| Endpoint | Description |
|---|---|
GET /settings/workstages | All work stages |
GET /settings/workstages/project | Project work stages |
GET /settings/workstages/item | Item work stages |
GET /settings/workstages/invoice | Invoice work stages |
GET /settings/workstages/quote | Quote work stages |
// Get items in a specific work stage (filter param is workstageid; // response field for items is activeworkstageid) GET /api/v4/items?workstageid=5&fields=title,activeworkstate,activeworkstageid // Response { "status": "success", "data": [ { "id": 101, "title": "Design mockups", "activeworkstate": "active", "activeworkstageid": 5 }, { "id": 102, "title": "Review copy", "activeworkstate": "active", "activeworkstageid": 5 } ], "meta": { "count": 2, "total": 2 } }
Authentication Changed
Authentication methods remain largely the same, with an important distinction between auth types.
API Key (Staff-level access)
API Key format is unchanged. Pass via the apikey header.
Format: xxxx-xxxx-xxxx-xxxx-PWFxxxx
Implied Staff Role
API key authentication implies staff-level access (usertype=3), since only staff members have access to API keys. No individual user identity is associated with the request.
Bearer Token (Individual user access)
Bearer tokens authenticate individual users via OAuth. The user's role (client, contractor, or staff) and permissions are determined by their account. Use this for client-facing apps where users log in with their own credentials.
OAuth app setup requires a client secret. Contact [email protected] for setup.
Authentication Precedence
If both an Authorization: Bearer header and an apikey header are sent on the same request, the Bearer token takes precedence and the API key is ignored.
curl 'https://api.proworkflow.com/api/v4/projects' \ -H 'apikey: xxxx-xxxx-xxxx-xxxx-PWFxxxx'
curl 'https://api.proworkflow.com/api/v4/projects' \ -H 'Authorization: Bearer eyJhbGciOi...'
New Fields & Filters New
v4 introduces several new fields and filter parameters across entities.
New Fields (all entities)
| Field | Type | Description |
|---|---|---|
activeworkstate | String | Workflow state enum value (e.g. active, complete, submitted, paid) |
workstageid / activeworkstageid | Integer | Active work stage ID. Projects expose this as workstageid; Items, Quotes, and Invoices expose it as activeworkstageid |
New Filter Parameters
| Parameter | Entities | Description |
|---|---|---|
workstageid | Projects, Items, Quotes, Invoices | Filter by work stage |
contacts | Projects, Items, Time, Messages | Filter by assigned contacts (supports me, all, and !ids negation) |
contactsmode | Projects, Items | Match any or all specified contacts |
divisionid | All | Filter by division (Advanced plan) |
// Request specific fields GET /api/v4/items?fields=title,status,project,assignedto // Request all fields GET /api/v4/items?fields=all
Fields & Sub-entities New
v4 uses a per-request field selection model to keep responses small. v3 typically returned every field — v4 returns only the fields you ask for.
The fields Parameter
Pass a comma-separated list of field names. Use fields=all to request every scalar/relation field. The id field is always returned regardless of selection.
| Value | Behavior |
|---|---|
| omitted | Endpoint-specific default field set |
name,code,status | Listed fields plus id |
all | All scalar and relation fields, but not sub-entity arrays |
Sub-entities Are Named in fields
Sub-entity arrays — phases, time records, messages, files, folders, etc. — are never included by fields=all. To include them, name them explicitly in the fields list. Each named sub-entity adds an extra SQL join, so include them only when needed.
| Sub-entity Name | Resource | Adds |
|---|---|---|
phases | Projects, Quotes, Invoices | Phases (with their items) |
timerecords | Projects | Time records |
messages | Projects | Messages |
files | Projects | File attachments |
folders | Projects | File folders |
invoices | Projects | Linked invoices |
workstages | Projects | Work stage history |
bookmarks | Projects | Bookmarks |
projectnotes | Projects | Project notes |
Single-item endpoints (GET /projects/{id}) include all sub-entities by default.
fields=all does NOT mean "everything"
Even fields=all will not include phases, time records, files, or messages. Combine all with sub-entity names: fields=all,phases,timerecords.
# Endpoint-specific default field set
GET /api/v4/projects
# Only id, title, and activeworkstate
GET /api/v4/projects?fields=title,status
GET /api/v4/projects?fields=all
# Embed phases (with their items) inline
GET /api/v4/projects?fields=all,phases
GET /api/v4/projects/123?fields=title,timerecords,messages
Time Records Changed
Time record endpoints now support the same field selection and filtering patterns as other entities.
Key Changes
| Feature | v3 | v4 |
|---|---|---|
| Field selection | All fields returned | fields param with named groups |
| Default date range | Last 6 days | Same: trackedfrom=-6d&trackedto=+0d |
| Status filter | projectstatus | projectstatus kept; new activeworkstate filter added (uses activeworkstate enum values) |
| Relative dates | -6d, +0d | Same format supported |
Available Field Groups
contact, item, project, company, dates, timetracked, notes, billable, lastmodified, all
# Get time for last 30 days with project info curl 'https://api.proworkflow.com/api/v4/time?\ fields=contact,item,project,timetracked&\ trackedfrom=-30d&trackedto=+0d' \ -H 'apikey: xxxx-xxxx-xxxx-xxxx-PWFxxxx' # Get only billable time for my user curl 'https://api.proworkflow.com/api/v4/time?\ fields=item,timetracked,billable&\ contacts=me&billable=billable' \ -H 'apikey: xxxx-xxxx-xxxx-xxxx-PWFxxxx'
Pagination Changed
Pagination parameters keep their v3 names. Either or both can be provided — the endpoint applies safe defaults for whatever you omit.
| Parameter | Default | Description |
|---|---|---|
pagenumber | 1 | Page number (1-based) |
pagesize | 30000 | Results per page (max 30000) |
sortby | varies | Sort field (entity-specific) |
sortorder | asc | asc or desc |
Set an Explicit pagesize
When pagesize is omitted, the API allows up to 30000 records per request. For predictable performance, target ≤500 records per call and never exceed 1000. Pass a small explicit pagesize (e.g. 50) on every list request.
Response Counts
List responses include a meta object with count (items in current page) and total (total matching records).
# Get page 2, 25 items per page curl 'https://api.proworkflow.com/api/v4/projects?\ pagenumber=2&pagesize=25&\ sortby=title&sortorder=asc' \ -H 'apikey: xxxx-xxxx-xxxx-xxxx-PWFxxxx' # Response includes counts in meta { "status": "success", "data": [...], "meta": { "count": 25, "total": 150, "page": 2, "pagesize": 25 } }
Rate Limiting New
v4 enforces request rate limits per API key (or per IP for unauthenticated requests). v3 did not.
Limits
| Window | Limit |
|---|---|
| 30 seconds | 500 requests |
Exceeding the limit returns HTTP 429 Too Many Requests.
Response Headers
Every response includes rate limit state:
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests in the window (always 500) |
X-RateLimit-Remaining | Requests remaining in the current window |
X-RateLimit-Reset | Seconds until the window resets (30) |
Migration Notes
If your v3 integration runs tight loops or bulk syncs, monitor X-RateLimit-Remaining and back off as it approaches zero. Consider larger pagesize values (up to 30,000 records per request, target ≤500) to reduce request volume.
Error Format Note
Middleware-level errors (rate limit, authentication failures) return the framework default {"message": "..."} rather than the standard handler envelope {"status": "error", "data": [...]}. Check both shapes in client error handling.
HTTP/1.1 200 OK X-RateLimit-Limit: 500 X-RateLimit-Remaining: 487 X-RateLimit-Reset: 30 Content-Type: application/json
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 500
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 30
{
"message": "Rate limit exceeded"
}
Company Address Fields → Company Locations Breaking
In v3, address data was stored directly on the Company object (address1, address2, address3, city, state, zipcode, country). In v4 these fields have been removed from the Company response. Address data is now managed through the dedicated Company Location resource, which supports multiple addresses per company with richer metadata.
Breaking Change
The fields address1, address2, address3, city, state, zipcode, and country have been removed from the Company response. You must now use the Company Locations API to read or write address data.
What Changed
| v3 Field | v4 Equivalent |
|---|---|
address1 | CompanyLocation.address1 |
address2 | CompanyLocation.address2 |
address3 | CompanyLocation.address3 |
city | CompanyLocation.city |
state | CompanyLocation.state |
zipcode | CompanyLocation.zipcode |
country | CompanyLocation.countryid / CompanyLocation.formattedaddress |
New: maincompanylocationid
The Company object now exposes maincompanylocationid — the ID of the company's primary location. Use this to look up the main address via the Company Locations endpoint.
Embedding locations in the company list
You can avoid the two-step lookup by passing includelocations=true on the company list or single-get endpoint. This embeds a locations array directly in each company object.
New Endpoints
| Endpoint | Description |
|---|---|
GET /api/v4/companies/{companyid}/locations | List locations for a company |
POST /api/v4/companies/{companyid}/locations | Create a location for a company |
GET /api/v4/companies/{companyid}/locations/{locationid} | Get a single location |
PUT /api/v4/companies/{companyid}/locations/{locationid} | Update a location |
DELETE /api/v4/companies/{companyid}/locations/{locationid} | Delete a location |
Creating / updating address data
CompanyLocation Fields
| Field | Type | Description |
|---|---|---|
id | Integer | Unique identifier |
name | String | Location name (e.g. "Head Office") |
code | String | Short code identifier |
type | String | Address type (e.g. postal, physical) |
description | String | Description of the location |
deliveryinstructions | String | Delivery / access instructions |
phone | String | Location phone number |
phone2 | String | Secondary phone number |
email | String | Location email address |
active | Boolean | Whether the location is active |
companyid | Integer | Parent company ID |
countryid | Integer | Country ID |
formattedaddress | String | Full formatted address string |
address1 | String | Street address line 1 |
address2 | String | Street address line 2 |
address3 | String | Street address line 3 |
suburb | String | Suburb |
city | String | City |
state | String | State / region |
zipcode | String | Postal / zip code |
latitude | Float | GPS latitude |
longitude | Float | GPS longitude |
placeid | String | Google Maps place ID |
lastmodifiedutc | String | Last modified timestamp (UTC, ISO8601) |
GET /api/v3/companies/42
// Response included inline address:
{
"id": 42,
"name": "Acme Corp",
"address1": "123 Main St",
"city": "New York",
"state": "NY",
"zipcode": "10001",
"country": "USA"
}
// Step 1 — get the company (includes maincompanylocationid)
GET /api/v4/companies/42?fields=name,maincompanylocationid
// Response:
{
"status": "success",
"data": {
"id": 42,
"name": "Acme Corp",
"maincompanylocationid": 7
}
}
// Step 2 — fetch the location
GET /api/v4/companylocations/7
// Response:
{
"status": "success",
"data": {
"id": 7,
"name": "Head Office",
"address1": "123 Main St",
"city": "New York",
"state": "NY",
"zipcode": "10001",
"formattedaddress": "123 Main St, New York NY 10001, USA"
}
}
GET /api/v4/companies?fields=name,maincompanylocationid&includelocations=true
// Each company in the response includes:
{
"id": 42,
"name": "Acme Corp",
"maincompanylocationid": 7,
"locations": [
{
"id": 7,
"name": "Head Office",
"type": "postal",
"active": true,
"address1": "123 Main St",
"city": "New York",
"state": "NY",
"zipcode": "10001",
"formattedaddress": "123 Main St, New York NY 10001, USA"
}
]
}
POST /api/v4/companies/42/locations
{
"name": "Head Office",
"type": "postal",
"address1": "123 Main St",
"city": "New York",
"state": "NY",
"zipcode": "10001",
"countryid": 1,
"active": true
}
// After creating the location (returns id: 7), set it as the main location:
PUT /api/v4/companies/42
{
"maincompanylocationid": 7
}
Staff Rates Breaking
In v3, staff rates were available at two separate endpoints under quotes and invoices settings. In v4, these have been consolidated into a single endpoint.
| v3 Endpoint | v4 Endpoint |
|---|---|
/settings/quotes/staffrates | /settings/staffrates |
/settings/invoices/staffrates |
New Fields
The consolidated endpoint now includes the linked hourly rate service for each staff member.
| Field | Type | Description |
|---|---|---|
id | Integer | Staff contact ID |
firstname | String | First name |
lastname | String | Last name |
hourlyrateserviceid | Integer | Default hourly rate service ID |
hourlyrateservicename | String | Name of the linked hourly rate service |
Rate Field Visibility
The sell rate (outprice) is included in the response for staff with the ViewSensitiveBusinessInfo permission. Staff without this permission will not see it. Pay rate and cost rate fields are also available on individual items (project items, quote items, template items) and time allocations where applicable.
// Two separate endpoints
GET /api/v3/settings/quotes/staffrates
GET /api/v3/settings/invoices/staffrates
// Single consolidated endpoint GET /api/v4/settings/staffrates // Response { "status": "success", "data": [ { "id": 42, "firstname": "Jane", "lastname": "Smith", "hourlyrateserviceid": 3, "hourlyrateservicename": "Senior Developer", "outprice": 120.00 } ], "meta": { "count": 1, "total": 1 } }
Product Libraries New
v4 introduces dedicated endpoints for each product library type, matching the categories in the ProWorkflow UI.
| Endpoint | Library | Description |
|---|---|---|
/settings/product/hourlyservice | Hourly Services | Products charged at an hourly rate |
/settings/product/fixedprice | Fixed Price | Products charged at a set price per unit |
/settings/product/goodservice | Goods & Services | Products with both hourly and quantity components |
Service Rates
The /settings/servicerates endpoint returns the hourly rate service definitions used to link products to billable rates.
Product Fields
Each product library returns fields appropriate to its type. Hourly service products include hourlyrateserviceid and hourlyrateservicename. Fixed price products include inUnitId and outUnitId. Goods & Services products include all of the above.
Rate Field Visibility
Labour rates (inLabourPrice, outLabourPrice) are gated by the ViewSensitiveBusinessInfo permission. They are returned by /settings/product/hourlyservice and /settings/product/goodservice only when the user holds that permission. Unit prices (inUnitPrice, outUnitPrice) on the Goods & Services library are gated the same way; on the Fixed Price library they are returned to all staff.
# Hourly Services GET /api/v4/settings/product/hourlyservice # Fixed Price Products GET /api/v4/settings/product/fixedprice # Goods & Services GET /api/v4/settings/product/goodservice # Hourly Rate Service definitions GET /api/v4/settings/servicerates
{
"status": "success",
"data": [
{
"id": 10,
"name": "Web Development",
"code": "WEBDEV",
"itemtypeid": 2,
"hourlyrateserviceid": 3,
"hourlyrateservicename": "Developer",
"inLabourPrice": 50,
"outLabourPrice": 100,
"billable": true
}
],
"meta": {
"count": 1,
"total": 1
}
}
Removed Endpoints Breaking
The following endpoints from v3 have been removed in v4.
| Removed Endpoint | Replacement | Reason |
|---|---|---|
/settings/quotes/staffrates | /settings/staffrates | Consolidated into single endpoint |
/settings/invoices/staffrates | /settings/staffrates | Consolidated into single endpoint |
/settings/invoices/hourlyrates | /settings/servicerates | Consolidated into single endpoint |
/settings/quotes/hourlyrates | /settings/servicerates | Consolidated into single endpoint |
/settings/fixedcostitems | Product Libraries | Replaced by /settings/product/* endpoints |
/settings/projects/customstatuses | Work Stages | Custom statuses replaced by Work Stages |
/settings/projects/customstatuses/:id | Work Stages | Custom statuses replaced by Work Stages |
Action Required
If your integration uses any of the removed endpoints, update your code to use the replacement endpoints listed above. Requests to removed endpoints will return a 404 Not Found response.
Custom Statuses → Work Stages
The /settings/projects/customstatuses CRUD endpoints have been removed. Custom statuses are replaced by Work Stages (activeworkstageid), which provide a more flexible workflow system that applies across all entities (projects, items, invoices, quotes) — not just projects.
See the Work Stages section above for details on the new system. Use the workstageid field and filter parameter to work with stages.
Webhooks (REST Hooks) Changed
REST hook subscriptions are managed under /settings/webhooks in v4. All webhook endpoints require staff-level access.
Endpoints
| Method | Path | Description |
|---|---|---|
GET | /settings/webhooks | List all webhook subscriptions |
POST | /settings/webhooks | Create a webhook subscription |
GET | /settings/webhooks/:webhookid | Get a single subscription |
PUT | /settings/webhooks/:webhookid | Update a subscription |
DELETE | /settings/webhooks/:webhookid | Delete a subscription |
GET | /settings/webhooks/requests | View recent webhook delivery attempts (retained for 7 days) |
curl 'https://api.proworkflow.com/api/v4/settings/webhooks' \ -H 'apikey: xxxx-xxxx-xxxx-xxxx-PWFxxxx'
# Inspect recent webhook fires for debugging
curl 'https://api.proworkflow.com/api/v4/settings/webhooks/requests' \
-H 'apikey: xxxx-xxxx-xxxx-xxxx-PWFxxxx'