v1.0.0
OAS 3.1.0

Blocx API

Blocx is the multi-channel transactional API for product teams that need email, SMS/MMS, Telegram, and 2FA verification from a single provider — one bill, one SDK, one webhook contract.

Why Blocx

  • One API, every channel a real product needs. Transactional email, marketing email, SMS, MMS, Telegram, and 2FA verification through the same authentication, SDK, and signed webhook envelope. No second integration when you outgrow email-only — and no second integration ever for OTP/2FA over SMS or Telegram.
  • 2FA verification as a first-class service. Multi-channel verifications (EMAIL, SMS, TELEGRAM) with template approval, per-channel sender selection, and pay-on-delivery billing for Telegram. Drop-in replacement for hand-rolled OTP pipelines built on top of a generic email or SMS API.
  • Carrier-registered SMS, included. 10DLC brand registration, campaign registration, and downstream carrier sharing are first-class API resources — register and start sending without a side contract or third-party compliance vendor.
  • Receive, not just send. Inbound email with parsed MIME, SPF/DKIM/DMARC/spam/virus verdicts, presigned S3 attachment URLs, and a dedicated mailbox per address. Inbound SMS/MMS on every provisioned number. Both arrive through the same signed webhook contract you already wired up for outbound events.
  • Deliverability you can audit. Per-domain DKIM/SPF/DMARC setup, dedicated IP option on paid plans, open/click tracking opt-in per identity, and a full event stream (email.delivered, email.bounced, email.complained, email.opened, email.clicked) — so reputation problems are observable on day one, not after the first deliverability incident.
  • Predictable pricing. Each plan includes a monthly allowance per metered metric; overage is charged at the standard rate from a top-up balance. No per-channel minimums, no SMS short-code surcharges hidden in a separate invoice.

When to choose Blocx

Use case Surface
Transactional email for Supabase Auth / Auth.js / Clerk / custom auth POST /email with a verified EmailIdentity
OTP / 2FA over email, SMS, or Telegram POST /verificationsPOST /verifications/:id/check
Application notifications (receipts, alerts, order updates) POST /email or POST /messages
Marketing email campaigns with templates POST /email + marketing_email capability
10DLC SMS at scale POST /brandsPOST /campaignsPOST /messages
Inbound email parsing (support inboxes, reply-to workflows) Configure a mailbox; subscribe to email.received
MMS image / media delivery POST /messages with media URLs

If your stack is "transactional email only, forever," a single-channel provider is a fine choice. Pick Blocx when you ever expect to need SMS, 2FA, MMS, Telegram, or inbound parsing alongside email — integrating two vendors costs more in code, billing, and on-call surface than the per-message price difference.

Official SDK

Prefer a typed SDK over raw HTTP? Install @otterlabs/blocx — fully generated from this spec.

npm install @otterlabs/blocx
import { createBlocxClient, Messaging } from '@otterlabs/blocx'

const { client } = createBlocxClient({
  accessKeyId: process.env.BLOCX_ACCESS_KEY_ID!,
  secretAccessKey: process.env.BLOCX_SECRET_ACCESS_KEY!,
})

await Messaging.sendMessage({
  client,
  body: { to: '+15551234567', from: '+15559876543', body: 'Hello!', type: 'SMS' },
})

Help & guides

Step-by-step guides for everything you can do in Blocx — onboarding, brand and campaign registration, sending email, configuring webhooks, billing, and more — live in two places:

  • help.otterblocx.com — the human-friendly help center with full styling, search, and navigation.
  • api.otterblocx.com/articles — the same articles served as plain, chrome-free HTML directly off the API. This is the recommended index for AI agents and tooling that want to ingest the guides programmatically without parsing a marketing site.

Both surfaces serve identical content; pick whichever is easier for your reader.

Authentication

All requests require two headers:

  • x-access-key-id — Your API key ID
  • x-secret-access-key — Your API secret

Create API keys in the dashboard under Developer > API Keys.

Permissions

API keys carry scoped permissions. Each endpoint requires specific permissions (documented per endpoint). If a permission is missing, the request returns 403.

Available resources: messages, email, campaigns, brands, numbers, messaging_profiles, webhooks, twofa, twofa_templates, quotas, team.

Rate Limits & Quotas

