Skip to main content

Payload Customization

Transform webhook payloads and create dynamic URLs to match your system's exact requirements. Eliminate middleware with JSONata expressions.

Overview​

Field Nation webhooks now support customizable payloads and dynamic URLs, giving you complete control over how webhook data is structured and delivered.

What You Can Do​

CapabilityDescription
Transform PayloadsRestructure webhook data to match your system's expected format using JSONata expressions.
Dynamic URLsInclude event data in webhook URLs for intelligent routing (e.g., route by region or company).
Filter FieldsSend only the fields you need — reduce payload size and processing overhead.
Rename FieldsMatch your system's naming conventions without building middleware.

Why Customize Payloads?​

The Problem​

Without customization, integrating with external systems requires:

  1. Middleware servers to transform Field Nation's payload format
  2. Extra development time to map fields between systems
  3. Infrastructure costs to maintain translation services
  4. Processing delays from additional network hops

The Solution​

With payload customization, transformations happen at the source:

BeforeAfter
Build middleware to transformTransform at delivery
Maintain translation serversNo extra infrastructure
One fixed payload formatUnlimited custom formats
Static webhook URLsDynamic, data-driven URLs

Real-World Use Cases​

Challenge: ServiceNow expects incident tickets in a specific format with custom field names.

JSONata Script:

{
"u_external_ticket_id": $string($.workorder.id),
"short_description": $.workorder.title,
"state": $.workorder.status.name = "Work Done" ? "6" : "2",
"assignment_group": "Field Services",
"u_technician": $.workorder.assignee.first_name & " " & $.workorder.assignee.last_name,
"u_client_company": $.workorder.company.name,
"work_notes": "Status updated via Field Nation at " & $.timestamp
}

Result: Direct webhook delivery to ServiceNow without middleware.


Transformation Options​

JSONata is a powerful query and transformation language for JSON data.

Why JSONata?

It's purpose-built for JSON transformation, has a concise syntax, and supports complex operations like filtering, sorting, and aggregation.

Basic Field Selection​

{
"order_id": $.workorder.id,
"title": $.workorder.title,
"status": $.workorder.status.name
}

Concatenating Fields​

{
"technician_name": $.workorder.assignee.first_name & " " & $.workorder.assignee.last_name,
"location": $.workorder.location.city & ", " & $.workorder.location.state
}

Conditional Logic​

{
"order_id": $.workorder.id,
"is_complete": $.workorder.status.name = "Work Done",
"priority": $.workorder.status.name = "At Risk" ? "high" : "normal",
"state_code": $.workorder.status.name = "Work Done" ? "6" :
$.workorder.status.name = "Approved" ? "7" : "2"
}

Accessing Arrays​

{
"work_order_id": $.workorder.id,
"po_number": $.workorder.custom_fields.results[name="PO Number"].value,
"tags": $.workorder.tags.results.name,
"has_priority_tag": "Priority" in $.workorder.tags.results.name
}

Built-in Functions​

{
"work_order_id": $string($.workorder.id),
"title_uppercase": $uppercase($.workorder.title),
"timestamp": $now(),
"scheduled_date": $substringBefore($.workorder.schedule.start.utc, "T")
}

Static JSON Merge​

For simpler use cases, merge static fields into every webhook payload:

{
"source": "field-nation",
"environment": "production",
"api_version": "3.0",
"integration_id": "your-integration-id"
}

This adds the static fields to the original payload without transforming it.


Dynamic URL Templates​

Include values from the webhook payload in your endpoint URL using template expressions.

Template Syntax​

https://api.example.com/workorders/{{$.workorder.id}}/updates

Templates use {{ expression }} syntax where expression is a JSONata path.

Common Patterns​

Route by Work Order ID
https://api.example.com/workorders/{{$.workorder.id}}/webhooks

Delivers to: https://api.example.com/workorders/12345/webhooks

Route by Company
https://api.example.com/clients/{{$.workorder.company.id}}/events

Delivers to: https://api.example.com/clients/100/events

Route by Region
https://{{$.workorder.location.country}}.api.example.com/webhooks

Delivers to: https://us.api.example.com/webhooks

Multiple Templates
https://api.example.com/{{$.workorder.company.id}}/workorders/{{$.workorder.id}}

Delivers to: https://api.example.com/100/workorders/12345

Restriction

Templates are not allowed in the domain/origin part of the URL for security reasons. https://{{$.malicious}}.example.com is not permitted.


Payload Field Reference​

All webhook events include these fields that you can use in transformations:

Root Level​

PathTypeDescription
$.event.namestringEvent name (e.g., workorder.status.work_done)
$.event.paramsobjectEvent-specific parameters
$.timestampstringISO 8601 timestamp when event occurred
$.triggered_by_user.idnumberUser ID who triggered the event

Work Order Core​

PathTypeDescription
$.workorder.idnumberUnique work order ID
$.workorder.titlestringWork order title
$.workorder.descriptionstringDetailed description
$.workorder.status.idnumberStatus ID
$.workorder.status.namestringStatus name

Company & People​

PathTypeDescription
$.workorder.company.idnumberBuyer company ID
$.workorder.company.namestringBuyer company name
$.workorder.manager.first_namestringManager first name
$.workorder.manager.last_namestringManager last name
$.workorder.assignee.idnumberAssigned provider ID
$.workorder.assignee.first_namestringProvider first name
$.workorder.assignee.last_namestringProvider last name

