API Reference · v1

Bizmitra Notify API

One unified HTTP API for transactional messaging across every channel — like Resend, but channel-agnostic. Send through the same endpoint, swap providers without touching your code, and track delivery end to end.

Today: the email channel is live via the Brevo adapter. SMS, WhatsApp and Push are on the roadmap and will plug into the same /messages/send endpoint — only the channel value changes.

Base URL

All endpoints are served under the /api prefix.

https://your-domain.com/api

Authentication

Authenticate with a tenant-scoped API key via the Authorization header using the Bearer scheme. Generate keys from the Developer Dashboard → API Keys.

Authorization: Bearer nk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Keys are shown once at creation. The server stores only a SHA-256 hash and an 8-character prefix used for tenant resolution. Treat the full key like a password — rotate immediately if exposed.

Quickstart

Send your first email in under a minute:

curl -X POST https://your-domain.com/api/messages/send \
  -H "Authorization: Bearer nk_live_xxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "channel": "email",
    "to": "jane@example.com",
    "subject": "Welcome to Acme",
    "event_key": "user_welcome",
    "transaction_id": "ord_8421",
    "data": {
      "first_name": "Jane",
      "activation_url": "https://acme.com/activate/abc123"
    }
  }'

You'll get back a queued message ID you can correlate with webhook callbacks:

{
  "message_id": "01HZX7K...",
  "status": "queued"
}

Channels & Providers

A channel is the medium (email, SMS, WhatsApp, push). A provider is the underlying vendor that actually delivers the message. Notify abstracts the two so you can route, fail over and price independently.

Email Live Provider: Brevo (transactional SMTP API)
"channel": "email"
WhatsApp Roadmap Adapter scaffolded (BrevoWhatsAppAdapter) — schema-stable, not yet routable
"channel": "whatsapp"
SMS Roadmap Pluggable via the same provider-adapter contract
"channel": "sms"
Push Roadmap Mobile & web push, planned
"channel": "push"

Templates & Events

Every send references a server-side template via event_key. Templates are created from the Developer Dashboard and bound to a channel and tenant. The runtime resolves event_key + channel + is_active=true and renders the body with the values in data.

If a matching template isn't found for your tenant, Notify falls back to the test_email template (when present) so your integration never crashes silently during onboarding.

Idempotency

Pass a unique transaction_id on every request. Notify derives a business-event ID from it ({transaction_id}_{action}), so safe retries from your side will not double-send. Reuse the same transaction_id when retrying a failed network call.

Rate Limits & Quotas

LimitDefaultResponse
Per-tenant burst100 requests / minute429 Rate limit exceeded
Sustained tenant rate20 requests / minute429 Too many requests in the last minute
Daily send quota100 messages / day / tenant429 Daily quota exceeded
Event ingestion100 requests / minute429
Provider webhooks300 requests / minute429

Defaults shown — contact us for higher tiers.

Send a Message

POST /api/messages/send

The single endpoint you use for every channel. Today only email is routable.

Headers

NameRequiredDescription
AuthorizationRequiredBearer token — your tenant API key
Content-TypeRequiredapplication/json

Body Parameters

FieldTypeRequiredDescription
channelstringRequiredCurrently "email". More channels coming.
tostringRequiredRecipient address (must be a valid email for the email channel)
subjectstringRequiredSubject line for email channel
event_keystringRequiredName of the template to render (must exist for your tenant + channel)
transaction_idstringRequiredYour unique ID for this send — used for idempotency and reconciliation
dataobjectOptionalKey/value map merged into the template variables
actionstringOptionalLogical action (default: "send"). Appended to the business-event ID for idempotency scoping.

Example Request

POST /api/messages/send HTTP/1.1
Host: your-domain.com
Authorization: Bearer nk_live_xxxxxxxx
Content-Type: application/json

{
  "channel": "email",
  "to": "customer@example.com",
  "subject": "Your order has shipped",
  "event_key": "order_shipped",
  "transaction_id": "ord_8421",
  "data": {
    "order_id": "8421",
    "tracking_url": "https://track.acme.com/8421"
  }
}

Success Response 200 OK

{
  "message_id": "01HZX7K2A0Q8VVQH...",
  "status": "queued"
}

Error Responses

StatusCode pathMeaning
401Missing / Invalid API KeyAuthorization header absent or key not found
403Tenant inactiveAPI key resolved but the tenant is suspended
422Invalid templateNo active template matched event_key + channel
429Rate limit / quotaSee Rate Limits
500Dispatch failedProvider error — safe to retry with the same transaction_id

Ingest a Business Event

POST /api/events

Forward business events from your apps (ERP, billing, CRM) so Notify can react with the correct template + channel. Events are deduplicated by event_id and processed asynchronously.

Body Parameters

FieldTypeRequiredDescription
event_idstring ≤ 64RequiredUnique ID — repeats return {"status":"duplicate"}
event_namestring ≤ 100Requirede.g. order.shipped
sourcestring ≤ 50RequiredOriginating system, e.g. erp
org_idintegerRequiredTenant org ID
actor.typestring ≤ 20Requirede.g. user, system
actor.idintegerOptionalActor identifier in your system
dataobjectRequiredFree-form event payload
occurred_atISO 8601 dateRequiredWhen the event happened in source-of-truth

Response

{ "status": "accepted" }

Provider Webhooks (inbound)

POST /api/webhooks/{provider}

Endpoint Notify exposes for providers to call. Configure this URL in your provider dashboard (e.g. Brevo → Transactional → Webhooks) and Notify will normalize the payload into a unified delivery-status lifecycle. Signatures are verified per provider — unsigned or invalid requests get 403.

Supported {provider} values today: brevo.

Health Check

GET /api/health

Unauthenticated liveness probe — safe for uptime monitors and load balancers.

{ "status": "ok", "service": "bizmitra-notify" }

Errors

Errors use standard HTTP status codes with a JSON body:

{ "error": "Invalid template" }

For validation failures, Laravel's default 422 shape applies with a message and errors map keyed by field.

Delivery Status Lifecycle

Once dispatched, a message moves through these normalized states (the same vocabulary regardless of provider):

StatusMeaning
queuedAccepted by Notify, not yet handed to a provider
sentProvider accepted the message for delivery
deliveredRecipient mailbox / device received it
openedRecipient opened the message (channel-dependent)
clickedA tracked link was clicked
bouncedHard or soft bounce reported by the provider
failedPermanent failure — see provider response logged on the message

Changelog

v1 · Initial release

  • Unified /messages/send endpoint
  • Email channel live via Brevo adapter
  • Tenant-scoped API keys with prefix lookup and SHA-256 hashing
  • Provider webhook normalization (Brevo)
  • Async event ingestion with idempotency