Rate limits are enforced per-account and, where applicable, per-recipient. Default limits are applied to all accounts. Custom limits can be requested via the Quotas API or the dashboard.

Rate limit headers on applicable endpoints: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset.

Test Phone Sandbox

Every account can send outbound SMS from a shared test phone number without registering a 10DLC brand, getting a campaign approved, or buying a number. It's intended for first-call integration testing and webhook wire-up.

The shared test number is +13079999302 (same for every account).

To use it, set from to +13079999302 when calling POST /messaging/send. Test sends are subject to four rules:

  • [Otter] prefix. The body must start with [Otter]. Otherwise the request returns 400 with code: "test_prefix_required".
  • Heavy rate limit. Default caps are 5/min, 30/hour, 100/day per account. Exceeding any window returns 429 with code: "test_rate_limited". These caps cannot be raised — graduate to a real number when you outgrow them.
  • Outbound only. Replies to the test phone are dropped; message.received is never fired. Provision a real number if you need inbound.
  • No billing. Test sends do not draw from your balance and are not counted toward your monthly included quota.

Test sends flow through the same queue, carrier, webhook contract, and event types as real sends — message.sent, message.delivered, and message.failed all fire normally — so your integration code does not need to special-case them. The send response includes "test": true for client-side disambiguation.

2FA Verification Service

The 2FA verification endpoints (POST /verifications, POST /verifications/:id/check) are served by a separate service. In production, use the 2FA service base URL. Templates are managed through this API under /twofa/templates.

Channels: Verifications support EMAIL, SMS, and TELEGRAM. Set channel on the request and provide a matching to (email address or E.164 phone). Each channel supports its own template type and an optional tenant-owned sender:

  • EMAILfromIdentityId selects a verified EmailIdentity. Omit it to send from the system default sender.
  • SMSfromPhoneNumberId selects a tenant phone number that is ASSIGNED/ACTIVE and attached to a messaging profile. Omit it to send from the system default number.
  • TELEGRAM — Delivered via Telegram Gateway to the recipient's Telegram account on the given E.164 phone number. The message body is formatted by Telegram and cannot be customized — templateId and sender overrides are not supported. Returns 422 if the recipient is not reachable on Telegram (no Telegram account, or messaging the sender is restricted). Billed only after delivery is confirmed by the Gateway.

Template approval: New templates are auto-approved on create and on edit, so they're usable immediately. A template's channel must match the verification request's channel. SMS templates additionally require a tenant-owned fromPhoneNumberId — they cannot be sent from the system default number.

Webhooks

Subscribe to events that happen in your account by registering one or more webhook endpoints under /webhooks. We POST a signed JSON body to your URL whenever a subscribed event fires.

Event types

Event Fires when
message.sent An outbound SMS/MMS has been accepted by the carrier
message.delivered An outbound SMS/MMS was delivered to the handset
message.failed An outbound SMS/MMS could not be delivered
message.received An inbound SMS/MMS arrived on one of your numbers
email.delivered An outbound email was accepted by the recipient mail server
email.bounced An outbound email bounced
email.complained A recipient marked your message as spam
email.opened A recipient opened the email (if open tracking is enabled)
email.clicked A recipient clicked a tracked link
email.received An inbound email arrived on one of your mailboxes

Payload envelope

Every delivery has the same outer shape. Upstream carrier and mail-provider differences are normalized by Blocx before dispatch — your handler does not need to branch on which underlying provider produced the event. Any provider field in the payload is an opaque internal identifier and should not be parsed or depended on by integrations.

{
  "id": "evt_8f2a4d6e9c1b0a7d5e3f2c1b",
  "type": "message.delivered",
  "createdAt": "2026-05-06T12:34:56.789Z",
  "data": { /* event-specific, see below */ }
}

Event payloads (data field)

message.sent / message.delivered

Delivery status update for an outbound SMS/MMS.

{
  "messageId": "msg_1717689296000",
  "providerMessageId": "40a8b6e7-...",
  "status": "DELIVERED",
  "from": "+15559876543",
  "to": "+15551234567",
  "direction": "OUTBOUND",
  "type": "SMS",
  "occurredAt": "2026-05-06T12:34:55.120Z"
}

message.failed

Same shape as above, with two additional fields describing the failure.

