Skip to content

SDK Overview

Inboxical provides official SDKs that wrap the REST API with type-safe, ergonomic methods. Choose the package that matches your test runner.

PackageUse case
@inboxical/sdkNode.js — Jest, Vitest, Mocha, or any Node runtime
@inboxical/playwrightPlaywright e2e tests with auto-managed mailboxes
@inboxical/cypressCypress e2e tests via cy.task() integration

The core Node.js client. All other SDKs use this under the hood.

Terminal window
npm install @inboxical/sdk
import { Inboxical } from '@inboxical/sdk'
const client = new Inboxical({
apiKey: process.env.INBOXICAL_API_KEY!,
})
// Create an inbox
const inbox = await client.createInbox({ name: 'signup-test' })
console.log(inbox.email_address) // [email protected]
// Trigger your app to send an email...
// Wait for the message (long-poll, up to 30s)
const message = await client.waitForMessage(inbox.id, { timeout: 30 })
console.log(message.subject) // "Welcome to MyApp!"
// Extract a verification code from the email body
const code = client.extractCode(message)
console.log(code) // "482910"
// Clean up
await client.deleteInbox(inbox.id)
const client = new Inboxical({
apiKey: 'ixk_live_...', // Required
baseUrl: 'https://....', // Optional — default: https://api.inboxical.com
timeout: 30_000, // Optional — request timeout in ms (default: 30000)
})
MethodDescription
createInbox(options?)Create a new test inbox. Options: { name?, domain? }
listInboxes(options?)List inboxes with pagination. Options: { page?, limit? }
getInbox(inboxId)Get a single inbox by ID
deleteInbox(inboxId)Delete an inbox and all its messages
MethodDescription
getMessages(inboxId, options?)List messages with pagination. Options: { page?, limit? }
getLatestMessage(inboxId)Get the most recent message in an inbox
waitForMessage(inboxId, options?)Long-poll until a message arrives. Options: { timeout?, since? }
getMessage(messageId)Get a single message by ID
deleteMessage(messageId)Delete a single message
MethodDescription
extractCode(message, options?)Extract an OTP/verification code from a message body

Searches the message body for common verification code patterns (4-8 digit numbers preceded by words like “code”, “otp”, “pin”). Returns the code string or null.

const message = await client.waitForMessage(inbox.id)
// Auto-detect common patterns
const code = client.extractCode(message)
// Or supply a custom regex with a capture group
const code = client.extractCode(message, {
pattern: /verification-code: ([A-Z0-9]{6})/i,
})
import { InboxicalApiError, InboxicalNetworkError } from '@inboxical/sdk'
try {
const message = await client.waitForMessage(inbox.id, { timeout: 10 })
} catch (err) {
if (err instanceof InboxicalApiError) {
console.log(err.status) // 408 (timeout), 404, etc.
console.log(err.code) // Machine-readable error code
}
if (err instanceof InboxicalNetworkError) {
console.log(err.message) // "Request timed out after 15000ms"
}
}

All types are exported from the package:

import type {
Inbox,
Message,
InboxList,
MessageList,
InboxicalOptions,
CreateInboxOptions,
PaginationOptions,
WaitForMessageOptions,
ExtractCodeOptions,
} from '@inboxical/sdk'

A high-level mailbox helper designed for Playwright tests. Manages inbox lifecycle automatically.

Terminal window
npm install @inboxical/playwright
import { test, expect } from '@playwright/test'
import { InboxicalMailbox } from '@inboxical/playwright'
test('user receives verification email', async ({ page }) => {
const mailbox = new InboxicalMailbox()
const { email } = await mailbox.create({ name: 'verify-test' })
await page.goto('/signup')
await page.fill('#email', email)
await page.click('button[type=submit]')
const message = await mailbox.waitForMessage({ timeout: 30 })
expect(message.subject).toContain('Verify')
const code = await mailbox.extractCode()
await page.fill('#code', code)
await page.click('#verify')
await expect(page.locator('.success')).toBeVisible()
await mailbox.cleanup()
})

InboxicalMailbox reads INBOXICAL_API_KEY from the environment by default. You can override it:

