ES6 Module JavaScript

Welcome


@@@@@@@        @@@         @@@@@@       @@@       @@@@@@@         @@@@@@    @@@@@@@        @@@@@@@
 @@@@@@@      @@@@@      @@@@@@@       @@@@@@      @@@@@@@      @@@@@@@      @@@@@@@      @@@@@@@
  @@@@@@@    @@@@@@@@   @@@@@@@       @@@@@@@@       @@@@@@@   @@@@@@@        @@@@@@@    @@@@@@
   @@@@@@@ @@@@@@@@@@@ @@@@@@@       @@@@@@@@@@       @@@@@@@ @@@@@@@          @@@@@@@ @@@@@@@
    @@@@@@@@@@@@@@@@@@@@@@@@@      @@@@@@@@@@@@@       @@@@@@@@@@@@@            @@@@@@@@@@@@@
      @@@@@@@@@@ @@@@@@@@@@@      @@@@@@@  @@@@@@       @@@@@@@@@@                @@@@@@@@@@
       @@@@@@@@   @@@@@@@@       @@@@@@@    @@@@@@@      @@@@@@@@                  @@@@@@@@
        @@@@@       @@@@@       @@@@@@@      @@@@@@@       @@@@@                    @@@@@
         @@@         @@@       @@@@@@@        @@@@@@@       @@@                      @@@
{ "title": "WAVV Docs", "lastUpdated": "2021-10-21T04:34:35.363Z" }

Welcome to WAVV's developer documentation.

Ready to supercharge your app with our comm widgets?

Learn more about a specific widget:

Or check out our REST API.

We've also written some helpful guides.

And outlined common data structures.

Dialer

Latest version: 2.3.0

Quick Start

To get started, follow these simple steps:


1. Include

Step 1:

npm install @wavv/dialer

Alternatively:

<script src="https://app.wavv.com/js/dialer-2.3.0.js"></script>

There are two ways to include the widget:

You'll also need to add <div id="wavv-dialer"></div> to your HTML.

(The div determines where the dialer will appear in your app.)


2. Initialize

Step 2:

import { init } from '@wavv/dialer';