{
  "messageId": "msg_1717689296000",
  "providerMessageId": "40a8b6e7-...",
  "status": "FAILED",
  "from": "+15559876543",
  "to": "+15551234567",
  "direction": "OUTBOUND",
  "type": "SMS",
  "occurredAt": "2026-05-06T12:34:55.120Z",
  "errorCode": "40010",
  "errorMessage": "Destination unreachable"
}

message.received

An inbound SMS/MMS arrived on one of your numbers.

{
  "messageId": "msg_in_01HK9...",
  "providerMessageId": "40a8b6e7-...",
  "from": "+15551234567",
  "to": "+15559876543",
  "direction": "INBOUND",
  "type": "SMS",
  "text": "Hello!",
  "media": [
    { "url": "https://...", "contentType": "image/jpeg" }
  ],
  "occurredAt": "2026-05-06T12:34:55.120Z"
}

email.delivered / email.bounced / email.complained

Status update for an outbound email. bounceType/bounceSubType are present on email.bounced; complainedAt is present on email.complained.

{
  "messageId": "eml_1717689296000",
  "status": "DELIVERED",
  "from": "hello@example.com",
  "to": ["user@recipient.com"],
  "subject": "Welcome aboard",
  "domain": "example.com",
  "occurredAt": "2026-05-06T12:34:55.120Z"
}

email.bounced adds:

{
  "bounceType": "Permanent",
  "bounceSubType": "General",
  "diagnosticCode": "smtp; 550 5.1.1 user unknown"
}

email.opened / email.clicked

Engagement events (only fire if open/click tracking is enabled on the identity).

{
  "messageId": "eml_1717689296000",
  "to": "user@recipient.com",
  "userAgent": "Mozilla/5.0 ...",
  "ipAddress": "203.0.113.42",
  "occurredAt": "2026-05-06T12:35:30.000Z",
  "link": "https://example.com/landing"
}

link is only present on email.clicked.

email.received

An inbound email arrived on one of your mailboxes. The message body is not included in the webhook payload — only metadata, headers, and attachment metadata. Fetch the raw MIME from S3 (or via the dashboard) when needed.

{
  "messageId": "abc123def456...",
  "receivedAt": "2026-05-06T12:34:56.789Z",
  "from": [
    { "name": "Jane Doe", "address": "jane@sender.com" }
  ],
  "to": [
    { "name": null, "address": "k7q9...@inbound.otterblocx.com" }
  ],
  "cc": [],
  "subject": "Re: your invoice",
  "text": "Thanks — see attached.",
  "html": "<p>Thanks — see attached.</p>",
  "headers": {
    "Message-ID": "<...>",
    "Date": "Tue, 06 May 2026 12:34:55 +0000"
  },
  "spam": false,
  "verdicts": {
    "spam": "PASS",
    "virus": "PASS",
    "spf": "PASS",
    "dkim": "PASS",
    "dmarc": "PASS"
  },
  "attachments": [
    {
      "filename": "invoice.pdf",
      "contentType": "application/pdf",
      "size": 48211,
      "contentId": null,
      "url": "https://s3...presigned"
    }
  ],
  "mailbox": {
    "id": 42,
    "address": "k7q9...@inbound.otterblocx.com",
    "label": "Support inbox"
  }
}

Attachment urls are presigned S3 URLs. They are time-limited (24h by default) — download or re-host within that window.

Verifying signatures

Each request carries these headers:

  • Blocx-Signaturet=<unix>,v1=<hex> where v1 is HMAC-SHA256(signingSecret, t + "." + rawBody).
  • Blocx-Timestamp — the same Unix timestamp as in the signature header (convenience copy).
  • Blocx-Event — the event type, e.g. message.delivered.
  • Blocx-Event-Id — stable event ID for idempotent processing.
  • Blocx-Attempt — current delivery attempt number (1-based).

Verification recipe (Node.js):

import { createHmac, timingSafeEqual } from 'crypto'

function verify(rawBody: string, header: string, secret: string): boolean {
  const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')))
  const t = Number(parts.t), v1 = parts.v1
  if (!t || !v1) return false
  if (Math.abs(Date.now() / 1000 - t) > 300) return false  // 5-minute tolerance
  const expected = createHmac('sha256', secret).update(`${t}.${rawBody}`).digest('hex')
  return expected.length === v1.length && timingSafeEqual(Buffer.from(expected), Buffer.from(v1))
}