const mailbox = new InboxicalMailbox({
apiKey: 'ixk_live_...', // Optional — defaults to INBOXICAL_API_KEY env var
baseUrl: 'https://...', // Optional
})
MethodDescription
create(options?)Create a new inbox. Returns { id, email }. Cleans up any previous inbox
waitForMessage(options?)Long-poll for a message. Options: { timeout?, since? }
getMessages()Get all messages in the current inbox
getLatestMessage()Get the latest message
extractCode(options?)Extract OTP from the last fetched message. Options: { pattern? }
cleanup()Delete the current inbox. Safe to call multiple times
getClient()Access the underlying Inboxical SDK client
getInboxId()Get the current inbox ID (or null)
getEmail()Get the current inbox email address (or null)

Use createMailboxFixture() for automatic cleanup after each test:

tests/fixtures.ts
import { test as base } from '@playwright/test'
import { InboxicalMailbox, createMailboxFixture } from '@inboxical/playwright'
export const test = base.extend<{ mailbox: InboxicalMailbox }>({
mailbox: createMailboxFixture(),
})
tests/signup.spec.ts
import { test } from './fixtures'
import { expect } from '@playwright/test'
test('welcome email after signup', async ({ page, mailbox }) => {
const { email } = await mailbox.create()
await page.goto('/register')
await page.fill('[name=email]', email)
await page.fill('[name=password]', 'test-password-123')
await page.click('[type=submit]')
const message = await mailbox.waitForMessage({ timeout: 30 })
expect(message.subject).toBe('Welcome to MyApp!')
await mailbox.cleanup()
})

Registers Cypress tasks that call the Inboxical API from the Node.js process (required because Cypress commands run in the browser and cannot make cross-origin API calls directly).

Terminal window
npm install @inboxical/cypress

1. Register the plugin in cypress.config.ts:

import { defineConfig } from 'cypress'
import { setupInboxical } from '@inboxical/cypress'
export default defineConfig({
e2e: {
setupNodeEvents(on, config) {
setupInboxical(on, config, {
apiKey: process.env.INBOXICAL_API_KEY,
})
return config
},
},
})

You can also set INBOXICAL_API_KEY in cypress.env.json instead of passing it in options.

TaskArgumentsReturns
inboxicalCreateInbox{ name?, domain? } or null{ id, email }
inboxicalGetInboxinboxId (string)Inbox object
inboxicalDeleteInboxinboxId (string)null
inboxicalGetMessagesinboxId (string)Message[]
inboxicalGetLatestMessageinboxId (string)Message object
inboxicalWaitForMessage{ inboxId, timeout?, since? }Message object
inboxicalGetMessagemessageId (string)Message object
inboxicalDeleteMessagemessageId (string)null
inboxicalExtractCode{ message, pattern? }string | null
cypress/e2e/signup.cy.ts
describe('Signup email flow', () => {
let inbox: { id: string; email: string }
beforeEach(() => {
cy.task('inboxicalCreateInbox', { name: 'signup-test' }).then((result) => {
inbox = result as { id: string; email: string }
})
})
afterEach(() => {
cy.task('inboxicalDeleteInbox', inbox.id)
})
it('sends welcome email after signup', () => {
cy.visit('/register')
cy.get('[name=email]').type(inbox.email)
cy.get('[name=password]').type('test-password-123')
cy.get('[type=submit]').click()
cy.url().should('include', '/dashboard')
cy.task('inboxicalWaitForMessage', {
inboxId: inbox.id,
timeout: 30,
}).then((message: any) => {
expect(message.subject).to.equal('Welcome to MyApp!')
})
})
it('extracts verification code from email', () => {
cy.visit('/register')
cy.get('[name=email]').type(inbox.email)
cy.get('[name=password]').type('test-password-123')
cy.get('[type=submit]').click()
cy.task('inboxicalWaitForMessage', {
inboxId: inbox.id,
timeout: 30,
}).then((message: any) => {
cy.task('inboxicalExtractCode', { message }).then((code) => {
cy.get('#verification-code').type(code as string)
cy.get('#verify-button').click()
cy.contains('Email verified').should('be.visible')
})
})
})
})