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.