Docs/SDKs & Libraries

SDKs & Libraries

Official SDKs for every major language. Type-safe, well-documented, and designed for developer productivity.

Quick Install

Install via npm, pip, gem, or your preferred package manager.

Type Safety

Full TypeScript, type hints, and IDE autocompletion support.

Built-in Retries

Automatic retry logic with exponential backoff.

Official SDKs

Node.js

v1.2.0
@canary/node
npm install @canary/node
TypeScript supportESM & CommonJSAuto-retries
View on GitHub

Python

v1.1.0
canary-python
pip install canary-python
Type hintsAsync supportPydantic models
View on GitHub

Ruby

v1.0.0
canary
gem install canary
Rails integrationFaraday clientZeitwerk loader
View on GitHub

Go

v1.0.0
github.com/canary/canary-go
go get github.com/canary/canary-go
Context supportGenericsZero dependencies
View on GitHub

PHP

v1.0.0
canary/canary-php
composer require canary/canary-php
PHP 8.1+Laravel facadePSR-18 client
View on GitHub

Java

v1.0.0
dev.canary:canary-java
implementation 'dev.canary:canary-java:1.0.0'
Java 11+Spring BootReactive support
View on GitHub

Quick Start

Get started with Canary in your language of choice. All SDKs provide the same functionality with idiomatic APIs.

Node.js / TypeScript

example.ts
import Canary from '@canary/node';

const canary = new Canary(process.env.CANARY_API_KEY);

// Send an SMS
const message = await canary.sms.send({
  to: '+15551234567',
  message: 'Hello from Canary!'
});

console.log('Message ID:', message.id);

// Send an email
const email = await canary.email.send({
  to: 'user@example.com',
  from: 'hello@yourcompany.com',
  subject: 'Welcome!',
  html: '<h1>Welcome to our app!</h1>'
});

// Verify a phone number
const verification = await canary.verify.send({
  to: '+15551234567',
  channel: 'sms'
});

const result = await canary.verify.check({
  verification_id: verification.id,
  code: '123456'
});

Python

example.py
from canary import Canary

canary = Canary(api_key=os.environ["CANARY_API_KEY"])

# Send an SMS
message = canary.sms.send(
    to="+15551234567",
    message="Hello from Canary!"
)

print(f"Message ID: {message.id}")

# Send an email
email = canary.email.send(
    to="user@example.com",
    from_="hello@yourcompany.com",
    subject="Welcome!",
    html="<h1>Welcome to our app!</h1>"
)

# Verify a phone number
verification = canary.verify.send(
    to="+15551234567",
    channel="sms"
)

result = canary.verify.check(
    verification_id=verification.id,
    code="123456"
)

Ruby

example.rb
require 'canary'

Canary.api_key = ENV['CANARY_API_KEY']

# Send an SMS
message = Canary::SMS.send(
  to: '+15551234567',
  message: 'Hello from Canary!'
)

puts "Message ID: #{message.id}"

# Send an email
email = Canary::Email.send(
  to: 'user@example.com',
  from: 'hello@yourcompany.com',
  subject: 'Welcome!',
  html: '<h1>Welcome to our app!</h1>'
)

# Verify a phone number
verification = Canary::Verify.send(
  to: '+15551234567',
  channel: 'sms'
)

result = Canary::Verify.check(
  verification_id: verification.id,
  code: '123456'
)

Go

main.go
package main

import (
    "context"
    "fmt"
    "os"

    "github.com/canary/canary-go"
)

func main() {
    client := canary.NewClient(os.Getenv("CANARY_API_KEY"))
    ctx := context.Background()

    // Send an SMS
    message, err := client.SMS.Send(ctx, &canary.SMSParams{
        To:      "+15551234567",
        Message: "Hello from Canary!",
    })
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("Message ID: %s\n", message.ID)

    // Send an email
    email, err := client.Email.Send(ctx, &canary.EmailParams{
        To:      "user@example.com",
        From:    "hello@yourcompany.com",
        Subject: "Welcome!",
        HTML:    "<h1>Welcome to our app!</h1>",
    })

    // Verify a phone number
    verification, err := client.Verify.Send(ctx, &canary.VerifyParams{
        To:      "+15551234567",
        Channel: "sms",
    })

    result, err := client.Verify.Check(ctx, &canary.VerifyCheckParams{
        VerificationID: verification.ID,
        Code:           "123456",
    })
}

Configuration

All SDKs support the same configuration options for customizing behavior.

OptionTypeDefaultDescription
api_keystring-Your Canary API key
base_urlstringapi.canarymsg.devAPI base URL (for testing)
timeoutnumber30000Request timeout in milliseconds
max_retriesnumber3Maximum retry attempts
debugbooleanfalseEnable debug logging

Error Handling

All SDKs throw typed exceptions that you can catch and handle appropriately.

// Node.js / TypeScript
import { CanaryError, RateLimitError, ValidationError } from '@canary/node';

try {
  await canary.sms.send({ to: '+15551234567', message: 'Hello!' });
} catch (error) {
  if (error instanceof RateLimitError) {
    // Wait and retry
    const retryAfter = error.retryAfter;
    console.log(`Rate limited. Retry after ${retryAfter}s`);
  } else if (error instanceof ValidationError) {
    // Fix the request
    console.log('Validation error:', error.errors);
  } else if (error instanceof CanaryError) {
    // Handle other API errors
    console.log('API error:', error.message, error.code);
  }
}

Webhook Verification

All SDKs include helpers for verifying webhook signatures to ensure requests are genuinely from Canary.

// Node.js / Express
import { verifyWebhookSignature } from '@canary/node';

app.post('/webhooks/canary', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-canary-signature'];
  const timestamp = req.headers['x-canary-timestamp'];

  const isValid = verifyWebhookSignature({
    payload: req.body,
    signature,
    timestamp,
    secret: process.env.CANARY_WEBHOOK_SECRET,
  });

  if (!isValid) {
    return res.status(401).send('Invalid signature');
  }

  const event = JSON.parse(req.body);
  console.log('Received event:', event.type);

  res.status(200).send('OK');
});

Community SDKs

Build Your Own SDK

Don't see your language? Our REST API is fully documented and easy to integrate. We also welcome community SDK contributions!

Next Steps