Fourbyfour
ServicesDocs
Get Started
PricingDocsAboutBlogCareerSupportDiscordPrivacyTerms

© 2026 Occupy Mars Private Limited. All rights reserved.

Getting Started

Services

Documentation

Three services. One SDK. Zero infrastructure.

Stream

Publish and consume events in real-time. Topics, partitions, consumer groups.

Notifications

Send email, SMS, push, and in-app notifications. Templates included.

Hooks

Deliver webhooks with retries, signatures, and delivery tracking.

Installation

Install the SDK:

npm install @fourbyfour/sdk

Initialize the client:

import { Fourbyfour } from '@fourbyfour/sdk';

const client = new Fourbyfour({
  apiKey: process.env.FOURBYFOUR_API_KEY,
  projectId: process.env.FOURBYFOUR_PROJECT_ID
});

Get your API key from the dashboard.

Quick Start

Stream

— Publish and consume events
// Publish an event
await client.stream.topics.produce('order.placed', {
  key: 'order-123',
  value: { orderId: '123', amount: 99.99 }
});

// Consume events
const { records } = await client.stream.topics.consume('order.placed', {
  group: 'order-processor'
});

for (const record of records) {
  console.log('Received:', record.value);
}

Notifications

— Send a notification
// Send an email notification
await client.notifications.send({
  channel: 'email',
  recipient: 'user@example.com',
  subject: 'Order Confirmed',
  body: 'Your order #123 has been confirmed.'
});

// Or use a template
await client.notifications.sendFromTemplate({
  template: 'order-confirmation',
  recipient: 'user@example.com',
  data: { orderId: '123', total: '$99.99' }
});

Hooks

— Send a webhook
// Register an endpoint
const endpoint = await client.hooks.createEndpoint({
  url: 'https://api.partner.com/webhook',
  events: ['order.placed', 'order.shipped']
});

// Send a webhook
await client.hooks.send({
  eventType: 'order.placed',
  payload: { orderId: '123', amount: 99.99 }
});

Services Overview

Three services, one SDK. Each service handles a specific infrastructure need.

Stream

Real-time event streaming with topics, partitions, and consumer groups. Kafka-compatible semantics.

Notifications

Multi-channel notifications via email, SMS, push, and webhooks. Template support with variable substitution.

Hooks

Webhook delivery with HMAC signatures, automatic retries, and delivery tracking.

Stream

Real-time event streaming with topics, partitions, and consumer groups. Kafka-compatible semantics.

Key Concepts

Topics

Named event channels. Events are partitioned for parallel processing.

Partitions

Events with the same key always go to the same partition, preserving order.

Consumer Groups

Multiple consumers can share work. Each partition is consumed by one group member.

Offsets

Position markers. Commit offsets to track progress and resume after failures.

Topics

Events

Statistics

Notifications

Multi-channel notifications via email, SMS, push, and webhooks. Template support with variable substitution.

Key Concepts

Channels

Email, SMS, push, and webhook. Each channel has specific recipient validation.

Templates

Reusable message templates with {{variable}} substitution.

Status Lifecycle

pending -> sent -> delivered (or failed). Async processing with retries.

Sending

Templates

Statistics

Hooks

Webhook delivery with HMAC signatures, automatic retries, and delivery tracking.

Key Concepts

Endpoints

Registered webhook URLs. Each gets a unique secret for signature verification.

Signatures

X-Webhook-Signature header contains HMAC-SHA256 of payload. Verify to ensure authenticity.

Deliveries

Each webhook attempt is tracked. HTTP 2xx = success. Automatic retries on failure.

Event Filtering

Endpoints can subscribe to specific event types or receive all events.

Endpoints

Webhooks

Deliveries

Statistics

Verifying Webhook Signatures

Always verify the X-Webhook-Signature header to ensure the webhook is authentic.

import crypto from 'crypto';

function verifySignature(payload: string, signature: string, secret: string): boolean {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}

// In your webhook handler:
app.post('/webhook', (req, res) => {
  const signature = req.headers['x-webhook-signature'];
  const deliveryId = req.headers['x-webhook-delivery-id'];

  if (!verifySignature(JSON.stringify(req.body), signature, WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }

  // Process webhook...
  res.status(200).send('OK');
});