Location​

PathTypeDescription
$.workorder.location.citystringCity
$.workorder.location.statestringState/Province
$.workorder.location.zipstringZIP/Postal code
$.workorder.location.countrystringCountry code

Schedule & Pay​

PathTypeDescription
$.workorder.schedule.start.utcstringScheduled start (UTC)
$.workorder.schedule.end.utcstringScheduled end (UTC)
$.workorder.pay.typestringPay type (fixed, hourly, etc.)
$.workorder.pay.base.amountnumberBase pay amount

Custom Fields & Tags​

PathTypeDescription
$.workorder.custom_fields.resultsarrayCustom field objects
$.workorder.custom_fields.results[n].namestringField name
$.workorder.custom_fields.results[n].valuestringField value
$.workorder.tags.resultsarrayTag objects
$.workorder.tags.results[n].namestringTag name

Setting Up Payload Customization​

Step 1: Create or Edit a Webhook​

Navigate to Webhooks Dashboard and create a new webhook or edit an existing one.

Step 2: Enable Payload Override​

Check the "Override default payload" option to enable customization. This reveals a preview panel showing your custom payload configuration.

Enable Payload Customization

info

The payload customization workflow is identical whether you're creating a new webhook or editing an existing one. The only difference is clicking Create Webhook versus Update Webhook to save your changes.

Step 3: Open the Payload Editor​

Click Edit Payload to open the side drawer where you can write your transformation script.

Webhook Payload Sidedrawer

Step 4: Select Script Language​

Choose your transformation approach:

  • JSONata (recommended) — Dynamic expressions for complex transformations
  • JSON — Static field merge for simple additions

Step 5: Write Your Transformation Script​

Enter your JSONata expression or JSON object:

{
"ticket_id": $.workorder.id,
"title": $.workorder.title,
"status": $.workorder.status.name,
"technician": $.workorder.assignee.first_name & " " & $.workorder.assignee.last_name
}

Step 6: Preview Your Payload​

After saving in the side drawer, your transformation script appears in the preview panel. This shows what you've configured but hasn't been saved to the webhook yet.

Saved Payload Preview

Important

The preview only shows your local changes. You must click Create Webhook (for new webhooks) or Update Webhook (for existing webhooks) to persist your payload customization.

Step 7: Add Dynamic URL (Optional)​

If needed, update your webhook URL to include template expressions:

https://api.example.com/workorders/{{$.workorder.id}}

Step 8: Save and Test​

Save the webhook configuration and trigger a test event to verify the transformation works correctly.


Best Practices​

Start Simple​

Begin with basic field selection, then add complexity as needed:

// Start here
{ "id": $.workorder.id, "status": $.workorder.status.name }

// Then expand
{
"id": $.workorder.id,
"status": $.workorder.status.name,
"company": $.workorder.company.name,
"technician": $.workorder.assignee.first_name & " " & $.workorder.assignee.last_name
}

Handle Missing Fields​

Use the coalesce operator to provide defaults:

{
"assignee_name": $.workorder.assignee.first_name ?
($.workorder.assignee.first_name & " " & $.workorder.assignee.last_name) :
"Unassigned"
}

Test Before Production​

Use the webhook test feature to validate transformations before enabling in production.

Keep Original Payloads​

Original payloads are automatically preserved in Field Nation for debugging and re-delivery. You can access them through the delivery logs.

Debugging Tip

If a transformation fails, the original payload is still available in the delivery log details. Use this to diagnose and fix your script.


Troubleshooting​

Transformation produces empty payload

Cause: JSONata expression doesn't match payload structure.

Solution:

  • Check field paths match the actual payload structure
  • Use $.workorder.id not $.data.id
  • Verify the event includes the fields you're accessing
URL template not resolving

Cause: Template expression returns undefined or null.

Solution:

  • Verify the field exists in the payload
  • Check for typos in the path
  • Use a fallback: {{$.workorder.id ? $.workorder.id : 'default'}}
Script validation error

Cause: Invalid JSONata syntax.

Solution:

  • Check for missing quotes around strings
  • Verify bracket matching
  • Test your expression at try.jsonata.org
Fields appear as null

Cause: Accessing fields that don't exist for this event.

Solution:

  • Not all events include all fields (e.g., assignee is null before assignment)
  • Use conditional logic to handle missing data

API Configuration​

When creating or updating webhooks via API, include the webhookScript field:

curl -X POST https://api.fieldnation.com/api/v1/webhooks \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://api.example.com/workorders/{{$.workorder.id}}",
"method": "post",
"status": "active",
"events": ["workorder.status.work_done"],
"webhookScript": {
"scriptLanguage": "jsonata",
"script": "{ \"id\": $.workorder.id, \"status\": $.workorder.status.name }",
"enabled": true
}
}'

webhookScript Fields​

FieldTypeDescription
scriptLanguagestring"jsonata" or "json"
scriptstringThe transformation script
enabledbooleanToggle transformation on/off

Summary​

Payload customization eliminates the need for middleware by transforming data at the source:

CapabilityBenefit
JSONata transformationsRestructure data to match any system
Dynamic URLsRoute webhooks based on event content
Enable/disable toggleTest without deleting configurations
Original payload storageDebug with full context

Bottom line: Your webhooks, your format. No middleware required.