You must verify against the raw, unparsed request body. JSON re-serialization changes byte-for-byte content and will break the signature.

Retries

Failed deliveries (non-2xx response, network error, or timeout) are retried up to 5 attempts total with the following backoff:

Attempt Delay before this attempt
1 — (immediate)
2 30 seconds
3 2 minutes
4 5 minutes
5 15 minutes

After the 5th failure the delivery is recorded as FAILED and not retried further. Each request times out after 10 seconds.

Endpoint requirements

  • HTTPS only (HTTP is allowed in development).
  • The hostname must resolve to a public IP address. Private/loopback/link-local ranges (RFC1918, 169.254.0.0/16, 127.0.0.0/8, fc00::/7, etc.) are rejected at registration time and re-checked at delivery time to defeat DNS rebinding.
  • Respond with any 2xx status code within 10 seconds. The response body is captured (truncated to 2KB) for diagnostics.

Idempotency

The same event may be re-delivered after a transient failure. Use Blocx-Event-Id to deduplicate.

Email Deliverability & Sender Authentication

Email reputation is enforced at the EmailIdentity level (one identity per sending domain or address). Every identity must complete sender authentication before it can send:

  • SPF — published as part of the domain record set returned by GET /email/identities/{id}. Required for all sending domains.
  • DKIM — Blocx generates a 2048-bit DKIM keypair per identity; the public key is exposed in the dnsRecords array on the identity. Required for all sending domains; rotated on request.
  • DMARC — Blocx surfaces a recommended DMARC record on each identity. Enforcement policy is left to the domain owner.
  • MX (inbound) — required only when the identity is configured to receive mail. Inbound identities are validated against the same SPF/DKIM/DMARC results before email.received is dispatched.

The full required record set for any identity is available at GET /email/identities/{id} under dnsRecords. Each record reports current verification state (PENDING, VERIFIED, FAILED) so that integrations can show setup status to end users.

IP reputation

Default sending is on a shared, warmed pool segmented by traffic class (transactional vs. marketing). Enterprise accounts can request a dedicated IP for marketing or high-volume transactional traffic — Blocx handles warming and reputation monitoring automatically.

Bounce, complaint, and engagement tracking

Per-identity event history is available through the webhook stream (email.delivered, email.bounced, email.complained, email.opened, email.clicked) and as paginated history under the identity resource. Bounce classification (Permanent / Transient / subtype) is normalized regardless of underlying upstream so deliverability dashboards do not need provider-specific parsing.

Suppression list

Hard bounces and recipient complaints are automatically added to a per-tenant suppression list. Attempts to send to a suppressed address return 409 SUPPRESSED without consuming quota or producing a webhook event. Suppression entries can be inspected and (where compliant) removed via the dashboard.

Async Operations

Brand registration, campaign creation, and domain setup are processed asynchronously. The API returns immediately with PENDING_REGISTRATION or PENDING status. Poll the resource to check completion.

Plans & Capabilities

Every account is on one subscription plan. There are only two: Pay as you go (the default; everyone starts here) and Enterprise (admin-assigned for negotiated commercial terms). Plans gate three things:

  1. Capabilities — boolean feature flags that decide which endpoints the tenant can call.
  2. Included quotas — a monthly allowance of metered usage (currently 3,000 free emails on PAYG). Once exhausted, additional usage is charged from the account balance at the standard PriceItem rate.
  3. Spend cap and coverage — PAYG caps spend at $2,500/month and rejects non-US destinations. Enterprise removes both limits and uses contract-set pricing.

The plans

Plan Monthly base Included emails / mo Coverage Spend cap
Pay as you go $0 (starts with $10 free credit) 3,000 US (NANP) $2,500 / month
Enterprise Custom (starts at $1,000 / mo minimum) Custom +190 countries beyond the US None

Capability matrix

Both plans grant every standard sending capability by default — the practical differences are coverage, the spend cap, dedicated IPs, and contract terms.

