@felipecoder/evolution-go-sdk
v1.0.1
Published
Typed TypeScript SDK for Evolution GO with WhatsApp calling support
Downloads
316
Maintainers
Readme
Install
npm install @felipecoder/evolution-go-sdkor:
pnpm add @felipecoder/evolution-go-sdkyarn add @felipecoder/evolution-go-sdkOverview
Evolution GO uses two authentication levels, and the SDK mirrors them with two separate clients.
EvolutionGoClient— authenticated with the server's global admin API key. Used for instance lifecycle management.InstanceClient— authenticated with a specific instance token. Used for messaging, chats, groups, communities, labels, calls and instance session operations.
Instance-scoped modules include:
- Call
- Chat
- Community
- Group
- Label
- Message
- Send Message
The SDK is fully typed and supports both ESM and CommonJS.
Admin client
Use EvolutionGoClient with your Evolution GO global API key.
import {
EvolutionGoClient,
EvolutionGoApiError,
} from "@felipecoder/evolution-go-sdk";
const admin = new EvolutionGoClient({
baseUrl: "https://your-evolution-go-server.com",
apiKey: process.env.EVOLUTION_GO_ADMIN_KEY!,
});
try {
const instance = await admin.instance.create({
name: "my-instance",
token: "secret",
});
const qr = await instance.getQr();
console.log(qr);
} catch (err) {
if (err instanceof EvolutionGoApiError) {
console.error(err.status, err.message, err.body);
} else {
throw err;
}
}The admin client provides instance lifecycle operations such as:
const instance = await admin.instance.create({
name: "my-instance",
token: "secret",
});
const instances = await admin.instance.getAll();
const info = await admin.instance.getInfo("inst-123");
await admin.instance.setProxy("inst-123", {
host: "proxy.example.com",
port: "8080",
});
await admin.instance.forceReconnect("inst-123");
const logs = await admin.instance.getLogs("inst-123", {
level: "error",
limit: 50,
});
await admin.instance.delete("inst-123");Instance client
If you already know the instance ID and token, you can create an InstanceClient directly.
import {
InstanceClient,
} from "@felipecoder/evolution-go-sdk";
const instance = new InstanceClient(
{
id: "inst-123",
token: "secret",
},
{
baseUrl: "https://your-evolution-go-server.com",
},
);The instance token is automatically used by all instance-scoped modules.
An Instance returned by create(), getInfo() or getAll() extends InstanceClient and also exposes its cached .data.
Calls
The SDK includes extended support for Evolution GO WhatsApp calls.
Supported call operations include:
- Dial outbound calls
- Answer incoming calls
- Reject incoming calls
- Hang up calls
- Send reactions
- Add participants
- Raise/lower hand
- Start/stop screen sharing
- Upgrade audio calls to video
- Enable/disable outbound video
- Set video orientation
- Connect to the real-time call media stream
Some advanced call features depend on Evolution GO versions or forks that include the extended
meowcallercall implementation.
Dial a call
const result = await instance.call.dial({
number: "5511999999999",
video: false,
});
console.log(result.callId);number can be a phone number or another identifier accepted by the underlying Evolution GO/meowcaller implementation.
For a video call:
const result = await instance.call.dial({
number: "5511999999999",
video: true,
});Answer a call
await instance.call.answer({
callId: "abc123",
callCreator: "[email protected]",
});Reject a call
await instance.call.reject({
callId: "abc123",
callCreator: "[email protected]",
});Hang up
await instance.call.hangup({
callId: "abc123",
});Send a reaction
await instance.call.react({
callId: "abc123",
emoji: "👍",
});Add a participant
await instance.call.addParticipant({
callId: "abc123",
number: "5511888888888",
});This can be used to add another participant to an active call.
Screen sharing
Start screen sharing:
await instance.call.screenShare({
callId: "abc123",
start: true,
});Stop screen sharing:
await instance.call.screenShare({
callId: "abc123",
start: false,
});Hand raise
Raise hand:
await instance.call.handRaise({
callId: "abc123",
raised: true,
});Lower hand:
await instance.call.handRaise({
callId: "abc123",
raised: false,
});Video upgrade
Upgrade an active audio call to video:
await instance.call.videoUpgrade({
callId: "abc123",
start: true,
});Stop outbound video while keeping the call:
await instance.call.videoUpgrade({
callId: "abc123",
start: false,
});Enable or disable outbound video
await instance.call.videoEnabled({
callId: "abc123",
enabled: true,
});Disable without renegotiating the call:
await instance.call.videoEnabled({
callId: "abc123",
enabled: false,
});Video orientation
Evolution GO represents orientation as quarter turns clockwise (0 to 3).
await instance.call.videoOrientation({
callId: "abc123",
orientation: 1,
});Call media stream
Calls can expose a dedicated WebSocket connection for lifecycle events and real-time media.
Create a call and connect to its stream:
const result = await instance.call.dial({
number: "5511999999999",
video: false,
});
const stream = instance.call.stream(
result.callId,
);The SDK automatically derives the WebSocket URL from the configured Evolution GO baseUrl and authenticates it using the instance token.
For example:
https://example.comis converted internally to:
wss://example.com/call/stream/:callId?apikey=INSTANCE_TOKENYou don't need to construct this URL manually.
Call lifecycle events
Listen for the WebSocket connection:
stream.on("open", () => {
console.log("Call stream connected");
});Listen for call state changes:
stream.on("state", ({ state }) => {
console.log("Call state:", state);
});Possible states currently include:
idle
calling
ringing
connecting
active
ended
waiting_roomListen for the peer accepting the call:
stream.on("accepted", ({ callId }) => {
console.log("Call accepted:", callId);
});Listen for the call ending:
stream.on("stop", ({ reason }) => {
console.log("Call ended:", reason);
});The termination reason is intentionally exposed as a string.
Depending on Evolution GO, meowcaller and the remote WhatsApp client, different termination reasons may be emitted.
Examples observed by the extended implementation include:
rejected
timeout
hangupDo not rely on those being the only possible values.
Receiving media
Listen for incoming media:
stream.on("media", ({
track,
payload,
}) => {
console.log(
"Media:",
track,
payload.length,
);
});Media payloads are transported as Base64.
For audio calls, the current Evolution GO call stream uses PCM16LE mono audio at 16 kHz.
Sending media
Send outbound media using:
stream.sendMedia(base64Payload);For example:
stream.on("open", () => {
stream.sendMedia(base64Pcm);
});The SDK sends the corresponding WebSocket message:
{
"event": "media",
"track": "outbound",
"payload": "..."
}When sending audio, callers should respect the frame format expected by the Evolution GO call bridge.
Raw call events
The SDK also exposes every recognized stream event through raw:
stream.on("raw", (event) => {
console.log(event);
});Current protocol events include:
start
state
accepted
media
stopThis is useful when building custom call handling, recording, WebRTC bridges, softphones or other real-time integrations.
Closing the stream
stream.close();You can optionally provide a WebSocket close code and reason:
stream.close(
1000,
"client closed stream",
);Closing the stream is not the same as hanging up the WhatsApp call.
To terminate the actual call, use:
await instance.call.hangup({
callId,
});Instance session
Connect:
await instance.connect({
phone: "5511999999999",
});Get QR code:
const qr = await instance.getQr();Get connection status:
const status = await instance.getStatus();Pair:
await instance.pair({
phone: "5511999999999",
});Other operations:
await instance.disconnect();
await instance.reconnect();
await instance.logout();Advanced settings:
const settings =
await instance.getAdvancedSettings();
await instance.updateAdvancedSettings({
rejectCall: true,
});Chat
await instance.chat.archive(jid);
await instance.chat.pin(jid);
await instance.chat.mute(jid);
await instance.chat.historySyncRequest({
count: 50,
});Unarchive, unpin and unmute operations are also available.
You can also create a local chat handle:
const chat = instance.chat.from(
"[email protected]",
);
await chat.archive();Community
const community =
await instance.community.create(
"My Community",
);
await community.addParticipants([
"[email protected]",
]);Group
Create a group:
const group =
await instance.group.create({
groupName: "Dev Team",
participants: [
"[email protected]",
],
});Other examples:
const groups =
await instance.group.list();
const myGroups =
await instance.group.myGroups();
await instance.group.join(
"<invite-code>",
);Entities expose bound operations:
await group.setName("New name");
await group.updateSettings("locked");
await group.leave();
await group.refresh();Label
const labels =
await instance.label.list();
await labels[0].edit({
name: "Urgent",
color: 2,
});
await labels[0].addToChat(jid);Message
Create a local message handle:
const message =
instance.message.from({
chat: jid,
id: "msg-1",
});
await message.markRead();
await message.edit(
"new text",
);
const status =
await message.getStatus();Download media from a raw Evolution GO message:
const media =
await instance.message.downloadMedia({
message: rawWebhookMessage,
});Send Message
Send text:
const sent =
await instance.sendMessage.text({
number: "5511999999999",
text: "Hi!",
});The returned value is a Message entity, so it can immediately be used:
await sent.react("👍");Other supported message types include:
- Text
- Media
- Sticker
- Location
- Contact
- Link
- Button
- Carousel
- List
- Poll
- Status text
- Status media
Example:
await instance.sendMessage.media({
number: "5511999999999",
url: "https://example.com/image.jpg",
type: "image",
});Error handling
All non-2xx API responses throw EvolutionGoApiError.
import {
EvolutionGoApiError,
} from "@felipecoder/evolution-go-sdk";
try {
await instance.group.getInfo(
"invalid-jid",
);
} catch (err) {
if (
err instanceof EvolutionGoApiError
) {
console.error(
err.status,
err.message,
err.body,
);
}
}The error exposes:
err.status;
err.message;
err.body;Custom transport
A custom fetch implementation can be provided:
const client = new EvolutionGoClient({
baseUrl: "https://your-server.com",
apiKey: "your-api-key",
fetch: customFetch,
});A custom WebSocket implementation can also be provided when necessary:
const instance = new InstanceClient(
{
id: "inst-123",
token: "secret",
},
{
baseUrl: "https://your-server.com",
WebSocket: CustomWebSocket,
},
);API documentation
Evolution GO exposes its Swagger UI at:
/swagger/index.htmlThe exact API surface may depend on the Evolution GO version or fork being used.
Development
Install dependencies:
pnpm installType check:
pnpm check-typesRun tests:
pnpm testLint:
pnpm lintBuild:
pnpm buildBefore submitting changes, it is recommended to run:
pnpm lint
pnpm check-types
pnpm test
pnpm buildEvolution GO compatibility
This SDK can be used with the official Evolution GO API for the endpoints supported by the upstream project.
However, the complete call API documented by this SDK — including outbound
calls, answering calls, call lifecycle events, media streaming, reactions,
participants, screen sharing and video controls — requires an Evolution GO
build containing the extended meowcaller call implementation.
Recommended Evolution GO image
For full compatibility with this SDK, including all call features, use:
services:
evolution-go:
image: felipecoder/evolution-go:latestOr with Docker directly:
docker pull felipecoder/evolution-go:latestdocker run felipecoder/evolution-go:latestThe felipecoder/evolution-go:latest image is based on Evolution GO v0.7.2
and includes the extended WhatsApp calling implementation used and tested by
this SDK.
Compatibility matrix
| Feature | Official Evolution GO | felipecoder/evolution-go:latest |
|---|---:|---:|
| Instance management | ✅ | ✅ |
| Messages | ✅ | ✅ |
| Chats | ✅ | ✅ |
| Groups | ✅ | ✅ |
| Communities | ✅ | ✅ |
| Labels | ✅ | ✅ |
| Reject calls | ✅ | ✅ |
| Dial outbound calls | Depends on upstream version | ✅ |
| Answer calls | Depends on upstream version | ✅ |
| Hang up calls | Depends on upstream version | ✅ |
| Call lifecycle events | Depends on upstream version | ✅ |
| Call media WebSocket | Depends on upstream version | ✅ |
| Bidirectional audio | Depends on upstream version | ✅ |
| Call reactions | Depends on upstream version | ✅ |
| Add call participants | Depends on upstream version | ✅ |
| Screen sharing | Depends on upstream version | ✅ |
| Hand raise | Depends on upstream version | ✅ |
| Video upgrade/control | Depends on upstream version | ✅ |
[!IMPORTANT] If you are using the official Evolution GO Docker image, some advanced call methods exposed by this SDK may return
404or may not be available, depending on the Evolution GO version installed.
For the complete SDK feature set, use:
felipecoder/evolution-go:latestThe custom image tracks the Evolution GO base used by this project while including the additional calling functionality required by the SDK.
Quick start with Docker
A minimal example using the compatible Evolution GO image:
services:
evolution-go:
image: felipecoder/evolution-go:latest
container_name: evolution-go
restart: unless-stopped
env_file:
- .env
ports:
- "4000:4000"Then configure the SDK:
import {
EvolutionGoClient,
} from "@felipecoder/evolution-go-sdk";
const evolution = new EvolutionGoClient({
baseUrl: "http://localhost:4000",
apiKey: process.env.EVOLUTION_GO_API_KEY!,
});For production environments, use HTTPS. The SDK automatically converts an HTTPS API URL to WSS when connecting to call media streams.
For example:
https://evolution.example.combecomes:
wss://evolution.example.com/call/stream/:callIdThe instance token is automatically included by the SDK when opening the stream.
Credits
This project was originally based on the MIT-licensed
@solufy/evolution-go-sdk
and has been extended with additional Evolution GO functionality, including advanced WhatsApp call control and real-time call/media streaming support.
Thanks to the original project contributors for the initial SDK architecture and implementation.
Evolution GO is developed by the Evolution Foundation.
The extended calling functionality is built on top of the Evolution GO/meowcaller integration.
Author
Felipe Bruno
GitHub: @felipecoder
License
MIT
