any update on this integration, wish to contribute
Really like to have Zapier integration…
Sure enough it’s here on the request wish todo list Integration to Zapier · Issue #9943 · frappe/erpnext · GitHub
But not here on the bounty list https://erpnext.org/bounties
Hello everyone,
I recently published the first ERPNext app for Zapier.
Features:
- Search all records in ERPNext.
- Create a new record in ERPNext with data from any Zapier app.
- Trigger any Zapier app when something happens in ERPNext.
- Works for all DocTypes. (Especially well for Leads and Opportunities.)
Please email me about a custom integration (raffael@alyf.de / German Website) and feel free to contribute on Github.
Best regards,
Raffael
Hi
I cannot seem to see this app on Zapier.
Hi Olamide,
you are correct, it’s not a public app on zapier. You have to deploy it as a private app. This has the following reasons:
-
ERPNext has no single API (like Facebook) but, in contrast, everybody has his own ERPNext instance with his own API and oAuth clients.
-
I’m not the ERPNext foundation, so I should not publish an app in their name.
The consequence is, that you have to deploy the app privately to Zapier, using the Zapier command line interface tool.
Afterwards, “ERPNext v0.0.1” will appear in your list of available apps on Zapier.
If you cannot deploy the app on your own, I’ll be happy to help. (raffael@alyf.de)
Best regards,
Raffael
Hi-Is your app limited to only Leads and opportunities? e.g if we wanted to do the following use cases
Sales invoice creation on My ERP instance> Zapier>Messaging App e.g Twillo or ZipWhip or
Appointment created on myERPNext instance> Zapier> Integrated Zapier chatbot
What changes to this app do we need to make?
It’s not limited to a specific DocType. You can can create a trigger for any event of any DocType. For example, on_submit of Sales Invoice. No changes required.
@MichaelPinkowski let’s see if we can get the team to take a look at the Zapier capabilities. There are so many potential uses for this, it could accelerate some of our customer adoption.
I’m using Zapier actions to accomplish the following:
- Listen via webhook for a transaction from a marketplace site
- Call the marketplace api to get some order details
- Parse and error check
- Construct a json object to create a new Sales Invoice in ERPNext
The new token-based authentication in ERPNext V11 made it possible. Trying to authenticate in prior versions was problematic.
Sure, I’ll put something together.
Mike
Hi,
I’ve been away at my son’s wedding, sorry for the delay.
Creating a record via Zapier
This works with ERPNext v11, as we’re relying on the API Access feature of the User DocType to give us token-based authentication
-
Generate API Access keys in ERPNext. Good process would be to create a Zapier user dedicated to this purpose. You will need the API Key and API Secret
-
In Zapier, add a Webhook Action to your zap. This should be after the point in your zap that you’ve rendered all of the necessary data that you will be writing to ERPNext.
-
Use the “Custom Request Action”.
-
Method = “Post” if you’re creating a new record
-
URL like https://erp.yoursite.com/api/resource/Sales Invoice for creating a Sales invoice
-
For “Data”, enter the raw json to create the record. What I did was to use Postman to read a Sales Invoice, then pare the json down to the fields I needed. I then validated the json using one of the web tools avalable to make sure I didn’t drop any braces, etc. To learn and play, start with a simple DocType first, like a Customer or an Item
-
You need three headers: Content-Type = application/json, Accept = application/json and Authorization. Authorization is “token {apikey}:{apisecret}”, (token space apikey colon apisecret) like
token 819abcxxxxx558e:4da5xxxxxxxx292
Hope that helps!
Mike
@Mike_Z Interesting idea to use raw requests. Did you also try to use the app? If so, what were problems that you encountered?
@flexy2ky Heres a guide on how to set up the app:
@rmeyer I was already pulling marketplace transactions into a Google sheet for erpnext import with a zap, so replacing it with a custom webhook post was easy.
Here’s an actual json construct for Zapier. All elements in double braces represent Zapier data from prior steps. A lot of the data is fixed, such as currency, naming_series, etc.
{
“naming_series”: “REV-”,
“company”: “Safe Haven Music”,
“posting_date”: “{{52735607__output}}”,
“currency”: “USD”,
“conversion_rate”: 1,
“selling_price_list”: “Standard Selling”,
“price_list_currency”: “USD”,
“plc_conversion_rate”: 1,
“base_net_total”: {{54716025__total__amount}},
“base_grand_total”: {{54716025__direct_checkout_payout__amount}},
“grand_total”: {{54716025__direct_checkout_payout__amount}},
“debit_to”: “1310 - Acct Receivable - SHM”,
“customer”: “Reverb Customer”,
“is_pos”: 1,
“pos_profile”: “Reverb”,
“due_date”: “{{52735607__output}}”,
“update_stock”: 1,
“base_total”: {{54716025__total__amount}},
“total”: {{54716025__total__amount}},
“net_total”: {{54716025__total__amount}},
“status”: “Draft”,
“market_place_order_id”:“{{54716025__order_number}}”,
“items”: [
{
“base_amount”: {{54716025__amount_product__amount}},
“qty”: 1,
“rate”: {{54716025__amount_product__amount}},
“cost_center”: “Main - SHM”,
“stock_uom”: “Each”,
“item_name”: “{{63048145__output}}”,
“amount”: {{54716025__amount_product__amount}},
“conversion_factor”: 1,
“warehouse”: “Retail Store - SHM”,
“uom”: “Each”,
“description”: “{{63048145__output}}”,
“base_rate”: {{54716025__amount_product__amount}},
“item_code”: “{{54716025__sku}}”,
“income_account”: “4110 - Product Sales - SHM”,
“expense_account”: “5110 - Cost of Goods Sold - SHM”
}
],
“taxes”: [
{
“cost_center”: “Main - SHM”,
“charge_type”: “Actual”,
“description”: “Reverb Shipping Label per Order (neg)”,
“account_head”: “5166 - Shipping Labels - SHM”,
“tax_amount”: -{{62410989__output}}
},
{
“cost_center”: “Main - SHM”,
“charge_type”: “Actual”,
“description”: “Reverb Processing Fee per Order (neg)”,
“account_head”: “5162 - Processing Fees - SHM”,
“tax_amount”: -{{54716025__direct_checkout_fee__amount}}
},
{
“cost_center”: “Main - SHM”,
“charge_type”: “Actual”,
“description”: “Reverb Selling Fee per Order (neg)”,
“account_head”: “5164 - Selling Fees - SHM”,
“tax_amount”: -{{54716025__selling_fee__amount}}
},
{
“cost_center”: “Main - SHM”,
“charge_type”: “Actual”,
“description”: “Reverb Bump Fees per Order (neg)”,
“account_head”: “5164 - Selling Fees - SHM”,
“tax_amount”: -{{62410764__output}}
},
{
“cost_center”: “Main - SHM”,
“charge_type”: “Actual”,
“description”: “Amount Collected from Customer for Shipping (pos)”,
“account_head”: “4115 - Shipping Sales - SHM”,
“tax_amount”: {{54716025__shipping__amount}}
}
],
“payments”: [
{
“account”: “Reverb Bucks - SHM”,
“mode_of_payment”: “{{54716025__payment_method}}”,
“default”: 0,
“amount”: {{54716025__direct_checkout_payout__amount}},
“type”: “Bank”
}
]
}<
Thanks a lot for the installation guide. I was able to deploy the app successfully but when trying to test a zap by sending a mail on submit for Purchase Order, I get this error:
Response: { “exc”: “["Traceback (most recent call last):\n File \"/home/saandb/frappe-bench/apps/frappe/frappe/app.py\", line 60, in application\n response = frappe.api.handle()\n File \"/home/saandb/frappe-bench/apps/frappe/frappe/api.py\", line 116, in handle\n data = json.loads(frappe.local.form_dict.data)\n File \"/usr/lib/python3.6/json/init.py\", line 348, in loads\n ‘not {!r}’.format(s.class.name))\nTypeError: the JSON object must be str, bytes or bytearray, not ‘NoneType’\n"]” } What happened (You are seeing this because you are an admin): Starting POST request to http://dev.flexcomsystems.net/api/resource/Webhook Received 500 code from http://dev.flexcomsystems.net/api/resource/Webhook after 77ms Received content “{“exc”:”["Traceback (most recent call last):\n File \"/home/saandb/frappe-bench/apps/frappe/fra" Response: { “exc”: “["Traceback (most recent call last):\n File \"/home/saandb/frappe-bench/apps/frappe/frappe/app.py\", line 60, in application\n response = frappe.api.handle()\n File \"/home/saandb/frappe-bench/apps/frappe/frappe/api.py\", line 116, in handle\n data = json.loads(frappe.local.form_dict.data)\n File \"/usr/lib/python3.6/json/init.py\", line 348, in loads\n ‘not {!r}’.format(s.class.name))\nTypeError: the JSON object must be str, bytes or bytearray, not ‘NoneType’\n"]” } Console logs: POST :censored:29:de49cbe66a:/api/resource/Webhook returned HTTP 500: Headers: { “Content-Type”: “application/json”, “user-agent”: “Zapier”, “Authorization”: “:censored:6:c2dc31949c: :censored:30:0d49aa3da6:”, “Accept”: “application/json” } Params: undefined Body: “{"request_url":"https://zapier.com/hooks/standard/5479441/7e2e677530104e6bb8358481a6b1679b/\",\“webhook_doctype\”:\"Purchase Order","webhook_docevent":"on_submit","webhook_data":[{"fieldname":"name","key":"id"}]}” Stack trace: “exc”: “["Traceback (most recent call last):\n File \"/home/saandb/frappe-bench/apps/frappe/frappe/app.py\", line 60, in application\n response = frappe.api.handle()\n File \"/home/saandb/frappe-bench/apps/frappe/frappe/api.py\", line 116, in handle\n data = json.loads(frappe.local.form_dict.data)\n File \"/usr/lib/python3.6/json/init.py\", line 348, in loads\n ‘not {!r}’.format(s.class.name))\nTypeError: the JSON object must be str, bytes or bytearray, not ‘NoneType’\n"]” } mustBe200 (/var/task/middleware/response.js:57:11) Object.collector.then.newOutput (/var/task/node_modules/zapier-platform-core/src/middleware.js:80:37) bound (domain.js:301:14) Object.runBound (domain.js:314:12) Object.tryCatcher (/var/task/node_modules/bluebird/js/release/util.js:16:23) Promise._settlePromiseFromHandler (/var/task/node_modules/bluebird/js/release/promise.js:512:31) Promise._settlePromise (/var/task/node_modules/bluebird/js/release/promise.js:569:18) Promise._settlePromise0 (/var/task/node_modules/bluebird/js/release/promise.js:614:10) Promise._settlePromises (/var/task/node_modules/bluebird/js/release/promise.js:693:18) Async._drainQueue (/var/task/node_modules/bluebird/js/release/async.js:133:16) Async._drainQueues (/var/task/node_modules/bluebird/js/release/async.js:143:10) Immediate.Async.drainQueues (/var/task/node_modules/bluebird/js/release/async.js:17:14) runCallback (timers.js:794:20) tryOnImmediate (timers.js:752:5) processImmediate [as _immediateCallback] (timers.js:729:5)
Now I can’t even test connection
Check your json. In Zapier, look at Task History to see the json you’re sending to ERPNext. Copy it and paste it into a json validator, like jsonlint.com
Couple of things I encountered were:
Undefined data - look for curly brace elements in your json. there shouldn’t be any. Here’s a missing item_code
“item_code”: “{{54716025__sku}}”,
Quotes. Make sure you have double quotes around every Zapier element that’s not a numeric. Including dates
Pleas format the error message so everybody can read it
Traceback (most recent call last):
File \"/home/saandb/frappe-bench/apps/frappe/frappe/app.py\", line 60, in application
response = frappe.api.handle()
File \"/home/saandb/frappe-bench/apps/frappe/frappe/api.py\", line 116, in handle
data = json.loads(frappe.local.form_dict.data)
File \"/usr/lib/python3.6/json/init.py\", line 348, in loads
‘not {!r}’.format(s.class.name))
TypeError: the JSON object must be str, bytes or bytearray, not ‘NoneType’
What happened (You are seeing this because you are an admin):
Starting POST request to http://dev.flexcomsystems.net/api/resource/Webhook
Received 500 code from http://dev.flexcomsystems.net/api/resource/Webhook after 77ms
Console logs:
POST http://dev.flexcomsystems.net/api/resource/Webhook returned HTTP 500:
Headers: {
"Content-Type": "application/json",
"user-agent": "Zapier",
"Authorization": ":censored:6:c2dc31949c: :censored:30:0d49aa3da6:",
"Accept": "application/json"
}
Params: undefined
Body:
{
"request_url": "https://zapier.com/hooks/standard/xxxxxxxx/xxxxxxxxxx/",
"webhook_doctype": "Purchase 1 Order",
"webhook_docevent": "on_submit",
"webhook_data": [
{
"fieldname":"name",
"key":"id"
}
]
}
This seems to be a general bug in frappe – it’s not possible to create new documents via the API at the moment:
Hi. I’m also facing this issue with the Zapier app. I’m running into the same issue. When creating leads using zapier I get the error below. Running V 11.1.61. Would appreciate some assistance
What happened(You are seeing this because you are an admin):
Starting POST request to https: //erp.co.ke/api/resource/Lead
Received 500 code from https: //erp.co.ke/api/resource/Lead after 287ms
Received content "<html> <
head >
<
title > Internal Server Error < /title> <
/head> <
body >
<
h1 > < p > Internal Serv "
Expected a JSON response.Got undefined.
Console logs:
Stack trace:
mustBeJson(/var/task / middleware / response.js: 25: 11)
Object.collector.then.newOutput(/var/task / node_modules / zapier - platform - core / src / middleware.js: 80: 37)
bound(domain.js: 301: 14)
Object.runBound(domain.js: 314: 12)
Object.tryCatcher(/var/task / node_modules / bluebird / js / release / util.js: 16: 23)
Promise._settlePromiseFromHandler(/var/task / node_modules / bluebird / js / release / promise.js: 512: 31)
Promise._settlePromise(/var/task / node_modules / bluebird / js / release / promise.js: 569: 18)
Promise._settlePromise0(/var/task / node_modules / bluebird / js / release / promise.js: 614: 10)
Promise._settlePromises(/var/task / node_modules / bluebird / js / release / promise.js: 693: 18)
Async._drainQueue(/var/task / node_modules / bluebird / js / release / async.js: 133: 16)
Async._drainQueues(/var/task / node_modules / bluebird / js / release / async.js: 143: 10)
Immediate.Async.drainQueues(/var/task / node_modules / bluebird / js / release / async.js: 17: 14)
runCallback(timers.js: 794: 20)
tryOnImmediate(timers.js: 752: 5)
processImmediate[as _immediateCallback](timers.js: 729: 5)