Server-side library implementing Amio API for instant messengers. It supports API calls as well as webhooks.
Let us know how to improve this library. We'll be more than happy if you report any issues or even create pull requests. ;-)
Signup to Amio and create a channel before using this library.
npm install amio-sdk-js --save
const AmioApi = require('amio-sdk-js').AmioApi
const amioApi = new AmioApi({
accessToken: 'get access token at https://app.amio.io/administration/settings/api'
})
async function sendMessage() {
const message = await amioApi.messages.send({
channel: {id: '{CHANNEL_ID}'},
contact: {id: '{CONTACT_ID}'},
content: content
})
return message
}
const express = require('express')
const router = express.Router()
const WebhookRouter = require('amio-sdk-js').WebhookRouter
const amioWebhookRouter = new WebhookRouter({
secrets: {
'{CHANNEL_ID}':'{SECRET}'
}
})
amioWebhookRouter.onMessageReceived(function(data) {
console.log('new message received from contact ' + data.contact.id + 'with content ' + data.content)
})
router.post('/webhooks/amio', function (req, res) {
amioWebhookRouter.handleEvent(req, res)
})
const AmioApi = require('amio-sdk-js').AmioApi
const amioApi = new AmioApi({
accessToken: 'get access token at https://app.amio.io/administration/settings/api'
})
// request with async/await
const message = await amioApi.messages.send({/* message */})
// request with a promise
amioApi.messages.send({/* message */})
.then(message => ...)
Amio API errors keep the structure described in the docs.
try{
const message = await amioApi.messages.send({/* message */})
} catch(err){
if (err.amioApiError) {
console.error(err.jsonify(), err)
return
}
console.error(err)
}
amioApi.messages.send({/* message */})
.then(message => ...)
.catch(err => {
if (err.amioApiError) {
console.error(err.jsonify(), err)
return
}
console.error(err)
})
amioApi.* | Description | Links |
---|---|---|
channels.get(channelId) |
Get information about specified channel. | docs |
channels.list(params) |
List available channels. | docs, params |
channels.create(request) |
Create a new channel. | docs |
channels.update(channelId, request) |
Update specified channel. | docs |
channels.delete(channelId) |
Delete specified channel. | docs |
contentBuilder.typeAudio(url) |
Start building Audio content. | sdk-docs |
contentBuilder.typeFile(url) |
Start building File content. | sdk-docs |
contentBuilder.typeGeneric(payload, type) |
Start building any content. | sdk-docs |
contentBuilder.typeImage(url) |
Start building Image content. | sdk-docs |
contentBuilder.typeVideo(url) |
Start building Video content. | sdk-docs |
contentBuilder.typeStructure() |
Start building Structure content. | sdk-docs |
contentBuilder.typeText(text) |
Start building Text content. | sdk-docs |
contacts.get(channelId, contactId) |
Get information about a contact in specified channel. | docs |
contacts.list(channelId, params) |
List contacts for specified channel. | docs, params |
contacts.delete(channelId, contactId) |
Delete a contact within specified channel. | docs |
messages.send(message) |
Send a message to a contact. | docs |
messages.list(channelId, contactId, params) |
List messages for specified channel and contact. | docs, params |
notifications.send(notification) |
Send a notification to a contact. | docs |
settings.get(channelId) |
Get settings for specified channel. | docs |
settings.set(channelId, setting) |
Modify settings for specified channel. | docs |
Use content-builders to better structure your code. The builders represent all available message types and it's up to you pick the right builder for the right platform.
For example, you can add a location quick reply to your question:
const content = amioApi.contentBuilder.typeText('Where are you now?')
.addQuickReply('location')
.build()
assertEquals(content, {
type: 'text',
payload: 'Where are you now?',
quick_replies: [{type: 'location'}]
})
Then you just send the content
in the message:
amioApi.messages.send({channel, contanct, content})
All available builders have these methods:
addQuickReply(quickReply)
- adds a quick reply according to docsaddQuickReply(type)
- adds a quick reply for type of location, email or phone_number. Suitable for quickReplies withtype
field only.build()
- returns final content
Available builders are:
contentBuilder.typeGeneric(payload, type)
contentBuilder.typeImage(url)
contentBuilder.typeVideo(url)
contentBuilder.typeStructure()
- use
.addNextStructure()
to create a horizontal scroll
- use
contentBuilder.typeText(text)
const content = contentBuilder.typeStructure()
.setText('structure 1')
.addNextStructure()
.setText('structure 2')
.build();
assertEquals(content, {
type: 'structure',
payload: [
{text: 'structure 1'},
{text: 'structure 2'}
]
})
Central logic to handle webhooks coming from Amio is WebhookRouter. What does it do?
- It responds OK 200 to Amio.
- It verifies X-Hub-Signature.
- It routes events to handlers (e.g. event
message_received
to a method registered inamioWebhookRouter.onMessageReceived()
)
- Attach raw body to requests.
const bodyParser = require('body-parser');
const attachRawBody = require('amio-sdk-js').attachRawBody;
app.use(bodyParser.json({
verify: attachRawBody
}))
- Setup webhook routing
const express = require('express')
const router = express.Router()
const WebhookRouter = require('amio-sdk-js').WebhookRouter
const amioWebhookRouter = new WebhookRouter({
secrets: {
// CHANNEL_ID: SECRET
// !!! CHANNEL_ID must be a string. The numbers can be converted to a different value
// get CHANNEL_ID at https://app.amio.io/administration/channels/
// get SECRET at https://app.amio.io/administration/channels/{{CHANNEL_ID}}/webhook
'15160185464897428':'thzWPzSPhNjfdKdfsLBEHFeLWW'
}
// xhubEnabled: false // disables X-Hub-Signature verification, do it at your own risk only
})
// add secret dynamically
amioWebhookRouter.setSecret('48660483859995133', 'fdsafJzSPhNjfdKdfsLBEjdfks')
// error handling, e.g. x-hub-signature is not correct
amioWebhookRouter.onError(error => console.error(error))
// assign event handlers
amioWebhookRouter.onMessageReceived(webhook => console.log('a new message from contact ${data.contact.id} was received!'))
amioWebhookRouter.onMessagesDelivered(webhook => {/* TODO */})
amioWebhookRouter.onMessagesRead(webhook => {/* TODO */})
amioWebhookRouter.onMessageEcho(webhook => {/* TODO */})
amioWebhookRouter.onPostbackReceived(webhook => {/* TODO */})
amioWebhookRouter.onOptIn(webhook => {/* TODO */})
router.post('/webhooks/amio', (req, res) => amioWebhookRouter.handleEvent(req, res))
module.exports = router
- Attach router to express app
const amioWebhookRouter = require('path/to/amio-webhook-router.js')
app.use('/', amioWebhookRouter)
amioWebhookRouter.* | Description |
---|---|
setSecret(channelId, secret) |
Pairs a channelId with a secret . Setting secret for the same channelId twice will override the previous value. |
getSecret(channelId) |
Returns a secret if found. |
Facebook:
Viber Bot:
Viber Business Messages:
SMS:
To enable logging for debugging purposes, set the following environment variable:
variable | value |
---|---|
process.env.DEBUG | amio-sdk-js:* |
To narrow down logs even further, replace the *
wildcard with a specific endpoint.
File an issue or create a pull request. If you need a quick solution, use the prepared axios http client:
const amioHttpClient = require('amio-sdk-js').amioHttpClient
amioHttpClient.get('/v1/messages')
.then(response => {
// ...
})