Integration recipes
n8n
- Calling the API: HTTP Request node → Authentication Generic Credential Type → Header Auth, Name
Authorization, ValueBearer dpk_xxx. URLs look likehttps://<domain>/api/v1/.... - Receiving events: Webhook node (POST), enable Options → Raw Body. Copy the Production URL, then register it with
POST /api/v1/webhooks. Verify the signature with a Crypto node (HMAC, SHA256, hex) over the string<X-Deplao-Timestamp>.<raw body>. - Example: new order (Webhook from your online store) → HTTP Request
POST /api/v1/accounts/{account_id}/conversations/{thread_id}/messageswith the body{"text": "Thank you for your order #{{$json.order_id}}"}.
Make (Integromat)
- Calling the API: HTTP → Make a request module, header
Authorization: Bearer dpk_xxx, Body type Raw, Content type JSON (application/json). - Receiving events: Webhooks → Custom webhook, copy the address, then register a Deplao webhook with the
eventsyou need. If your scenario can't verify the signature itself, keep the webhook address secret (Make generates a long random address) and use HTTPS only.
Google Apps Script / Google Sheets
Apps Script can't read the headers of incoming requests (so it can't verify signatures) and answers POST requests with a 302, so don't use webhooks. Use polling with a time-driven trigger instead (Triggers → Time-driven → every minute):
js
const BASE = 'https://<domain>/api/v1';
function pollDeplao() {
const props = PropertiesService.getScriptProperties();
const key = props.getProperty('DEPLAO_KEY');
const since = Number(props.getProperty('since') || 0);
const res = UrlFetchApp.fetch(BASE + '/events?types=message.received&limit=200&since=' + since, {
headers: { Authorization: 'Bearer ' + key },
muteHttpExceptions: true,
});
const body = JSON.parse(res.getContentText());
if (!body.success) throw new Error(body.error.code + ': ' + body.error.message);
const sheet = SpreadsheetApp.getActive().getSheetByName('Messages');
body.data.forEach(function (ev) {
const conv = ev.data.conversation || {};
const msg = ev.data.message || {};
sheet.appendRow([new Date(ev.ts), ev.account_id, conv.display_name, msg.text]);
});
props.setProperty('since', String(body.pagination.next_since));
}Your own worker or server (calling the API)
js
const res = await fetch('https://<domain>/api/v1/accounts/0501234567/conversations/8765432109876/messages', {
method: 'POST',
headers: {
Authorization: 'Bearer ' + process.env.DEPLAO_KEY,
'Content-Type': 'application/json',
'Idempotency-Key': 'order-1001-shipped', // resending with the same key → no duplicate message
},
body: JSON.stringify({ text: 'Order #1001 has been handed over to the courier', thread_type: 'user' }),
});
const out = await res.json();
if (!out.success) console.error(out.error.code, out.error.message);Idempotency-Keyis remembered for 24 hours (or until the app restarts). Resending with the same key returns the result of the first call unchanged.- Group chats:
"thread_type": "group".
Generating SDKs and tooling
bash
npx @openapitools/openapi-generator-cli generate -i http://127.0.0.1:9900/api/v1/openapi.json -g typescript-fetch -o deplao-sdk- Postman, Insomnia, Bruno: Import → URL
http://127.0.0.1:9900/api/v1/openapi.json. - By default
openapi.jsoncan be viewed without a key. If you've turned off "Public docs" (Tài liệu công khai), add anAuthorizationheader when importing remotely.
Didn't find your answer?
Message us on Telegram