Capability Pay as you go Enterprise
sms — SMS / MMS sending, brands, campaigns, phone numbers, messaging profiles, compliance
twofa — 2FA verifications & templates (email, SMS, Telegram)
marketing_email — marketing email & campaigns
multiple_email_domains — more than one verified sending domain
dedicated_email_ip — dedicated IP for email

Tenants calling a gated endpoint they lack the capability for receive 402 CAPABILITY_REQUIRED. PAYG accounts attempting a non-US destination receive 403 non_us_destination; PAYG accounts past the spend cap receive 402 monthly_cap_reached.

Per-tenant overrides

Admins can grant or revoke individual capabilities on a single subscription without changing the plan. Effective value = subscription override (if set) → plan default → false. Use this for pilots, trials, or revoking a feature for a specific account.

Quotas vs. balance overage

Subscription.includedQuotas is the monthly allowance per metric. Send-time consumption decrements the remaining counter; once it hits zero, further usage on that metric is charged from the tenant's balance. Counters reset every calendar month.

PAYG's 3,000 monthly email allowance is the only included quota; everything else (SMS, MMS, 2FA, Telegram, number rentals, mailbox rentals) is billed per use from the balance at the standard PriceItem rate.

Subscription standing

A subscription with status PAST_DUE, INCOMPLETE, or CANCELED retains its plan capabilities at the data-model level but send-path checks block new sends until the subscription returns to ACTIVE (or TRIALING). New tenants are ACTIVE on PAYG with no Stripe subscription attached (PAYG has no recurring base charge).

No authentication selected
Client Libraries

Brands

10DLC brand registration

List brands

List all registered 10DLC brands.

Plan: Requires the sms capability. Granted by default on Pay as you go and Enterprise.

Responses
  • application/json
Request Example for get/brands
curl /brands \
  --header 'x-access-key-id: YOUR_SECRET_TOKEN' \
  --header 'x-secret-access-key: YOUR_SECRET_TOKEN'
{
  "brands": [
    {
      "id": 1,
      "tcrBrandId": "BLNFT6G",
      "entityType": "PRIVATE_PROFIT",
      "displayName": "Acme Corp",
      "companyName": "string",
      "country": "US",
      "email": "hello@example.com",
      "phone": "+15551234567",
      "vertical": "PROFESSIONAL",
      "brandRelationship": "BASIC_ACCOUNT",
      "webhookUrl": "https://example.com",
      "failoverUrl": "https://example.com",
      "tags": [
        "string"
      ],
      "identityStatus": "PENDING",
      "status": "PENDING_REGISTRATION",
      "claimedAt": "2026-06-03T15:01:58.235Z",
      "createdAt": "2026-06-03T15:01:58.235Z"
    }
  ]
}

Register brand

Register a 10DLC brand. Created as PENDING_REGISTRATION, processed async. $4.50 fee charged on completion.

Plan: Requires the sms capability. Granted by default on Pay as you go and Enterprise.

