This guide covers everything you need to know about using webhooks in Uncanny Automator—from sending data to external services (outgoing webhooks) to receiving data and triggering recipes (incoming webhooks), including nested data, array workarounds, real API examples, and troubleshooting.
Table of Contents
- What Are Webhooks?
- Outgoing Webhooks: Send Data to a Webhook (Action)
- Incoming Webhooks: Receive Data from a Webhook (Trigger)
- Understanding Keys, Values, and Data Types
- Working with Nested Data
- Advanced: Complex Objects and Arrays
- Common Use Cases and Examples
- Troubleshooting
- Quick Reference Card
- Glossary
- Version History
What Are Webhooks?
A webhook is a way for one application to send real-time data to another application when something happens. Think of it like a notification system between apps.
Two Types in Uncanny Automator
| Type | Direction | When to Use |
|---|---|---|
| Outgoing Webhook (Action) | Your site → External service | Send data when something happens on your WordPress site |
| Incoming Webhook (Trigger) | External service → Your site | Receive data and trigger a recipe when an external service sends data to you |
Simple Analogy
- Outgoing Webhook: Like sending a text message to someone
- Incoming Webhook: Like receiving a text message from someone
Outgoing Webhooks: Send Data to a Webhook
Location: Actions → Webhooks → Send data to a webhook
Use this action to send data FROM your WordPress site TO an external service when a trigger fires.
Field Reference
URL (Required)
The destination URL where data will be sent.
Example values:
https://hooks.zapier.com/hooks/catch/123456/abcdef/
https://api.example.com/webhooks/receive
https://make.com/webhook/abc123
Tips:
- Must be a publicly accessible URL (not localhost in production)
- Supports tokens — you can use
{{user_email}}or other tokens in the URL - Must start with
https://orhttp://
Request Method (Required)
The HTTP method to use when sending the request.
| Method | When to Use |
|---|---|
| POST | Most common. Use when creating new data or sending form submissions |
| GET | Retrieving data. Parameters are sent in the URL query string |
| PUT | Updating/replacing existing data completely |
| PATCH | Partially updating existing data |
| DELETE | Removing data |
| HEAD | Same as GET but returns only headers, no body |
| OPTIONS | Checking what methods are allowed |
Default: POST (recommended for most webhooks)
Data Format (Required)
How the data in the Body section will be formatted when sent.
| Format | Content-Type Header | Best For |
|---|---|---|
| JSON | application/json |
Most APIs, Zapier, Make, modern services |
| x-www-form-urlencoded | application/x-www-form-urlencoded |
Traditional form submissions |
| form-data | multipart/form-data |
File uploads, legacy systems |
| XML | application/xml |
SOAP APIs, legacy enterprise systems |
| Text | text/plain |
Simple text content |
| HTML | text/html |
HTML content |
| GraphQL | application/graphql |
GraphQL APIs |
| Raw | application/octet-stream |
Binary or unformatted data |
Default: x-www-form-urlencoded
Important: The receiving service must accept your chosen format. When in doubt, use JSON.
Authorization (Optional)
Authentication credentials sent in the Authorization header.
Common patterns:
| Auth Type | Value to Enter |
|---|---|
| Bearer Token | Bearer your_api_token_here |
| Basic Auth | Basic base64_encoded_credentials |
| API Key | ApiKey your_key_here |
| Custom | Whatever the service requires |
Security Note: After saving, the value is masked with asterisks (e.g., ************abc). The original value is stored securely and used during execution.
Supports tokens: You can use tokens like {{custom_field_api_key}} if the API key is stored in user meta or a custom field.
Headers (Optional)
Additional HTTP headers to include with the request.
Default header added:
Accept: application/json
Common headers to add:
| Name | Value | Purpose |
|---|---|---|
Content-Type |
application/json |
Explicitly set content type |
X-API-Key |
your_api_key |
Alternative API key location |
X-Custom-Header |
custom_value |
Service-specific headers |
User-Agent |
Uncanny Automator/1.0 |
Identify the request source |
Note: The Authorization header is automatically added from the Authorization field — don’t duplicate it here.
Body (Required for most use cases)
The actual data being sent. Configured as key-value pairs.
See: Understanding Keys, Values, and Data Types
Outgoing Webhook Buttons
| Button | Purpose |
|---|---|
| Help | Opens documentation |
| Check data format | Preview how your data will be formatted before sending |
| Send test | Actually sends a test request and shows the response |
Recommendation: Always use “Send test” before going live to verify the destination accepts your data.
Incoming Webhooks: Receive Data from a Webhook
Location: Triggers → Webhooks → Receive data from a webhook
Requirement: Uncanny Automator Pro
Use this trigger to receive data FROM an external service TO your WordPress site, then run recipe actions.
Field Reference
Webhook URL (Read-only)
The unique URL that external services should send data to.
Format:
https://yoursite.com/wp-json/uap/v2/uap-{recipe_id}-{trigger_id}
Example:
https://example.com/wp-json/uap/v2/uap-3594-3614
Supported HTTP methods:
- POST (most common)
- GET
- PUT
Important: This URL is generated automatically and unique to each trigger. Copy it and paste it into the external service’s webhook configuration.
Data Format (Required)
How to parse the incoming data.
| Format | When to Select |
|---|---|
| Auto | Let Automator detect the format (recommended) |
| JSON | When you know the source sends JSON |
| x-www-form-urlencoded | Traditional form data |
| XML | When the source sends XML data |
| form-data | Multipart form data |
Default: Auto (recommended)
Tip: Auto works in most cases. Only change if you’re experiencing parsing issues.
Security Headers (Optional)
Headers that MUST be present and match for the webhook to be processed.
Use case: Verify that requests are legitimate by requiring a secret header.
Example configuration:
| Name | Value |
|---|---|
X-Webhook-Secret |
my_secret_key_12345 |
Authorization |
Bearer expected_token |
How it works:
- You define required headers here
- When a request arrives, Automator checks if these headers exist with the exact values
- If they don’t match, the request is ignored (returns 403)
Security tip: Always use security headers when the webhook is publicly accessible to prevent unauthorized triggers.
Fields (Required)
Define what data keys you expect to receive.
Two ways to configure:
- Manual: Add keys manually that match what the external service sends
- Get samples: Click the button to listen for a test webhook and auto-populate
See: Understanding Keys, Values, and Data Types
Headers (Extract Headers as Tokens)
Extract specific header values to use as tokens in your recipe.
Example: If the webhook sender includes a header X-User-ID: 12345, you can extract it:
| Header name |
|---|
X-User-ID |
This creates a token {{X-User-ID}} usable in your actions.
Response (Required)
What to send back to the service that called your webhook.
| Option | Description |
|---|---|
| Default | Returns {"status": "success"} with 200 OK |
| Custom | Define your own status code, content type, and body |
| Callable function | Use a PHP function to generate the response |
Custom Response Options
| Field | Description |
|---|---|
| Status code | HTTP status code (e.g., 200, 201, 204) |
| Content | The response body content |
| Content type | How to format the response (JSON, text, etc.) |
Example custom response:
- Status code:
200 - Content type:
JSON - Content:
{"received": true, "processed": "{{trigger_id}}"}
Callable Function
For advanced users who need dynamic responses:
// In your theme's functions.php or a custom plugin
function my_webhook_response( $response, $hooks, $recipe, $request ) {
// Custom logic here
return new WP_REST_Response(
array(
'status' => 'processed',
'recipe' => $recipe['ID'],
),
200
);
}
Then enter my_webhook_response in the Callable function field.
Incoming Webhook Buttons
| Button | Purpose |
|---|---|
| Get samples | Listens for 60 seconds for a test webhook, then auto-populates fields |
| Save | Save the trigger configuration |
Understanding Keys, Values, and Data Types
This section covers the most important concept for webhooks: how to define your data.
The Key-Value Concept
Webhooks send data as key-value pairs, like a dictionary or address book:
Key → Value
─────────────────────────
first_name → John
email → [email protected]
age → 30
is_active → true
In Automator’s interface:
| Key | Data Type | Value |
|---|---|---|
first_name |
Text | John |
email |
Text | [email protected] |
age |
Number | 30 |
is_active |
Boolean | true |
Data Types Explained
For Outgoing Webhooks (Sending Data)
| Type | What It Sends | Example Input | JSON Output |
|---|---|---|---|
| Text | A string of characters | Hello World |
"Hello World" |
| Number | A numeric value (integer or decimal) | 42.5 |
42.5 |
| Boolean | True or false | true or false |
true |
| NULL | Explicitly empty value | (any value) | null |
Text (Default)
Use for: Names, emails, descriptions, URLs, any general text.
Key: user_email
Type: Text
Value: {{user_email}}
Result: "user_email": "[email protected]"
Important: Even if the value looks like a number, selecting Text wraps it in quotes.
Key: phone
Type: Text
Value: 5551234567
Result: "phone": "5551234567" (as a string, not number)
Number
Use for: Ages, quantities, prices, IDs, counts.
Key: quantity
Type: Number
Value: 5
Result: "quantity": 5 (no quotes)
Key: price
Type: Number
Value: 19.99
Result: "price": 19.99
Warning: If the value is not a valid number, it may cause errors or be sent as 0.
Boolean
Use for: Yes/no values, flags, switches, opt-ins.
Accepted true values:
true1yes(converted totrue)
Accepted false values:
false0no(converted tofalse)
Key: subscribed
Type: Boolean
Value: true
Result: "subscribed": true (no quotes)
Key: is_verified
Type: Boolean
Value: 1
Result: "is_verified": true
NULL
Use for: Explicitly empty fields, clearing values in APIs.
Key: middle_name
Type: NULL
Value: (anything or empty)
Result: "middle_name": null
Note: NULL is different from an empty string. Some APIs treat them differently:
"field": null→ Field exists but has no value"field": ""→ Field exists with an empty string value- Field omitted → Field doesn’t exist
For Incoming Webhooks (Receiving Data)
| Type | What It Expects | Used For |
|---|---|---|
| Text | Any string value | General content, names, descriptions |
| Valid email format | Email addresses | |
| Integer | Whole numbers | Counts, IDs, quantities |
| Float | Decimal numbers | Prices, percentages |
| URL | Valid URL format | Links, file URLs |
The type you select helps Automator:
- Display the right icon for tokens
- Provide appropriate validation hints
- Categorize tokens in the token picker
Auto-detection (when using “Get samples”) generally follows these patterns:
- Contains
@and looks like email → Email - Valid URL format → URL
- Whole number → Integer
- Number with decimal → Float
- Everything else → Text
Using Tokens in Values
Tokens let you insert dynamic data from your trigger.
Syntax: {{token_name}}
Examples:
Key: user_email
Type: Text
Value: {{user_email}}
Key: order_total
Type: Number
Value: {{wc_order_total}}
Key: message
Type: Text
Value: New order from {{user_first_name}} {{user_last_name}}
Important: Token values are resolved at runtime. If a token is empty, an empty string is sent.
Working with Nested Data
Many APIs expect nested/hierarchical data structures. Automator supports this using the / separator in keys.
The / Separator
Use forward slash (/) to create nested objects.
Basic Nesting
Key: customer/name
Value: John Smith
Key: customer/email
Value: [email protected]
Produces JSON:
{
"customer": {
"name": "John Smith",
"email": "[email protected]"
}
}
Deep Nesting
Key: order/billing/address/street
Value: 123 Main St
Key: order/billing/address/city
Value: New York
Key: order/billing/address/zip
Value: 10001
Produces JSON:
{
"order": {
"billing": {
"address": {
"street": "123 Main St",
"city": "New York",
"zip": "10001"
}
}
}
}
Mixing Flat and Nested
Key: event_type
Value: purchase
Key: data/product_id
Value: 123
Key: data/quantity
Value: 2
Produces JSON:
{
"event_type": "purchase",
"data": {
"product_id": 123,
"quantity": 2
}
}
When Nesting Applies
Nesting with / works for these data formats:
- ✅ JSON
- ✅ XML
- ✅ GraphQL
- ❌ x-www-form-urlencoded (sent as flat
customer/name=value) - ❌ form-data (sent as flat)
- ❌ Text/Plain
Array Data
Currently, Automator sends key-value objects, not true arrays. To send array-like data, use numbered keys:
Key: items/0/name
Value: Product A
Key: items/0/qty
Value: 2
Key: items/1/name
Value: Product B
Key: items/1/qty
Value: 1
Produces:
{
"items": {
"0": {"name": "Product A", "qty": 2},
"1": {"name": "Product B", "qty": 1}
}
}
Note: This creates an object with numeric keys, not a true JSON array. Some APIs accept this, others don’t.
Advanced: Complex Objects and Arrays
Visual Guide: How Keys Map to JSON
YOUR AUTOMATOR CONFIGURATION RESULTING JSON
═══════════════════════════════════════════════════════════════════════════
FLAT (simple key-value):
Key: name ──► "name": "John"
Key: email ──► "email": "[email protected]"
NESTED (using / separator):
Key: user/name ──► "user": { "name": "John", ... }
Key: user/email ──►
DEEP NESTED:
Key: data/user/profile/name ──► "data": { "user": { "profile": { "name": "John" } } }
ARRAY-LIKE (using /0, /1, /2):
Key: tags/0 ──► "tags": { "0": "red", "1": "blue", "2": "green" }
ARRAY OF OBJECTS:
Key: items/0/name ──► "items": { "0": { "name": "...", "qty": ... }, "1": {...} }
Understanding JSON Structure Types
// 1. SIMPLE OBJECT - key-value pairs
{
"name": "John",
"email": "[email protected]"
}
// 2. NESTED OBJECT - objects within objects
{
"user": {
"profile": {
"name": "John"
}
}
}
// 3. ARRAY - ordered list of items
{
"tags": ["vip", "subscriber", "active"],
"items": [
{"id": 1, "name": "Product A"},
{"id": 2, "name": "Product B"}
]
}
Sending Complex Nested Objects
Example: E-commerce Order Payload
Target JSON structure:
{
"order": {
"id": "ORD-12345",
"status": "pending",
"customer": {
"id": 789,
"email": "[email protected]",
"name": {
"first": "John",
"last": "Smith"
},
"address": {
"billing": {
"street": "123 Main St",
"city": "New York",
"state": "NY",
"zip": "10001",
"country": "US"
},
"shipping": {
"street": "456 Oak Ave",
"city": "Los Angeles",
"state": "CA",
"zip": "90001",
"country": "US"
}
}
},
"totals": {
"subtotal": 99.99,
"tax": 8.50,
"shipping": 5.00,
"total": 113.49
},
"metadata": {
"source": "website",
"campaign": "summer_sale",
"notes": null
}
}
}
Automator Body Configuration:
| Key | Type | Value |
|---|---|---|
order/id |
Text | ORD-{{wc_order_id}} |
order/status |
Text | pending |
order/customer/id |
Number | {{user_id}} |
order/customer/email |
Text | {{user_email}} |
order/customer/name/first |
Text | {{user_first_name}} |
order/customer/name/last |
Text | {{user_last_name}} |
order/customer/address/billing/street |
Text | {{wc_order_billing_address_1}} |
order/customer/address/billing/city |
Text | {{wc_order_billing_city}} |
order/customer/address/billing/state |
Text | {{wc_order_billing_state}} |
order/customer/address/billing/zip |
Text | {{wc_order_billing_postcode}} |
order/customer/address/billing/country |
Text | {{wc_order_billing_country}} |
order/customer/address/shipping/street |
Text | {{wc_order_shipping_address_1}} |
order/customer/address/shipping/city |
Text | {{wc_order_shipping_city}} |
order/customer/address/shipping/state |
Text | {{wc_order_shipping_state}} |
order/customer/address/shipping/zip |
Text | {{wc_order_shipping_postcode}} |
order/customer/address/shipping/country |
Text | {{wc_order_shipping_country}} |
order/totals/subtotal |
Number | {{wc_order_subtotal}} |
order/totals/tax |
Number | {{wc_order_total_tax}} |
order/totals/shipping |
Number | {{wc_order_shipping_total}} |
order/totals/total |
Number | {{wc_order_total}} |
order/metadata/source |
Text | website |
order/metadata/campaign |
Text | {{utm_campaign}} |
order/metadata/notes |
NULL | |
Key insight: Each / creates a new nesting level. order/customer/name/first = 4 levels deep.
Working with Arrays
The Array Challenge
True JSON arrays look like this:
{
"tags": ["red", "blue", "green"],
"line_items": [
{"sku": "ABC", "qty": 2},
{"sku": "XYZ", "qty": 1}
]
}
Automator’s default behavior creates objects with numeric keys instead:
{
"tags": {
"0": "red",
"1": "blue",
"2": "green"
}
}
Solution 1: Numeric Index Keys (Object-Style Arrays)
Many APIs accept objects with numeric keys as arrays.
| Key | Type | Value |
|---|---|---|
tags/0 |
Text | red |
tags/1 |
Text | blue |
tags/2 |
Text | green |
Result:
{
"tags": {
"0": "red",
"1": "blue",
"2": "green"
}
}
Solution 2: Comma-Separated String
| Key | Type | Value |
|---|---|---|
tags |
Text | red,blue,green |
Result:
{
"tags": "red,blue,green"
}
Solution 3: JSON String in Value
| Key | Type | Value |
|---|---|---|
tags |
Text | ["red","blue","green"] |
Important: The array is sent as a STRING, not a real array. The receiving API must parse it.
Solution 4: Pre-built JSON Token
| Key | Type | Value |
|---|---|---|
line_items |
Text | {{wc_order_items_json}} |
Note: The token must output valid JSON. Use “Check data format” to verify.
Array of Objects
Target structure:
{
"contacts": [
{"email": "[email protected]", "name": "John", "role": "admin"},
{"email": "[email protected]", "name": "Jane", "role": "user"}
]
}
Configuration (Object-style):
| Key | Type | Value |
|---|---|---|
contacts/0/email |
Text | [email protected] |
contacts/0/name |
Text | John |
contacts/0/role |
Text | admin |
contacts/1/email |
Text | [email protected] |
contacts/1/name |
Text | Jane |
contacts/1/role |
Text | user |
Result:
{
"contacts": {
"0": {"email": "[email protected]", "name": "John", "role": "admin"},
"1": {"email": "[email protected]", "name": "Jane", "role": "user"}
}
}
Dynamic Arrays with Loopable Tokens
If your recipe/action supports loops, you can use a loop index token to build item collections.
| Key | Type | Value |
|---|---|---|
items/{{loop_index}}/sku |
Text | {{item_sku}} |
items/{{loop_index}}/name |
Text | {{item_name}} |
items/{{loop_index}}/quantity |
Number | {{item_qty}} |
items/{{loop_index}}/price |
Number | {{item_price}} |
Without loops, you’re limited to a fixed number of items or using a JSON token.
Common Use Cases and Examples
Example 1: Send User Registration to CRM
Scenario: When a user registers, send their data to a CRM.
| Field | Value |
|---|---|
| URL | https://api.crm.com/v1/contacts |
| Method | POST |
| Data Format | JSON |
| Authorization | Bearer sk_live_abc123 |
Body:
| Key | Type | Value |
|---|---|---|
email |
Text | {{user_email}} |
first_name |
Text | {{user_first_name}} |
last_name |
Text | {{user_last_name}} |
source |
Text | website_registration |
created_at |
Text | {{current_date}} |
Example 2: Send Order to Fulfillment Service
Scenario: When a WooCommerce order is placed, send to fulfillment.
| Field | Value |
|---|---|
| URL | https://fulfillment.example.com/api/orders |
| Method | POST |
| Data Format | JSON |
Body:
| Key | Type | Value |
|---|---|---|
order_id |
Number | {{wc_order_id}} |
customer/email |
Text | {{wc_order_billing_email}} |
customer/name |
Text | {{wc_order_billing_first_name}} {{wc_order_billing_last_name}} |
shipping/address |
Text | {{wc_order_shipping_address_1}} |
shipping/city |
Text | {{wc_order_shipping_city}} |
shipping/postal |
Text | {{wc_order_shipping_postcode}} |
total |
Number | {{wc_order_total}} |
Example 3: Receive Stripe Webhook
Scenario: Trigger a recipe when Stripe sends a payment event.
Trigger Configuration:
| Field | Value |
|---|---|
| Data Format | JSON |
| Security Headers | (Configure Stripe webhook signing in custom code) |
Fields:
| Key | Type |
|---|---|
type |
Text |
data/object/id |
Text |
data/object/amount |
Integer |
data/object/customer |
Text |
data/object/receipt_email |
Stripe sends:
{
"type": "payment_intent.succeeded",
"data": {
"object": {
"id": "pi_123",
"amount": 2000,
"customer": "cus_abc",
"receipt_email": "[email protected]"
}
}
}
Resulting tokens:
{{type}}=payment_intent.succeeded{{data/object/id}}=pi_123{{data/object/amount}}=2000{{data/object/customer}}=cus_abc{{data/object/receipt_email}}=[email protected]
Example 4: Zapier Integration
Outgoing to Zapier:
| Field | Value |
|---|---|
| URL | https://hooks.zapier.com/hooks/catch/123456/abcdef/ |
| Method | POST |
| Data Format | JSON |
Body:
| Key | Type | Value |
|---|---|---|
action |
Text | new_submission |
form_id |
Number | {{form_id}} |
user_email |
Text | {{user_email}} |
submission_data |
Text | {{form_all_fields}} |
Incoming from Zapier:
Configure your Fields to match what Zapier sends:
| Key | Type | Sample value |
|---|---|---|
zapier_event |
Text | spreadsheet_row_added |
row_data |
Text | {...} |
timestamp |
Text | 2024-01-15T10:30:00Z |
Troubleshooting
Outgoing Webhook Issues
“Webhook URL is not valid” Error
Causes:
- URL points to localhost, private IP, or internal network
- URL format is incorrect
- DNS cannot resolve the hostname
Solutions:
- Ensure URL is publicly accessible
- Check for typos in the URL
- Test the URL in a browser first
Request Timeout
Causes:
- Destination server is slow or unresponsive
- Network issues
Solutions:
- Default timeout is 30 seconds
- Contact the API provider to check their status
- Reduce payload size if sending large data
Wrong Data Format Received
Causes:
- Destination expects different format than selected
- Content-Type header mismatch
Solutions:
- Check API documentation for required format
- Use “Check data format” button to preview
- Try JSON format (most widely supported)
Authentication Failures (401/403)
Causes:
- Incorrect API key or token
- Wrong authorization format
- Expired credentials
Solutions:
- Verify credentials with the API provider
- Check the exact format required (Bearer, Basic, etc.)
- Generate new API credentials
Data Type Errors
Causes:
- Sending text when number expected
- Sending “true” as text instead of boolean
Solutions:
- Use “Check data format” to verify types
- Match types to API documentation
- Remember: Number sends
5, Text sends"5"
Incoming Webhook Issues
Webhook Not Triggering
Causes:
- Trigger is in Draft mode
- Security headers don’t match
- Wrong URL being called
- Recipe is not Live
Solutions:
- Set trigger to Live (not Draft)
- Verify the exact URL is being used
- Check security header values match exactly
- Ensure recipe is published and Live
“Get samples” Not Working
Causes:
- Trigger must be in Draft mode to collect samples
- Sample window is only 60 seconds
- Firewall blocking incoming requests
Solutions:
- Set trigger to Draft mode first
- Click “Get samples” then immediately send test webhook
- Check server firewall allows incoming POST requests
- Try from a different network/service
Fields Not Matching
Causes:
- Key names don’t match exactly (case-sensitive)
- Nested path syntax incorrect
- Data format mismatch
Solutions:
- Use “Get samples” to auto-detect exact keys
- Match case exactly:
User_Email≠user_email - For nested data, use
/separator:data/user/email
Empty Token Values
Causes:
- Key path doesn’t exist in payload
- Typo in key name
- Data structure changed
Solutions:
- Log the raw webhook body to see actual structure
- Re-run “Get samples” with current data
- Check if sender changed their payload format
General Debugging Tips
Enable Debug Logging
Add to wp-config.php:
define( 'AUTOMATOR_DEBUG_MODE', true );
Logs appear in the recipe log’s “Activity” section.
Check Recipe Logs
- Go to Automator → Logs
- Find the recipe run
- Check the Action/Trigger log details
- Look for error messages or response codes
Use “Send test” Button
- Fill in all fields
- Click “Send test”
- Review the response — success shows as green, errors as red
- Check response body for API error messages
Verify with External Tools
- Postman — Full API testing
- cURL — Command line testing
- webhook.site — Free webhook testing service
- RequestBin — Inspect incoming requests
Quick Reference Card
Outgoing Webhook Checklist
- URL is valid and publicly accessible
- Request method matches API requirements
- Data format matches what API expects
- Authorization credentials are correct
- Required headers are added
- Body keys match API field names exactly
- Data types are correct (Text vs Number vs Boolean)
- Nested paths use
/separator - “Send test” works successfully
Incoming Webhook Checklist
- Webhook URL copied to external service
- Data format set correctly (or Auto)
- Security headers configured (if needed)
- Fields match incoming data keys exactly
- “Get samples” run to verify field mapping
- Response type configured appropriately
- Trigger set to Live (not Draft) in production
- Recipe is published and Live
Data Type Quick Reference
| I Want to Send… | Use Type |
|---|---|
| Names, descriptions, any text | Text |
| Emails (as text) | Text |
| Whole numbers (1, 42, 1000) | Number |
| Decimal numbers (19.99, 3.14) | Number |
| Yes/No, On/Off, True/False | Boolean |
| “Clear this field” | NULL |
Common Nested Paths
| API Expects | Key to Use |
|---|---|
{"user": {"email": "..."}} |
user/email |
{"data": {"attributes": {"name": "..."}}} |
data/attributes/name |
{"contact": {"address": {"city": "..."}}} |
contact/address/city |
Array Patterns Quick Reference
| I Want to Create… | Keys to Use |
|---|---|
Simple array ["a","b","c"] |
items/0, items/1, items/2 |
| Array of objects | items/0/name, items/0/value, items/1/name, items/1/value |
| Nested array | data/tags/0, data/tags/1, data/tags/2 |
| Multiple levels | order/items/0/product/id, order/items/0/product/name |
Incoming Webhook Key Patterns
| Sender Sends… | Your Field Key |
|---|---|
{"user": {"email": "..."}} |
user/email |
{"data": {"object": {"id": "..."}}} |
data/object/id |
{"items": [{"sku": "..."}]} |
items/0/sku |
{"tags": ["a", "b"]} |
tags/0, tags/1 |
{"meta": {"custom_field": "..."}} |
meta/custom_field |
Glossary
| Term | Definition |
|---|---|
| Webhook | A URL that receives HTTP requests with data |
| Payload | The data sent in a webhook request |
| Endpoint | The URL path where a webhook is received |
| HTTP Method | The type of request (GET, POST, PUT, etc.) |
| Header | Metadata sent with the request (authentication, content type) |
| Body | The main content/data of the request |
| JSON | JavaScript Object Notation — a common data format |
| Token | A placeholder that gets replaced with actual data |
| Key | The name/identifier of a data field |
| Value | The actual data stored in a field |
| Nested Data | Data organized in a hierarchy (objects within objects) |
| REST API | A standard way for applications to communicate over HTTP |
| Object | A collection of key-value pairs: {"name": "John", "age": 30} |
| Array | An ordered list of items: ["apple", "banana", "cherry"] |
| Nested Object | An object containing other objects: {"user": {"name": "John"}} |
| Array of Objects | A list of objects: [{"id": 1}, {"id": 2}] |
| Path Separator | The / character used to access nested data: user/address/city |
| Index | The position of an item in an array, starting at 0: items/0, items/1 |
| Flat Structure | Data with no nesting: {"name": "John", "email": "[email protected]"} |
| Deep Nesting | Multiple levels of objects within objects |
| SSRF | Server-Side Request Forgery — a security attack prevented by URL validation |
Version History
- Document Version: 1.1
- Last Updated: January 2026
- Applies to: Uncanny Automator 6.x+ and Uncanny Automator Pro 6.x+
Changelog
v1.1 (January 2026)
- Added “Advanced: Complex Objects and Arrays” section
- Added visual diagrams for key-to-JSON mapping
- Added visual diagrams for incoming webhook data extraction
- Added real-world API examples (HubSpot, Mailchimp, Stripe, Slack, Airtable)
- Added array handling patterns and workarounds
- Added PHP filter example for true JSON arrays
- Expanded Quick Reference with array patterns
- Expanded Glossary with object/array terminology
v1.0 (January 2026)
- Initial release
Leave a Reply