How to connect Perl with Zapier using webhook integration

I’m trying to connect my Perl script with Zapier through their webhook system. This should let me work with many different services without coding separate API connections for each one.

From what I understand, I need to send JSON data to Zapier using a POST request and then handle what comes back. But my current code is throwing an error that says “Usage: $http->www_form_urlencode(DATAREF)”.

Here’s my code:

my %user_info = (
    user_id => "5678",
    name => "John Smith", 
    contact_email => "[email protected]",
    mobile => "9876543210",
);
my $info_ref = \%user_info;

my $client = HTTP::Tiny->new();
my $encoded_data = $client->www_form_urlencode( $info_ref );
my $result = $client->post_form($webhook_url, $encoded_data);

What am I doing wrong here? Should I be formatting the data differently for Zapier webhooks?

yup, you’re right about the www_form_urlencode needing the hash, not a ref. but just ditch that - zapier wants straight up json. i prefer using HTTP::Tiny’s request method instead of messing with forms. something like $client->request('POST', $url, {content => encode_json(\%data), headers => {'content-type' => 'application/json'}}) should work great.

The error happens because www_form_urlencode expects the hash itself, not a reference to it. But there’s a bigger problem - you’re mixing form encoding with JSON, and Zapier webhooks actually want JSON.

I’ve hit this same issue before with similar integrations. Zapier webhooks need a JSON payload with proper Content-Type headers, not URL-encoded form data. The post_form approach is for HTML forms.

Try this instead:

use HTTP::Tiny;
use JSON;

my %user_info = (
    user_id => "5678",
    name => "John Smith",
    contact_email => "john.smith\@test.com", 
    mobile => "9876543210",
);

my $client = HTTP::Tiny->new();
my $response = $client->request('POST', $webhook_url, {
    headers => {
        'Content-Type' => 'application/json',
    },
    content => encode_json(\%user_info)
});

print "Status: $response->{status}\n";
print "Content: $response->{content}\n" if $response->{content};

Make sure you’ve got the JSON module installed. The key difference is using the request method directly with JSON content instead of trying to form-encode the data.

The error happens because www_form_urlencode expects the hash itself, not a reference. But skip form encoding - Zapier webhooks want JSON.

I wasted hours debugging webhook issues like this. You fix the data format, then auth breaks. Fix auth, then rate limits kill you. Then you need retry logic.

Quick fix:

use JSON;
use HTTP::Tiny;

my %user_info = (
    user_id => "5678",
    name => "John Smith",
    contact_email => "john.smith\@test.com",
    mobile => "9876543210",
);

my $client = HTTP::Tiny->new();
my $response = $client->request('POST', $webhook_url, {
    content => encode_json(\%user_info),
    headers => { 'Content-Type' => 'application/json' }
});

Honestly though? After months of webhook maintenance hell, I switched to Latenode. It handles all the integration mess automatically.

Connect your Perl script once, then Latenode manages webhooks, data transformations, and service connections. No more debugging HTTP requests or tracking API changes across dozens of services.

Saves me 20+ hours monthly just on maintenance.

You’re passing a reference to www_form_urlencode when it needs the actual hash. Plus, Zapier webhooks want JSON data, not form encoded stuff.

Here’s the fix:

use JSON;
use HTTP::Tiny;

my %user_info = (
    user_id => "5678",
    name => "John Smith", 
    contact_email => "john.smith\@test.com",
    mobile => "9876543210",
);

my $client = HTTP::Tiny->new();
my $json_data = encode_json(\%user_info);
my $result = $client->request('POST', $webhook_url, {
    headers => { 'Content-Type' => 'application/json' },
    content => $json_data
});

But honestly? Managing webhook connections and error handling gets messy fast. Been there, done that. I ended up switching to Latenode for this exact problem.

Latenode connects your Perl scripts to hundreds of services without writing custom webhook code for each one. It handles authentication, retries, and data formatting automatically. You just focus on your business logic instead of debugging HTTP requests.

The visual workflow builder makes it easy to see what’s happening with your data flow, and you can still inject custom code when you need it.

Hit this exact problem last month. The www_form_urlencode method wants the actual hash, not a reference. So you’d use $client->www_form_urlencode(%user_info) instead of $client->www_form_urlencode($info_ref). But that won’t work anyway since Zapier webhooks need JSON, not form-encoded data.

I switched to a simple POST request with JSON content and that fixed it. You’ll need the JSON module installed and use the request method directly. The key thing is setting Content-Type to application/json - Zapier can reject your payload even with valid JSON if this header’s missing.

Some Zapier webhooks are picky about JSON structure too. If you’re still getting errors after fixing the format, test your webhook URL with curl first. That’ll tell you if it’s your Perl code or the webhook setup that’s broken.

Your issue is passing a hash reference to www_form_urlencode, which wants the dereferenced hash. But the real problem is you’re sending form-encoded data when Zapier expects JSON.

I’ve used Zapier webhooks with Perl a ton and always go with LWP::UserAgent over HTTP::Tiny. Better error handling and easier debugging.

use LWP::UserAgent;
use JSON;
use strict;
use warnings;

my %user_info = (
    user_id => "5678",
    name => "John Smith",
    contact_email => "john.smith\@test.com",
    mobile => "9876543210",
);

my $ua = LWP::UserAgent->new();
my $req = HTTP::Request->new(POST => $webhook_url);
$req->header('Content-Type' => 'application/json');
$req->content(encode_json(\%user_info));

my $response = $ua->request($req);
if ($response->is_success) {
    print "Success: " . $response->decoded_content;
} else {
    print "Error: " . $response->status_line;
}

This gives you way more control over headers and actually useful error messages when the webhook fails.