Body
required
application/json
  • brandRelationship
    Type: stringenum
    required
    values
    • BASIC_ACCOUNT
    • SMALL_ACCOUNT
    • MEDIUM_ACCOUNT
    • LARGE_ACCOUNT
    • KEY_ACCOUNT
  • city
    Type: string
    min length:  
    1
    max length:  
    100
    required
  • companyName
    Type: string
    min length:  
    1
    max length:  
    255
    required
  • country
    Type: string
    min length:  
    2
    max length:  
    2
    required
  • displayName
    Type: string
    min length:  
    1
    max length:  
    255
    required
  • ein
    Type: string
    min length:  
    1
    max length:  
    21
    required
  • email
    Type: string
    max length:  
    100
    Pattern: ^(?!\.)(?!.*\.\.)([A-Za-z0-9_'+\-\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$Format: email
    required
  • entityType
    Type: stringenum
    required
    values
    • PRIVATE_PROFIT
    • PUBLIC_PROFIT
    • NON_PROFIT
    • GOVERNMENT
  • phone
    Type: string
    min length:  
    1
    max length:  
    20
    required
  • postalCode
    Type: string
    min length:  
    1
    max length:  
    10
    required
  • state
    Type: string
    min length:  
    1
    max length:  
    20
    required
  • street
    Type: string
    min length:  
    1
    max length:  
    255
    required
Responses
  • application/json
Request Example for post/brands
curl /brands \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'x-access-key-id: YOUR_SECRET_TOKEN' \
  --header 'x-secret-access-key: YOUR_SECRET_TOKEN' \
  --data '{
  "entityType": "PRIVATE_PROFIT",
  "displayName": "",
  "companyName": "",
  "ein": "",
  "einIssuingCountry": "US",
  "phone": "",
  "street": "",
  "city": "",
  "state": "",
  "postalCode": "",
  "country": "",
  "email": "",
  "website": "",
  "vertical": "PROFESSIONAL",
  "brandRelationship": "BASIC_ACCOUNT",
  "stockSymbol": "",
  "stockExchange": "NONE",
  "altBusinessId": "",
  "altBusinessIdType": "NONE",
  "firstName": "",
  "lastName": "",
  "mobilePhone": "",
  "businessContactEmail": "",
  "referenceId": "",
  "webhookUrl": "",
  "failoverUrl": "",
  "tags": []
}'
{
  "id": 1,
  "tcrBrandId": "BLNFT6G",
  "entityType": "PRIVATE_PROFIT",
  "displayName": "Acme Corp",
  "companyName": "string",
  "country": "US",
  "email": "hello@example.com",
  "phone": "+15551234567",
  "vertical": "PROFESSIONAL",
  "brandRelationship": "BASIC_ACCOUNT",
  "webhookUrl": "https://example.com",
  "failoverUrl": "https://example.com",
  "tags": [
    "string"
  ],
  "identityStatus": "PENDING",
  "status": "PENDING_REGISTRATION",
  "claimedAt": "2026-06-03T15:01:58.235Z",
  "createdAt": "2026-06-03T15:01:58.235Z"
}

Get brand

Get brand details including campaigns.

Plan: Requires the sms capability. Granted by default on Pay as you go and Enterprise.

Path Parameters
  • id
    Type: number
    required

    Resource ID

Responses
  • application/json
  • application/json
Request Example for get/brands/{id}
curl /brands/1 \
  --header 'x-access-key-id: YOUR_SECRET_TOKEN' \
  --header 'x-secret-access-key: YOUR_SECRET_TOKEN'
{
  "id": 1,
  "tcrBrandId": "BLNFT6G",
  "entityType": "PRIVATE_PROFIT",
  "displayName": "Acme Corp",
  "companyName": "string",
  "country": "US",
  "email": "hello@example.com",
  "phone": "+15551234567",
  "vertical": "PROFESSIONAL",
  "brandRelationship": "BASIC_ACCOUNT",
  "webhookUrl": "https://example.com",
  "failoverUrl": "https://example.com",
  "tags": [
    "string"
  ],
  "identityStatus": "PENDING",
  "status": "PENDING_REGISTRATION",
  "claimedAt": "2026-06-03T15:01:58.235Z",
  "createdAt": "2026-06-03T15:01:58.235Z",
  "ein": "string",
  "updatedAt": "2026-06-03T15:01:58.235Z",
  "campaigns": [
    {
      "id": 1,
      "tcrCampaignId": "string",
      "usecase": "2FA",
      "status": "PENDING_REGISTRATION",
      "provisioningStage": "REGISTERING",
      "createdAt": "2026-06-03T15:01:58.235Z"
    }
  ]
}

Get brand feedback

Get TCR identity feedback (reasons for UNVERIFIED).

Plan: Requires the sms capability. Granted by default on Pay as you go and Enterprise.

Path Parameters
  • id
    Type: number
    required

    Resource ID

Responses
  • application/json
  • application/json
Request Example for get/brands/{id}/feedback
curl /brands/1/feedback \
  --header 'x-access-key-id: YOUR_SECRET_TOKEN' \
  --header 'x-secret-access-key: YOUR_SECRET_TOKEN'
{
  "brandId": "string",
  "category": [
    "string"
  ]
}

Compliance (Collapsed)

Compliance events and carrier feedback

Balance (Collapsed)

Account balance and usage

Messaging (Collapsed)

SMS and MMS sending

Messaging Operations

2FA Verifications (Collapsed)

Verification code send and check

2FA Templates (Collapsed)

Quotas (Collapsed)

Phone Orders (Collapsed)

Phone number provisioning orders

Webhooks (Collapsed)

Outbound event delivery configuration

Models