init({ token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' });
const { init } = window.WavvDialer;

init({ token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' });

Initialize the widget with a token.

For more information, see the guide on Tokens.


3. Listen

Step 3:

import { addCallStartedListener } from '@wavv/dialer';

const listener = addCallStartedListener(({ number }) => {
    console.log(`Calling ${number}...`);
});
const { addCallStartedListener } = window.WavvDialer;

const listener = addCallStartedListener(({ number }) => {
    console.log(`Calling ${number}...`);
});

Add listeners for the events you care about.

(Technically, this step is optional.)


4. Start

Step 4:

import { callPhone } from '@wavv/dialer';

callPhone({
    number: '9143504210',
    contactId: '541d4a8b-c583-4b0b-aca3-0afb75abdec6',
});
const { callPhone } = window.WavvDialer;

callPhone({
    number: '9143504210',
    contactId: '541d4a8b-c583-4b0b-aca3-0afb75abdec6',
});

Fire it up with Start Campaign or Call Phone.

Annnd you're done. Congratulations!

Functions

Init

import { init } from '@wavv/dialer';

init({ token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' });
const { init } = window.WavvDialer;

init({ token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' });

Initializes the widget and authenticates the user.


Parameters

Name Type Required Description
token string yes Token



Set Theme

import { setTheme } from '@wavv/dialer';

setTheme({ theme: 'LIGHT', primaryColor: '#BF6350' });
const { setTheme } = window.WavvDialer;

setTheme({ theme: 'LIGHT', primaryColor: '#BF6350' });

Changes the appearance of WAVV to suit your fancy.


Parameters

Name Type Required Description
theme string yes LIGHT or DARK
primaryColor string no Hex color code



Start Campaign

import { startCampaign } from '@wavv/dialer';

const contacts = [
    {
        contactId: '541d4a8b-c583-4b0b-aca3-0afb75abdec6',
        numbers: ['9143504210', '9143505590'],
        firstName: 'George',
        lastName: 'Costanza',
        address: '1344 Queens Boulevard',
        city: 'Long Island',
    },
];

try {
    await startCampaign({ contacts });
} catch (err) {
    console.log(err);
}
const { startCampaign } = window.WavvDialer;

const contacts = [
    {
        contactId: '541d4a8b-c583-4b0b-aca3-0afb75abdec6',
        numbers: ['9143504210', '9143505590'],
        firstName: 'George',
        lastName: 'Costanza',
        address: '1344 Queens Boulevard',
        city: 'Long Island',
    },
];

try {
    await startCampaign({ contacts });
} catch (err) {
    console.log(err);
}

Loads contact data and launches the dialer.


Parameters

Name Type Required Description
contacts Contact[] yes Contacts for the campaign



Call Phone

import { callPhone } from '@wavv/dialer';

callPhone({
    number: '9143504210',
    contactId: '541d4a8b-c583-4b0b-aca3-0afb75abdec6',
});
const { callPhone } = window.WavvDialer;

callPhone({
    number: '9143504210',
    contactId: '541d4a8b-c583-4b0b-aca3-0afb75abdec6',
});

Loads a single number and launches the dialer (click-to-call).


Parameters

Name Type Required Description
number string yes Phone number to call
contactId string no Associated contact ID



Add Phone

import { addPhone } from '@wavv/dialer';

addPhone({
    number: '9143504210',
    contactId: '541d4a8b-c583-4b0b-aca3-0afb75abdec6',
});
const { addPhone } = window.WavvDialer;

addPhone({
    number: '9143504210',
    contactId: '541d4a8b-c583-4b0b-aca3-0afb75abdec6',
});

Adds a number to a contact in the campaign.


Parameters

Name Type Required Description
number string yes Phone number to add
contactId string yes Associated contact ID



Remove Phone

import { removePhone } from '@wavv/dialer';

removePhone({
    number: '9143504210',
    hangup: true,
});
const { removePhone } = window.WavvDialer;

removePhone({
    number: '9143504210',
    hangup: true,
});

Removes a number from the campaign.


Parameters

Name Type Required Description
number string yes Phone number to remove
hangup boolean no Hangup call to number (if any)



Remove Contact

import { removeContact } from '@wavv/dialer';

removeContact({
    contactId: '541d4a8b-c583-4b0b-aca3-0afb75abdec6',
    hangup: true,
    resume: true,
});
const { removeContact } = window.WavvDialer;

removeContact({
    contactId: '541d4a8b-c583-4b0b-aca3-0afb75abdec6',
    hangup: true,
    resume: true,
});

Removes a contact from the campaign.


Parameters

Name Type Required Description
contactId string yes ID of the contact to remove
hangup boolean no Hangup calls to contact (if any)
resume boolean no Resume the campaign



Continue Campaign

import { continueCampaign } from '@wavv/dialer';

continueCampaign({
    resume: true,
});
const { continueCampaign } = window.WavvDialer;

continueCampaign({
    resume: true,
});

Allows the campaign to continue (enables the resume button).

Used in conjunction with Waiting For Continue.


Parameters

Name Type Required Description
resume boolean no Resume the campaign



Add DNC Number

import { addDncNumber } from '@wavv/dialer';

addDncNumber({
    number: '9143504210',
    addedBy: 'Kramer',
});
const { addDncNumber } = window.WavvDialer;

addDncNumber({
    number: '9143504210',
    addedBy: 'Kramer',
});

Adds a number to the DNC list.


Parameters

Name Type Required Description
number string yes Phone number to add
addedBy string no Who added the number



Remove DNC Number

import { removeDncNumber } from '@wavv/dialer';

removeDncNumber({
    number: '9143504210',
});
const { removeDncNumber } = window.WavvDialer;

removeDncNumber({
    number: '9143504210',
});

Removes a number from the DNC list.


Parameters

Name Type Required Description
number string yes Phone number to remove



List Voicemails

import { listVoicemails } from '@wavv/dialer';

const vms = await listVoicemails();
vms.forEach(({ id, name, seconds }) => {
    console.log(id, name, seconds);
});
const { listVoicemails } = window.WavvDialer;

const vms = await listVoicemails();
vms.forEach(({ id, name, seconds }) => {
    console.log(id, name, seconds);
});

Lists the user's voicemail recordings.

Used in conjunction with Drop Voicemail.




Drop Voicemail

import { dropVoicemail } from '@wavv/dialer';

dropVoicemail({ id: 'c25efb5c-3e4a-46f4-a2b9-ff2a48058737' });
const { dropVoicemail } = window.WavvDialer;

dropVoicemail({ id: 'c25efb5c-3e4a-46f4-a2b9-ff2a48058737' });

Drops a voicemail on the current call.

Logically equivalent to pressing the "Drop VM" button.


Parameters

Name Type Required Description
id string yes Voicemail ID



Record Call

import { recordCall } from '@wavv/dialer';

recordCall();
const { recordCall } = window.WavvDialer;

recordCall();

Records the current call.

Logically equivalent to pressing the "Record" button.



Listeners

Call Started

import { addCallStartedListener } from '@wavv/dialer';

const listener = addCallStartedListener(({ number }) => {
    console.log(`Calling ${number}...`);
});
const { addCallStartedListener } = window.WavvDialer;

const listener = addCallStartedListener(({ number }) => {
    console.log(`Calling ${number}...`);
});

Fired when a call starts dialing.


Properties

Name Type Description
number string Phone number
contactId string Associated contact ID



Call Answered

import { addCallAnsweredListener } from '@wavv/dialer';

const listener = addCallAnsweredListener(({ number }) => {
    console.log(`Call to ${number} answered...`);
});
const { addCallAnsweredListener } = window.WavvDialer;

const listener = addCallAnsweredListener(({ number }) => {
    console.log(`Call to ${number} answered...`);
});

Fired when a call is answered.


Properties

Name Type Description
number string Phone number
contactId string Associated contact ID
backgrounded boolean Call answered on a background line



Call Ended

import { addCallEndedListener } from '@wavv/dialer';

const listener = addCallEndedListener(({ number }) => {
    console.log(`Call to ${number} ended...`);
});
const { addCallEndedListener } = window.WavvDialer;

const listener = addCallEndedListener(({ number }) => {
    console.log(`Call to ${number} ended...`);
});

Fired when a call ends.


Properties

Name Type Description
number string Phone number
contactId string Associated contact ID
duration number Duration of the call in seconds
human boolean A human was detected on the call
outcome string Call Outcome



Call Recorded

import { addCallRecordedListener } from '@wavv/dialer';

const listener = addCallRecordedListener(({ number }) => {
    console.log(`Call to ${number} recorded...`);
});
const { addCallRecordedListener } = window.WavvDialer;

const listener = addCallRecordedListener(({ number }) => {
    console.log(`Call to ${number} recorded...`);
});

Fired when a call has been recorded.


Properties

Name Type Description
number string Phone number
contactId string Associated contact ID
recordingId string Call recording ID



Lines Changed

import { addLinesChangedListener } from '@wavv/dialer';

const listener = addLinesChangedListener(({ lines }) => {
    const call = lines.filter(({ focused }) => focused)[0];
    if (call) {
        await navigateToContact(call.contactId);
        highlightPhoneNumber(call.number);
    }
});
const { addLinesChangedListener } = window.WavvDialer;

const listener = addLinesChangedListener(({ lines }) => {
    const call = lines.filter(({ focused }) => focused)[0];
    if (call) {
        await navigateToContact(call.contactId);
        highlightPhoneNumber(call.number);
    }
});

Fired when dialing lines change.


Properties

Name Type Description
lines array Current dialing lines
lines[].number string Phone number
lines[].contactId string Associated contact ID
lines[].focused boolean Number should have focus
lines[].skippedNumbers array Skipped numbers on the contact



Dialer Idle

import { addDialerIdleListener } from '@wavv/dialer';

const listener = addDialerIdleListener(({ idle }) => {
    console.log(`Dialer is now ${idle ? 'idle' : 'active'}...`);
});
const { addDialerIdleListener } = window.WavvDialer;

const listener = addDialerIdleListener(({ idle }) => {
    console.log(`Dialer is now ${idle ? 'idle' : 'active'}...`);
});

Fired when idle state changes.

The dialer becomes idle when there are no numbers left to dial. A timer will be displayed, showing how much time is left before the dialer will auto-disconnect. At this point, the user can end their session or load more numbers.


Properties

Name Type Description
idle boolean Dialer is currently idle



Waiting For Continue

import { addWaitingForContinueListener } from '@wavv/dialer';

const listener = addWaitingForContinueListener(
    ({ waiting, number }) => {
        if (waiting) {
            await gatherNotes(number);
            continueCampaign();
        }
    }
);
const { addWaitingForContinueListener } = window.WavvDialer;

const listener = addWaitingForContinueListener(
    ({ waiting, number }) => {
        if (waiting) {
            await gatherNotes(number);
            continueCampaign();
        }
    }
);

Fired when waiting state changes.

By default, the dialer will wait to continue after every answered call. The resume button will be disabled, allowing you to gather additional information from the user. When it's safe to proceed, call Continue Campaign.


Properties

Name Type Description
waiting boolean Dialer is currently waiting
number string Phone number
contactId string Associated contact ID



Campaign Ended

import { addCampaignEndedListener } from '@wavv/dialer';

const listener = addCampaignEndedListener(({ history }) => {
    console.log(`Campaign ended, made ${history.length} calls...`);
});
const { addCampaignEndedListener } = window.WavvDialer;

const listener = addCampaignEndedListener(({ history }) => {
    console.log(`Campaign ended, made ${history.length} calls...`);
});

Fired when a campaign ends.


Properties

Name Type Description
complete boolean All numbers were dialed
history array Call Ended objects from the campaign



Dialer Visible

import { addDialerVisibleListener } from '@wavv/dialer';

const listener = addDialerVisibleListener(({ visible }) => {
    console.log(`Dialer is now ${visible ? 'visible' : 'hidden'}...`);
});
const { addDialerVisibleListener } = window.WavvDialer;

const listener = addDialerVisibleListener(({ visible }) => {
    console.log(`Dialer is now ${visible ? 'visible' : 'hidden'}...`);
});

Fired when dialer visibility changes.


Properties

Name Type Description
visible boolean Dialer is currently visible



Overlay Visible

import { addOverlayVisibleListener } from '@wavv/dialer';

const listener = addOverlayVisibleListener(({ visible }) => {
    console.log(`Overlay is now ${visible ? 'visible' : 'hidden'}...`);
});
const { addOverlayVisibleListener } = window.WavvDialer;

const listener = addOverlayVisibleListener(({ visible }) => {
    console.log(`Overlay is now ${visible ? 'visible' : 'hidden'}...`);
});

Fired when overlay visibility changes.

Certain dialogs and modals display a full-screen overlay.


Properties

Name Type Description
visible boolean Overlay is currently visible



DNC Changed

import { addDncChangedListener } from '@wavv/dialer';

const listener = addDncChangedListener(({ lines }) => {
    const call = lines.filter(({ focused }) => focused)[0];
    if (call) {
        await navigateToContact(call.contactId);
        highlightPhoneNumber(call.number);
    }
});
const { addDncChangedListener } = window.WavvDialer;

const listener = addDncChangedListener(({ lines }) => {
    const call = lines.filter(({ focused }) => focused)[0];
    if (call) {
        await navigateToContact(call.contactId);
        highlightPhoneNumber(call.number);
    }
});

Fired when a number is added or removed from the DNC list.


Properties

Name Type Description
number string Phone number
removed boolean Number was removed
type string DNC Type



Upsell Click

import { addUpsellClickListener } from '@wavv/dialer';

const listener = addUpsellClickListener(() => {
    displayOpportunity();
});
const { addUpsellClickListener } = window.WavvDialer;

const listener = addUpsellClickListener(() => {
    displayOpportunity();
});

Fired when the user clicks an upsell link.

Only applicable if you've chosen to handle billing.




Manage Subscription

import { addManageSubscriptionListener } from '@wavv/dialer';

const listener = addManageSubscriptionListener(() => {
    displayBilling();
});
const { addManageSubscriptionListener } = window.WavvDialer;

const listener = addManageSubscriptionListener(() => {
    displayBilling();
});

Fired when the user wants to manage their subscription.

Only applicable if you've chosen to handle billing.



Changelog

v2.3.0


v2.1.0


v2.0.0


Messenger

Latest version: 2.3.1

Quick Start

To get started, follow these simple steps:


1. Include

Step 1:

npm install @wavv/messenger

Alternatively:

<script src="https://app.wavv.com/js/messenger-2.3.1.js"></script>

There are two ways to include the widget:


2. Initialize

Step 2:

import { init } from '@wavv/messenger';

init({ token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' });
const { init } = window.WavvMessenger;

init({ token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' });

Initialize the widget with a token.

For more information, see the guide on Tokens.


3. Listen

Step 3:

import { addMessageSentListener } from '@wavv/messenger';

const listener = addMessageSentListener(({ number }) => {
    console.log(`Message sent by ${number}...`);
});
const { addMessageSentListener } = window.WavvMessenger;

const listener = addMessageSentListener(({ number }) => {
    console.log(`Message sent by ${number}...`);
});

Add listeners for the events you care about.

(Technically, this step is optional.)


4. Start

Step 4:

import { openMessenger } from '@wavv/messenger';

openMessenger();
const { openMessenger } = window.WavvMessenger;

openMessenger();

Fire it up with Open Messenger.

Annnd you're done. Congratulations!

Functions

Init

import { init } from '@wavv/messenger';

init({ token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' });
const { init } = window.WavvMessenger;

init({ token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' });

Initializes the widget and authenticates the user.


Parameters

Name Type Required Description
token string yes Token



Set Theme

import { setTheme } from '@wavv/messenger';

setTheme({ theme: 'LIGHT', primaryColor: '#BF6350' });
const { setTheme } = window.WavvMessenger;

setTheme({ theme: 'LIGHT', primaryColor: '#BF6350' });

Changes the appearance of WAVV to suit your fancy.


Parameters

Name Type Required Description
theme string yes LIGHT or DARK
primaryColor string no Hex color code



Open Messenger

import { openMessenger } from '@wavv/messenger';

openMessenger({
    contactView: true,
    contact: {
        contactId: '541d4a8b-c583-4b0b-aca3-0afb75abdec6',
        numbers: ['9143504210', '9143505590'],
        firstName: 'George',
        lastName: 'Costanza',
        address: '1344 Queens Boulevard',
        city: 'Long Island',
        avatarUrl:
            'https://wavv-public.s3.amazonaws.com/docs/summer/george.jpg',
        mergeFields: [
            { id: 'sqft', value: '4,000' },
            { id: 'neighborhood', value: 'Briarwood' },
        ],
    },
});
const { openMessenger } = window.WavvMessenger;

openMessenger({
    contactView: true,
    contact: {
        contactId: '541d4a8b-c583-4b0b-aca3-0afb75abdec6',
        numbers: ['9143504210', '9143505590'],
        firstName: 'George',
        lastName: 'Costanza',
        address: '1344 Queens Boulevard',
        city: 'Long Island',
        avatarUrl:
            'https://wavv-public.s3.amazonaws.com/docs/summer/george.jpg',
        mergeFields: [
            { id: 'sqft', value: '4,000' },
            { id: 'neighborhood', value: 'Briarwood' },
        ],
    },
});

Opens the Messenger.


Parameters

Name Type Required Description
dock boolean no Open in docked mode
minimized boolean no Start minimized (if docked)
contactView boolean no Show contact-centric view
contact Contact no Contact for contactView



Open Messenger Thread

import { openMessengerThread } from '@wavv/messenger';

openMessengerThread({
    number: '9143504210',
    dock: true,
});
const { openMessengerThread } = window.WavvMessenger;

openMessengerThread({
    number: '9143504210',
    dock: true,
});

Opens the Messenger to a specific thread.


Parameters

Name Type Required Description
number string yes Phone number of recipient
dock boolean no Open in docked mode
minimized boolean no Start minimized (if docked)
contact Contact no Contact for number



Start Blast

import { startBlast } from '@wavv/messenger';

startBlast({
    contact: {
        contactId: '541d4a8b-c583-4b0b-aca3-0afb75abdec6',
        numbers: ['9143504210', '9143505590'],
        firstName: 'George',
        lastName: 'Costanza',
        avatarUrl:
            'https://wavv-public.s3.amazonaws.com/docs/summer/george.jpg',
        mergeFields: [
            { id: 'sqft', value: '4,000' },
            { id: 'neighborhood', value: 'Briarwood' },
        ],
    },
});
const { startBlast } = window.WavvMessenger;

startBlast({
    contact: {
        contactId: '541d4a8b-c583-4b0b-aca3-0afb75abdec6',
        numbers: ['9143504210', '9143505590'],
        firstName: 'George',
        lastName: 'Costanza',
        avatarUrl:
            'https://wavv-public.s3.amazonaws.com/docs/summer/george.jpg',
        mergeFields: [
            { id: 'sqft', value: '4,000' },
            { id: 'neighborhood', value: 'Briarwood' },
        ],
    },
});

Opens the Messenger and starts a blast message.


Parameters

Name Type Required Description
contacts Contact[] yes Contacts for the blast message



Set Merge Fields

import { setMergeFields } from '@wavv/messenger';

setMergeFields({
    fields: [
        { id: 'sqft', label: 'Square Feet' },
        { id: 'neighborhood', label: 'Neighborhood' },
    ],
});
const { setMergeFields } = window.WavvMessenger;

setMergeFields({
    fields: [
        { id: 'sqft', label: 'Square Feet' },
        { id: 'neighborhood', label: 'Neighborhood' },
    ],
});

Adds custom merge field options.

For more information, see the guide on Merge Fields.


Parameters

Name Type Required Description
fields array yes Custom merge fields
fields[].id string yes Merge field ID
fields[].label string yes Merge field label


Listeners

import { addContactSearchListener } from '@wavv/messenger';

const listener = addContactSearchListener(
    ({ search, contacts, callback }) => {
        // callback expects an array of contact objects
        if (search) {
            const terms = search.trim().split(/\s+/);
            const results = findContactsBySearchTerms(terms);
            callback(results);
        } else if (contacts) {
            const results = contacts.map((contact) => {
                const { id, numbers } = contact;
                // ID might be unknown, find by phone number(s) if necessary
                return id
                    ? findContactById(id)
                    : findContactByNumbers(numbers);
            });
            callback(results);
        }
    }
);
const { addContactSearchListener } = window.WavvMessenger;

const listener = addContactSearchListener(
    ({ search, contacts, callback }) => {
        // callback expects an array of contact objects
        if (search) {
            const terms = search.trim().split(/\s+/);
            const results = findContactsBySearchTerms(terms);
            callback(results);
        } else if (contacts) {
            const results = contacts.map((contact) => {
                const { id, numbers } = contact;
                // ID might be unknown, find by phone number(s) if necessary
                return id
                    ? findContactById(id)
                    : findContactByNumbers(numbers);
            });
            callback(results);
        }
    }
);

Fired when contact data is needed from your app.


Properties

Name Type Description
search string Free-form search by the user
contacts Contact[] Specific contacts to return
callback function Callback for passing results



import { addContactLinkListener } from '@wavv/messenger';

const listener = addContactLinkListener(({ contact, callback }) => {
    try {
        await navigateToContact(contact.id);
        // contact found, close the WAVV modal
        callback({ closeModal: true });
    } catch (error) {
        // contact not found, display error in WAVV
        callback({ displayError: true });
    }
});
const { addContactLinkListener } = window.WavvMessenger;

const listener = addContactLinkListener(({ contact, callback }) => {
    try {
        await navigateToContact(contact.id);
        // contact found, close the WAVV modal
        callback({ closeModal: true });
    } catch (error) {
        // contact not found, display error in WAVV
        callback({ displayError: true });
    }
});

Fired when your app should display a contact record.

I.e. the user has clicked a link and expects to be shown contact details.


Name Type Description
contact Contact Contact to display
callback function Callback for controlling behavior



Message Sent

import { addMessageSentListener } from '@wavv/messenger';

const listener = addMessageSentListener(({ number }) => {
    console.log(`Message sent by ${number}...`);
});
const { addMessageSentListener } = window.WavvMessenger;

const listener = addMessageSentListener(({ number }) => {
    console.log(`Message sent by ${number}...`);
});

Fired when a message is sent.


Properties

Name Type Description
number string Receiving phone number
body string Body of the message



Message Received

import { addMessageReceivedListener } from '@wavv/messenger';

const listener = addMessageReceivedListener(({ number }) => {
    console.log(`Message received from ${number}...`);
});
const { addMessageReceivedListener } = window.WavvMessenger;

const listener = addMessageReceivedListener(({ number }) => {
    console.log(`Message received from ${number}...`);
});

Fired when a message is received.


Properties

Name Type Description
number string Sending phone number
body string Body of the message



Unread Count

import { addUnreadCountListener } from '@wavv/messenger';

const listener = addUnreadCountListener(
    ({ unreadCount, numberCounts }) => {
        console.log(`Unread message counts...`);
        console.log(`Total: ${unreadCount}`);
        console.log(`George: ${numberCounts['9143504210'] || 0}`);
    }
);
const { addUnreadCountListener } = window.WavvMessenger;

const listener = addUnreadCountListener(
    ({ unreadCount, numberCounts }) => {
        console.log(`Unread message counts...`);
        console.log(`Total: ${unreadCount}`);
        console.log(`George: ${numberCounts['9143504210'] || 0}`);
    }
);

Fired when the number of unread messages changes.


Properties

Name Type Description
unreadCount number Total unread messages
numberCounts object Unread count by number



Overlay Visible

import { addOverlayVisibleListener } from '@wavv/messenger';

const listener = addOverlayVisibleListener(({ visible }) => {
    console.log(`Overlay is now ${visible ? 'visible' : 'hidden'}...`);
});
const { addOverlayVisibleListener } = window.WavvMessenger;

const listener = addOverlayVisibleListener(({ visible }) => {
    console.log(`Overlay is now ${visible ? 'visible' : 'hidden'}...`);
});

Fired when overlay visibility changes.

Certain dialogs and modals display a full-screen overlay.


Properties

Name Type Description
visible boolean Overlay is currently visible



Upsell Click

import { addUpsellClickListener } from '@wavv/messenger';

const listener = addUpsellClickListener(() => {
    displayOpportunity();
});
const { addUpsellClickListener } = window.WavvMessenger;

const listener = addUpsellClickListener(() => {
    displayOpportunity();
});

Fired when the user clicks an upsell link.

Only applicable if you've chosen to handle billing.




Manage Subscription

import { addManageSubscriptionListener } from '@wavv/messenger';

const listener = addManageSubscriptionListener(() => {
    displayBilling();
});
const { addManageSubscriptionListener } = window.WavvMessenger;

const listener = addManageSubscriptionListener(() => {
    displayBilling();
});

Fired when the user wants to manage their subscription.

Only applicable if you've chosen to handle billing.



Changelog

v2.3.1


v2.3.0


v2.1.0


v2.0.0


Ringless Voicemail

Latest version: 1.1.0

Quick Start

To get started, follow these simple steps:


1. Include

Step 1:

npm install @wavv/ringless

Alternatively:

<script src="https://app.wavv.com/js/ringless-1.1.0.js"></script>

There are two ways to include the widget:


2. Initialize

Step 2:

import { init } from '@wavv/ringless';

init({ token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' });
const { init } = window.WavvRingless;

init({ token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' });

Initialize the widget with a token.

For more information, see the guide on Tokens.


3. Listen

Step 3:

// actually, there are no listeners yet... move on!

Add listeners for the events you care about.

(Technically, this step is optional.)


4. Start

Step 4:

import { startRingless } from '@wavv/ringless';

startRingless({
    contacts: [
        {
            contactId: '541d4a8b-c583-4b0b-aca3-0afb75abdec6',
            numbers: ['9143504210', '9143505590'],
        },
    ],
});
const { startRingless } = window.WavvRingless;

startRingless({
    contacts: [
        {
            contactId: '541d4a8b-c583-4b0b-aca3-0afb75abdec6',
            numbers: ['9143504210', '9143505590'],
        },
    ],
});

Fire it up with Start Ringless.

Annnd you're done. Congratulations!

Functions

Init

import { init } from '@wavv/ringless';

init({ token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' });
const { init } = window.WavvRingless;

init({ token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' });

Initializes the widget and authenticates the user.


Parameters

Name Type Required Description
token string yes Token



Set Theme

import { setTheme } from '@wavv/ringless';

setTheme({ theme: 'LIGHT', primaryColor: '#BF6350' });
const { setTheme } = window.WavvRingless;

setTheme({ theme: 'LIGHT', primaryColor: '#BF6350' });

Changes the appearance of WAVV to suit your fancy.


Parameters

Name Type Required Description
theme string yes LIGHT or DARK
primaryColor string no Hex color code



Start Ringless

import { startRingless } from '@wavv/ringless';

startRingless({
    contacts: [
        {
            contactId: '541d4a8b-c583-4b0b-aca3-0afb75abdec6',
            numbers: ['9143504210', '9143505590'],
        },
    ],
});
const { startRingless } = window.WavvRingless;

startRingless({
    contacts: [
        {
            contactId: '541d4a8b-c583-4b0b-aca3-0afb75abdec6',
            numbers: ['9143504210', '9143505590'],
        },
    ],
});

Loads contact data and launches ringless voicemail.


Parameters

Name Type Required Description
contacts Contact[] yes Contacts for ringless voicemail


Changelog

v1.1.0


REST API

If you're new here, see the REST API guide.

DNC List

List Numbers

curl -L -X GET 'https://api.wavv.com/v2/users/:userId/dnc' \
-H 'Authorization: Basic VENDOR_ID:API_KEY' \
-H 'Content-Type: application/json'

The above command returns JSON structured like this:

[
    {
        "id": "f4b5c94d-705a-43c2-9de3-0b0accf111f6",
        "number": "9143505590",
        "type": "MANUAL",
        "createdAt": "2021-10-20T20:21:17.911Z"
    }
]
GET
api.wavv.com/v2/users/userId/dnc

Messages

List Messages

curl -L -X GET 'https://api.wavv.com/v2/users/:userId/messages?limit=1' \
-H 'Authorization: Basic VENDOR_ID:API_KEY' \
-H 'Content-Type: application/json'

The above command returns JSON structured like this:

{
    "messages": [
        {
            "id": "12fb58e6-607d-47b7-9b2e-70ac57cbbbea",
            "date": "2021-10-20T05:00:09.613Z",
            "body": "Hello, Newman.",
            "status": "SENT",
            "number": "9143504210",
            "userNumber": "8444545111",
            "attachments": [
                {
                    "url": "https://api.wavv.com/sms/attachments/780d69a4160c4a70a0aae4d37442f3ef/8d7b1d70-5246-40c9-bf46-73c7331f2ecf",
                    "mimeType": "image/png"
                }
            ]
        }
    ],
    "nextPageToken": "MTA7MTA7MjAyMC0xMC0wMVQwNjowMDowMC4wMDBaOw=="
}
GET
api.wavv.com/v2/users/userId/messages


Query Parameters

Name Type Required Description
page-token string no Paging token
before date no Created before date
after date no Created after date
limit number no Messages per page

Recordings

List Recordings

curl -L -X GET 'https://api.wavv.com/v2/users/:userId/recordings' \
-H 'Authorization: Basic VENDOR_ID:API_KEY' \
-H 'Content-Type: application/json'

The above command returns JSON structured like this:

[
    {
        "id": "e17c6b83-cbc6-43eb-bbd6-5bc323124361",
        "contactId": "541d4a8b-c583-4b0b-aca3-0afb75abdec6",
        "date": "2021-10-20T13:15:02.530Z",
        "phone": "9143504210",
        "seconds": 86.125,
        "url": "https://api.wavv.com/audio/recordings/d28f557e418974a51d008b7718efb8e9/9143504210.mp3",
        "urlExpiration": "2021-10-24T04:34:35.360Z"
    }
]
GET
api.wavv.com/v2/users/userId/recordings


Get Recording

curl -L -X GET 'https://api.wavv.com/v2/users/:userId/recordings/:recordingId' \
-H 'Authorization: Basic VENDOR_ID:API_KEY' \
-H 'Content-Type: application/json'

The above command returns JSON structured like this:

{
    "id": "e17c6b83-cbc6-43eb-bbd6-5bc323124361",
    "contactId": "541d4a8b-c583-4b0b-aca3-0afb75abdec6",
    "date": "2021-10-20T13:15:02.530Z",
    "phone": "9143504210",
    "seconds": 86.125,
    "url": "https://api.wavv.com/audio/recordings/d28f557e418974a51d008b7718efb8e9/9143504210.mp3",
    "urlExpiration": "2021-10-24T04:34:35.360Z"
}
GET
api.wavv.com/v2/users/userId/recordings/recordingId


Delete Recording

curl -L -X DELETE 'https://api.wavv.com/v2/users/:userId/recordings/:recordingId' \
-H 'Authorization: Basic VENDOR_ID:API_KEY' \
-H 'Content-Type: application/json'

The above command returns JSON structured like this:

{ "success": true }
DELETE
api.wavv.com/v2/users/userId/recordings/recordingId

Tokens

Create Token

curl -L -X POST 'https://api.wavv.com/v2/token' \
-H 'Authorization: Basic VENDOR_ID:API_KEY' \
-H 'Content-Type: application/json' \
--data-raw '{ "userId": "f5f31ed2-5427-4036-975a-ccebd1eabb84" }'

The above command returns JSON structured like this:

{
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "payload": { "userId": "f5f31ed2-5427-4036-975a-ccebd1eabb84" }
}
POST
api.wavv.com/v2/token


Body Parameters

Name Type Required Description
userId string yes User ID to authenticate


Response Properties

Name Type Description
token string JWT for the user
payload object JWT payload (sanity check)

Users

List Users

curl -L -X GET 'https://api.wavv.com/v2/users' \
-H 'Authorization: Basic VENDOR_ID:API_KEY' \
-H 'Content-Type: application/json'

The above command returns JSON structured like this:

[
    {
        "id": "f5f31ed2-5427-4036-975a-ccebd1eabb84",
        "firstName": "George",
        "lastName": "Costanza",
        "phone": "9143504210",
        "email": "george@vandelayindustries.com",
        "address1": "1344 Queens Boulevard",
        "city": "Long Island",
        "state": "NY",
        "zip": "11101",
        "test": false,
        "subscriptions": { "single": true, "sms": true }
    }
]
GET
api.wavv.com/v2/users


Get User

curl -L -X GET 'https://api.wavv.com/v2/users/:userId' \
-H 'Authorization: Basic VENDOR_ID:API_KEY' \
-H 'Content-Type: application/json'

The above command returns JSON structured like this:

{
    "id": "f5f31ed2-5427-4036-975a-ccebd1eabb84",
    "firstName": "George",
    "lastName": "Costanza",
    "phone": "9143504210",
    "email": "george@vandelayindustries.com",
    "address1": "1344 Queens Boulevard",
    "city": "Long Island",
    "state": "NY",
    "zip": "11101",
    "test": false,
    "subscriptions": { "single": true, "sms": true }
}
GET
api.wavv.com/v2/users/userId


Create User

curl -L -X POST 'https://api.wavv.com/v2/users' \
-H 'Authorization: Basic VENDOR_ID:API_KEY' \
-H 'Content-Type: application/json' \
--data-raw '{
    "id": "f5f31ed2-5427-4036-975a-ccebd1eabb84",
    "firstName": "George",
    "lastName": "Costanza",
    "phone": "9143504210",
    "email": "george@vandelayindustries.com",
    "address1": "1344 Queens Boulevard",
    "city": "Long Island",
    "state": "NY",
    "zip": "11101",
    "test": false,
    "subscriptions": { "single": true, "sms": true }
}'

The above command returns JSON structured like this:

{ "success": true }
POST
api.wavv.com/v2/users


Body Parameters

Name Type Required Description
id string yes Unique ID
firstName string yes First name
lastName string yes Last name
email string yes Email address
phone string no Phone number
address1 string no Address
address2 string no Address line 2
city string no City
state string no State
zip string no Zip
test boolean no Testing account
subscriptions object yes Subscriptions
subscriptions.single boolean no Power Dialer Single Line
subscriptions.multi boolean no Power Dialer Multiple Line
subscriptions.previewLine boolean no Preview Line Dialer
subscriptions.smsBasic boolean no SMS Basic
subscriptions.sms boolean no SMS Pro


Update User

curl -L -X PUT 'https://api.wavv.com/v2/users/:userId' \
-H 'Authorization: Basic VENDOR_ID:API_KEY' \
-H 'Content-Type: application/json' \
--data-raw '{ "subscriptions": { "single": false } }'

The above command returns JSON structured like this:

{ "success": true }
PUT
api.wavv.com/v2/users/userId


Body Parameters

Name Type Required Description
firstName string no First name
lastName string no Last name
email string no Email address
phone string no Phone number
address1 string no Address
address2 string no Address line 2
city string no City
state string no State
zip string no Zip
subscriptions object no Subscriptions
subscriptions.single boolean no Power Dialer Single Line
subscriptions.multi boolean no Power Dialer Multiple Line
subscriptions.previewLine boolean no Preview Line Dialer
subscriptions.smsBasic boolean no SMS Basic
subscriptions.sms boolean no SMS Pro

Voicemails

List Voicemails

curl -L -X GET 'https://api.wavv.com/v2/users/:userId/voicemails' \
-H 'Authorization: Basic VENDOR_ID:API_KEY' \
-H 'Content-Type: application/json'

The above command returns JSON structured like this:

[
    {
        "id": "c25efb5c-3e4a-46f4-a2b9-ff2a48058737",
        "name": "These pretzels are making me thirsty",
        "createdAt": "2021-10-20T13:48:24.634Z",
        "seconds": 15,
        "url": "https://api.wavv.com/audio/messages/3e0d8287540a0252cb0c2b6f19ba3044/48388191-724f-44c9-8ae9-ca0dafb1193a.mp3"
    }
]
GET
api.wavv.com/v2/users/userId/voicemails


Get Voicemail

curl -L -X GET 'https://api.wavv.com/v2/users/:userId/voicemails/:voicemailId' \
-H 'Authorization: Basic VENDOR_ID:API_KEY' \
-H 'Content-Type: application/json'

The above command returns JSON structured like this:

{
    "id": "c25efb5c-3e4a-46f4-a2b9-ff2a48058737",
    "name": "These pretzels are making me thirsty",
    "createdAt": "2021-10-20T13:48:24.634Z",
    "seconds": 15,
    "url": "https://api.wavv.com/audio/messages/3e0d8287540a0252cb0c2b6f19ba3044/48388191-724f-44c9-8ae9-ca0dafb1193a.mp3"
}
GET
api.wavv.com/v2/users/userId/voicemails/voicemailId

Webhook URL

For more information, see the guide on Webhooks.

Get URL

curl -L -X GET 'https://api.wavv.com/v2/webhook' \
-H 'Authorization: Basic VENDOR_ID:API_KEY' \
-H 'Content-Type: application/json'

The above command returns JSON structured like this:

{ "url": "https://www.yourapp.com/api/wavv-event" }
GET
api.wavv.com/v2/webhook


Response Properties

Name Type Description
url string Current webhook URL


Set URL

curl -L -X PUT 'https://api.wavv.com/v2/webhook' \
-H 'Authorization: Basic VENDOR_ID:API_KEY' \
-H 'Content-Type: application/json' \
--data-raw '{ "url": "https://www.yourapp.com/api/wavv-event" }'

The above command returns JSON structured like this:

{ "success": true }
PUT
api.wavv.com/v2/webhook


Body Parameters

Name Type Required Description
url string yes URL for webhook events


Delete URL

curl -L -X DELETE 'https://api.wavv.com/v2/webhook' \
-H 'Authorization: Basic VENDOR_ID:API_KEY' \
-H 'Content-Type: application/json'

The above command returns JSON structured like this:

{ "success": true }
DELETE
api.wavv.com/v2/webhook

Guides

Tokens

import jwt from 'jsonwebtoken';

const issuer = VENDOR_ID;
const signature = API_KEY;

const payload = {
    userId: 'f5f31ed2-5427-4036-975a-ccebd1eabb84',
};

const options = { issuer, expiresIn: 3600 };

const token = jwt.sign(payload, signature, options);

WAVV uses JSON Web Tokens (JWTs) for front-end authentication.

There are two ways to obtain a token:


To generate your own token, follow these steps:


Merge Fields

Add custom merge field options:

import { setMergeFields } from '@wavv/messenger';

setMergeFields({
    fields: [
        { id: 'sqft', label: 'Square Feet' },
        { id: 'neighborhood', label: 'Neighborhood' },
    ],
});
const { setMergeFields } = window.WavvMessenger;

setMergeFields({
    fields: [
        { id: 'sqft', label: 'Square Feet' },
        { id: 'neighborhood', label: 'Neighborhood' },
    ],
});

Then provide values in each contact object:

{
    "contactId": "541d4a8b-c583-4b0b-aca3-0afb75abdec6",
    "mergeFields": [
        { "id": "sqft", "value": "4,000" },
        { "id": "neighborhood", "value": "Briarwood" }
    ]
}

WAVV allows you to add custom merge fields.

To get started with this:


Default Merge Fields

ID Label
name Full Name
first_name First Name
last_name Last Name
address Address
city City

Test Numbers

Send a message to (958) 555-1234:

Hello.

And it will echo back:

Hello.

WAVV provides several phone numbers for reliable, deterministic testing.

The last four digits of these numbers can be anything you want.


Number Calling Behavior Texting Behavior
(958) 555-XXXX Echos call audio Echos message body
(958) 666-XXXX Rings endlessly (no answer) No response
(958) 888-XXXX Plays voicemail greeting No response
(958) 777-XXXX Plays voice recording No response
(958) 444-XXXX Answers, quickly hangs up Delivery fails
(958) 000-XXXX Answers, presses 1, holds the line No response

REST API

Authentication

import axios from 'axios';

axios({
    method: 'PUT',
    url: 'https://api.wavv.com/v2/example',
    auth: {
        username: VENDOR_ID,
        password: API_KEY,
    },
    data: {
        email: 'george@vandelayindustries.com',
    },
});

All endpoints expect Basic Auth as follows:

Failure to authenticate will return status code 401.

Requests

Successful requests return data or an object of the form:

{ "success": true }

POST and PUT requests should be JSON encoded.

Ensure your Content-Type header is application/json.

Responses

Failed requests return an object of the form:

{ "success": false, "error": "Human-readable explanation" }

All responses will be a JSON object or array.

Status code will be one of: 200, 400, 404, or 500.

Webhooks

Configuration

To subscribe to webhook events, simply set your Webhook URL.

Requests

Webhook events will then POST to your URL.

The body will be a JSON object of the form {type, payload}.

For a list of event types and payloads, see Webhook Events.

Responses

Your server should respond with status code 200.

Failed requests will retry 10 times with exponential backoff.

Data

Types



Contact

{
    "contactId": "541d4a8b-c583-4b0b-aca3-0afb75abdec6",
    "numbers": ["9143504210", "9143505590"],
    "firstName": "George",
    "lastName": "Costanza",
    "name": "George Louis Costanza",
    "address": "1344 Queens Boulevard",
    "city": "Long Island",
    "avatarUrl": "https://wavv-public.s3.amazonaws.com/docs/summer/george.jpg",
    "subheading": "Architect",
    "mergeFields": [
        { "id": "sqft", "value": "4,000" },
        { "id": "neighborhood", "value": "Briarwood" }
    ]
}

Properties

Name Type Description
contactId string Unique ID
numbers array Phone numbers
firstName string First name
lastName string Last Name
name string Display name
address string Address
city string City
avatarUrl string Image URL for avatar
subheading string Displayed under name
mergeFields array Custom merge field data
mergeFields[].id string Merge field ID
mergeFields[].value string Merge field value

Enumerations



Call Outcome

import {
    CALL_OUTCOME_HUNG_UP,
    CALL_OUTCOME_USER_HUNG_UP,
    CALL_OUTCOME_NO_ANSWER,
    CALL_OUTCOME_BUSY,
    CALL_OUTCOME_DISCONNECTED,
    CALL_OUTCOME_CALLBACK,
    CALL_OUTCOME_VOICEMAIL,
    CALL_OUTCOME_NO_CALLBACK,
    CALL_OUTCOME_NO_VOICEMAIL,
    CALL_OUTCOME_UNKNOWN,
} from '@wavv/dialer';
const {
    CALL_OUTCOME_HUNG_UP,
    CALL_OUTCOME_USER_HUNG_UP,
    CALL_OUTCOME_NO_ANSWER,
    CALL_OUTCOME_BUSY,
    CALL_OUTCOME_DISCONNECTED,
    CALL_OUTCOME_CALLBACK,
    CALL_OUTCOME_VOICEMAIL,
    CALL_OUTCOME_NO_CALLBACK,
    CALL_OUTCOME_NO_VOICEMAIL,
    CALL_OUTCOME_UNKNOWN,
} = window.WavvDialer;

Enum Values

Name Description
HUNG_UP Callee hung up the line
USER_HUNG_UP User hung up the line
NO_ANSWER Call was not answered
BUSY Line was busy
DISCONNECTED Number was disconnected
CALLBACK Callback message was played
VOICEMAIL Voicemail message was played
NO_CALLBACK A callback message would have been played if the user had one recorded
NO_VOICEMAIL A voicemail message would have been played if the user had one recorded
UNKNOWN Call ended, but no one knows why



DNC Type

import {
    DNC_TYPE_MANUAL,
    DNC_TYPE_IVR_OPT_OUT,
    DNC_TYPE_SMS_OPT_OUT,
} from '@wavv/dialer';
const {
    DNC_TYPE_MANUAL,
    DNC_TYPE_IVR_OPT_OUT,
    DNC_TYPE_SMS_OPT_OUT,
} = window.WavvDialer;

Enum Values

Name Description
MANUAL Manually added
IVR_OPT_OUT Opt-opt via IVR prompt
SMS_OPT_OUT Opt-out via SMS STOP word

Webhook Events



Call Forwarded

{
    "type": "CALL_FORWARDED",
    "payload": {
        "userId": "f5f31ed2-5427-4036-975a-ccebd1eabb84",
        "phone": "8444545111",
        "destination": "9143504210"
    }
}

Payload Properties

Name Type Description
userId string User ID
phone string User phone number
destination string Destination phone number



Message Received

{
    "type": "MESSAGE_RECEIVED",
    "payload": {
        "userId": "f5f31ed2-5427-4036-975a-ccebd1eabb84",
        "to": "8444545111",
        "from": "9143504210",
        "body": "Hello, Jerry."
    }
}

Payload Properties

Name Type Description
userId string User ID
to string User phone number
from string Sending phone number
body string Body of the message



Message Sent

{
    "type": "MESSAGE_SENT",
    "payload": {
        "userId": "f5f31ed2-5427-4036-975a-ccebd1eabb84",
        "to": "9143504210",
        "from": "8444545111",
        "body": "Hello, Newman."
    }
}

Payload Properties

Name Type Description
userId string User ID
to string Receiving phone number
from string User phone number
body string Body of the message



Subscription Changed

{
    "type": "SUBSCRIPTION_CHANGED",
    "payload": {
        "userId": "f5f31ed2-5427-4036-975a-ccebd1eabb84",
        "subscriptions": { "multi": true }
    }
}

Payload Properties

Name Type Description
userId string User ID
subscriptions object Subscriptions
subscriptions.single boolean Power Dialer Single Line
subscriptions.multi boolean Power Dialer Multiple Line
subscriptions.previewLine boolean Preview Line Dialer
subscriptions.smsBasic boolean SMS Basic
subscriptions.sms boolean SMS Pro