Zapier - Invalid API Response - zapier

I'm integrating a CRM with Facebook lead Ads using Zapier, and I can create a lead in Facebook and create it in the CRM without any issues.
After a successful post (i.e. successfully creating the lead), I'm curious what I should be returning, I would have thought
return Ok();
would have been enough. Instead, I get an error message saying:
- Got a non-object result, expected an object from create ()
What happened (You are seeing this because you are an admin):
Executing creates.ZapLead.operation.perform with bundle
Invalid API Response:
- Got a non-object result, expected an object from create ()
What should I be returning?
Code which makes the post is:
perform: (z, bundle) => {
const promise = z.request({
url: 'https://{{bundle.authData.subdomain}}.ngrok.io/api/zapier/create/lead/' + bundle.inputData.lead_type + '/' + bundle.inputData.core_customerTypeId,
method: 'POST',
body: JSON.stringify({
fields: bundle.inputData
}),
headers: {
'content-type': 'application/json'
}
});
// return promise.then((response) => JSON.parse(response.content));
return promise.then((response) => {
if (response.status != 200) {
throw new Error(`Unexpected status code ${response.status}`);
}
});
Any ideas?
Thanks,

David here, from the Zapier Platform team.
While your answer is technically correct, I wanted to add some context about the error and why your solution works.
Zapier expects a javascript object (basically anything valid and wrapped in {}) to come out of a create function. That's why JSON.parse(response.content) works, it's returning whatever the server said. Your code throws an error if it's not a 200, but doesn't return anything if it is a 200. Since undefined is not of type Object, the error you're seeing is thrown.
While {"Success":"Success","Attempt":null,"Id":null,"RequestId":null} is totally a valid response (it's an object!), it's more useful for the end-user to return data about the new lead that was created. That way, it can be used downstream for other actions.
​Let me know if you've got any other questions!
As a side note, we're very open to how to make that error message more clear; it's one devs struggle with a lot.

I think I found it. Looks like I need to return this if successful:
{"Success":"Success","Attempt":null,"Id":null,"RequestId":null}

Related

What do I do with low Scores in reCAPTCHA v3?

I have set up reCAPTCHA v3 on my ASP.NET MVC project. Everything is working fine and is passing back data properly.
So the code below depends on another dll I have, but basically, the response is returned in the form of an object that shows everything that the JSON request passes back, as documented by https://developers.google.com/recaptcha/docs/v3
It all works.
But now that I know the response was successful, and I have a score, what do I do? What happens if the score is .3 or below? Some people recommend having v2 also set up for secondary validation (i.e. the 'choose all the stop signs in this picture' or 'type the word you see'). Is that really the only 'good' option?
Obviously the code isn't perfect yet. I'll probably handle the solution in the AJAX call rather than the controller, but still. What should I do if the score is low?
I read this article
reCaptcha v3 handle score callback
and it helped a little bit, but I'm still struggling to understand. I don't necessarily need code (although it would never hurt) but just suggestions on what to do.
VIEW:
<script src="https://www.google.com/recaptcha/api.js?render=#Session["reCAPTCHA"]"></script>
grecaptcha.ready(function () {
grecaptcha.execute('#Session["reCAPTCHA"]', { action: 'homepage' }).then(function (token) {
$.ajax({
type: "POST",
url: "Home/Method",
data: JSON.stringify({token: token }),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (response) {
console.log('Passed the token successfully');
},
failure: function (response) {
alert(response.d);
}
});
});
});
CONTROLLER:
[HttpPost]
public void ReCaptchaValidator(string token)
{
ReCaptcha reCaptcha = new ReCaptcha();
Models.ReCaptcha response = new Models.ReCaptcha();
response = reCaptcha.ValidateCaptcha(token);
//response returns JSON object including sucess and score
if (response.Success)
{
//WHAT DO I DO HERE????
}
}
Ended up getting the answer from another forum. Basically, the answer is "anything you want". There is no right or wrong when handing a successful response.
So what could be done, is if the response is successful and CAPTCHA doesn't throw a flag, do nothing. But if CAPTCHA is unhappy, you could display an alert or a banner that says 'could not process', or you could even add in CAPTCA version 2, which would make them do the picture test or the 'I am not a robot' checkbox, etc.

Cant find information about acceptable response from my site to zapier app on test step (It's "Action" on my site )

I can't find information about acceptable response content or code status from my site to zapier app on test step.
I have my site on Laravel and Zapier app for this site. In my Zapier app I have an action: "Create New Project". I made my "create" according to the example. Everything works except the testing step. I tested with the following zap:
Trello -> "New card created" trigger. Test successful.
My app -> "Create new project". Test fails with We had trouble sending your test through. Could not handle special, non-standard characters. Please contact support.
Strangely, the project was created successfully. Therefore, I think the problem lies in the response from my site to zapier:
// creates/project.js
// My perform function:
perform: (z, bundle) => {
const promise = z.request({
url: `${process.env.BASE_URL}/api/folder`,
method: 'POST',
body: JSON.stringify({
title: bundle.inputData.title,
}),
headers: {
'content-type': 'application/json',
}
});
return promise.then((response) => JSON.parse(response.content));
}
//ZapierController.php
public function addFolder(Request $request)
{
// Made record to DB, and other, after this returned same data which in request
return response()->json(['title' => $request['title']]);
}
Expected result - successful test on "Test this step". Can anyone help me?
David here, from the Zapier Platform team.
I already answered your support ticket, but I figured I'd reply here in case anyone else has the same issue.
The root problem is made clear when you run zapier logs on the cli:
== Log
Unhandled error: CheckError: Invalid API Response:
- Got a non-object result, expected an object from create ("title")
What happened:
Executing creates.сFolder.operation.perform with bundle
Invalid API Response:
- Got a non-object result, expected an object from create ("title")
Your server can reply with any 2xx status code, but the output needs to be valid json. Something like {"title": "my title here"} would certainly work. Users find it more helpful to get info about the project they just created, so the name, id, etc would be even better.
As for why this surfaced as a character encoding issue, I have no clue. We plan on getting to the bottom of it though!

"message" : "Internal server error" issue with Lambda/API Gateway and iOS

I've set up a lambda function and created some GET and POST methods inside the API Gateway which seem to work fine when testing them inside the web application.
I am then trying to call the functions inside an iOS application which is set up using the mobile hub. The functions also work inside the testing facility via the mobile hub perfectly fine, however when I actually test the functions inside the app I get:
"message" : "Internal server error"
I know the error is not much to work from, but I can't figure out a way to get a more detailed error description.
Any ideas?
This may happen because your Lambda function is not set to return a HTTP status code.
Changing from
exports.handler = (event, context, callback) => {
callback(null, 'Hello from Lambda');
};
to
exports.handler = (event, context, callback) => {
callback(null, { statusCode: 200, body: 'Hello from Lambda' });
};
Should fix the issue.
The JSON.stringify() solved my issue. The response.body needs to be in String format and not as JSON. I hope this helps.
exports.sendRes = (body, status = 200) => {
var response = {
statusCode: status,
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(body)
};
return response;
};
I had the same issue with the following code:
exports.handler = async event => {
console.log("hello world");
return {
statusCode: 200,
body: event
};
};
To fix all I had to do was JSON.stringify() the body.
exports.handler = async event => {
console.log("hello world");
return {
statusCode: 200,
body: JSON.stringify(event), // <-- here
};
};
I had this problem until I click in "Deploy API" under the "Actions" button.
The other possible reason could be the payload/request/response limits on API Gateway (10MB) and/or Lambda (6MB)
None of the above answers worked for me. I was having a permission issue. Below is how I solved it.
Context
This is my lambda function:
exports.handler = function(event, context, callback) {
callback(null, {
statusCode: '200',
body: JSON.stringify({ 'message': 'hello world' }),
headers: {
'Content-Type': 'application/json',
},
});
};
I used terraform to provision api gateway and lambda. I used the example code provided by this blog post.
Diagnosis
In the lambda console I ran a test event on my lambda. As my lambda was super basic I used the hello world test template, named, and saved it. The test return success.
I checked cloudwatch logs, but couldn't find anything of use. I'm new to AWS so wasn't sure if I had to set anything up.
In the api gateway console I ran a test event. I just added Content-Type:application/json to the headers of the event and ran the test. For whatever weird reason the test results returned on the right side of the browser so had to scroll to the right to see them.
I got this result: Execution failed due to configuration error: Invalid permissions on Lambda function
SOLUTION
I checked the basic terraform example for api gateway and lambda integration here and noticed I was missing the aws_lambda_permission resource. This is needed to give permission to api gateway to invoke the lambda function.
For those that aren't using terraform here is a link to the aws docs on how to create the appropriate permissions.
please try to
Give execute lambda permission API Gateway
tick checkbox : Use Lambda Proxy integration
Handle null pointer for query string, headers & body.
I solved the issue by adding "isBase64Encoded": False/True to my lambda response
results = {
"statusCode": 200,
"headers": {"Content-Type": "application/json"},
"body": json.dumps(res),
"isBase64Encoded": False
}
In my case, the issue resolved while adding the integration Response and redeploying API

difference between fetching page and file in serviceworker

event.respondWith(caches.match(event.request).then(function (response) {
if (response) {
return response;
}
//return fetch(event.reuqest, { credentials: 'include' });
//event.respondWith(fetch(event.request, { credentials: 'include' }));
}));
This is a common code for handling request via serviceworkers , if the url is in cache then return cache response or fetch it from server .
But my doubt is regarding the 2 commented lines , we need to use one of them for fetching the response .
My doubt is, when i use event.respondWith(fetch(event.request, { credentials: 'include' for fetching a page , i get the following error
DOMException: Failed to execute 'respondWith' on 'FetchEvent': The fetch event has already been responded to.
But the page is finally rendered , definitely browser is finally fetching the response , but when i use sam for fetching an image , i get the same error and on top of that the image is not fetched .
if i use the second option that return fetch(event.reuqest, { credentials: 'include' }); , then it works fine for both image as well as page.
I am not able to figure out what is the reason of that error , and also why it is behaving differently for file and page .
My another doubt is , do i actually need the credential parameter here ,i added it because most of the implementations i saw in web have used it,but what i have observed is that the request object already has a credential property with it , now it is not always
include
sometime it is
same-origin
too.
So could it happen that i am actually overriding the actual credential value by adding it .If that is not the case , then there is no difference in including it or not.It does not matter .
But if it is other way around , then we should not overwrite the credential value, which can have bad side effects.
You already have a call to event.respondWith, you don't need to call it twice.
Your first call is going to use the promise returned by:
caches.match(event.request).then(function(response) {
if (response) {
return response;
}
return fetch(event.reuqest, { credentials: 'include' });
})
This promise resolves to:
response, if the request is in the cache;
the promise returned by the call to fetch, otherwise.
The promise returned by fetch will resolve to a response, which is then going to be used by respondWith.

Looking for paradigm to use for generic error handling in Angular from a JSON response from Rails

I'm building an app which is architected as a Rails server app providing RESTful api's to the client. The Rails server uses RABL. The client is an Angular JS client performing standard $http calls (gets, puts, etc).
Occasionally my Rails server will produce an error (let's say validation error attached to the object) or even no error in which case I would want to display something to the user - either the errror e.g., "The record did not save because..." or "The record was updated successfully".
I'm trying to map out a pattern on both the Rails side and the Angular/client side to handle this.
As for Rails:
I can certainly pass back a node in each of my RABL files to contain error arrays
I can also return different RABL by checking in the controller before returning
Most suggest using http codes (which makes sense) as per here (although there doesn't seem to be a consistent usages of the codes for something like a validation error).
As for Angular:
I suppose I can write a response interceptor but not sure how that would fully get flushed out.
I guess I'm hoping that I don't have to reinvent the wheel here and someone can point me to a pattern that's currently used and suggested (and localized).
I went ahead and implemented what I thought needed to be done. Thanks for digger69 for some help with this.
On the Rails side, I went with using an http status code. As per here I agreed with using a 400 http status code for error validation.
In my controllers I now have something like the following:
def create
my_obj = MyObj.build_with_params(params)
if my_obj.save
respond_with(my_obj) # regular RABL response
else
respond_with_errors(my_obj.errors)
end
end
In my application_controller.rb I defined a common method respond_with_errors
# respond back to the client an http 400 status plus the errors array
def respond_with_errors(errors)
render :json => {:errors => errors}, :status => :bad_request
end
Note that the :bad_request symbol is already defined for Rails as per here
On the client side I needed to intercept http calls (not only for validation but for authentication failures too (and probably more). Here is an example of my code in Angular (thanks to this post for the help with that):
var interceptor = ['$rootScope', '$q', function (scope, $q) {
function success(response) {
return response;
}
function error(response) {
var status = response.status;
if (status == 401) { // unauthorized - redirect to login again
window.location = "/";
} else if (status == 400) { // validation error display errors
alert(JSON.stringify(response.data.errors)); // here really we need to format this but just showing as alert.
} else {
// otherwise reject other status codes
return $q.reject(response);
}
}
return function (promise) {
return promise.then(success, error);
}
}];
$httpProvider.responseInterceptors.push(interceptor);
I now can be consistent with my rails code and deal with success returns from http calls on the client. I'm sure I have some more to do, but I think this gives a localized solution.
Use an HTTP response interceptor. I am currently using that successfully in an application.
http://docs.angularjs.org/api/ng.$http
From the documentation:
$provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {
return function(promise) {
return promise.then(function(response) {
// do something on success
}, function(response) {
// do something on error
if (canRecover(response)) {
return responseOrNewPromise
}
return $q.reject(response);
});
}
});
$httpProvider.responseInterceptors.push('myHttpInterceptor');
In my case I created a feedback service, which displays either success or error messages globally. An other option would be to broadcast the responses on the rootscope.

Resources