v1 API reference

The canonical base URL is https://msghop.com. JSON endpoints are versioned beneath /v1; credentials are tenant- and app-scoped.

Common request headers

  • Authorization: Bearer <server-credential> — required for protected endpoints.
  • Content-Type: application/json — required for message submission.
  • Idempotency-Key — required for message submission.
  • X-Request-Id — optional caller correlation ID, 2–128 safe characters. A generated ID is returned when omitted.

Protected responses use Cache-Control: no-store, X-Content-Type-Options: nosniff, and X-Request-Id.

Download the OpenAPI 3.1 contract or follow the agent integration guide for authentication and registration over HTTP.

Endpoints

POST
/v1/sessions · /v1/sessions/refresh

Create or refresh a short-lived MessageHop user session.

POST
/v1/control/{operation}

Invoke an authorized Customer operation using a user access token and direct JSON.

GET
/v1/auth/check

Verify a server credential and return its effective tenant, app, environment, actions, and channels.

POST
/v1/messages

Durably accept one message for asynchronous provider dispatch. Requires messages.send and an allowed channel.

GET
/v1/messages/{messageId}

Read the caller-scoped message projection. Requires messages.read.

GET
/v1/balances?currency=INR

Read the Organization balance projection for one ISO-style uppercase currency. Requires billing.read.

GET
/v1/usage?currency=INR&from=...&to=...

Read bounded app-scoped financial activity. Requires usage.read.

GET
/v1/health · /v1/readiness · /v1/release

Public operational release endpoints. They do not authorize customer messaging.

POST /v1/messages

Request body

{
  "projectId": "project_checkout",
  "appId": "app_server",
  "channel": "sms",
  "to": "+919876543210",
  "templateId": "order_update",
  "variables": {"order_id": "8472"},
  "clientReference": "order-8472"
}
  • projectId, appId, and templateId: 2–128 letters, digits, underscores, or hyphens.
  • channel: sms, whatsapp, or email, subject to credential and account activation.
  • to: channel-valid recipient; SMS and WhatsApp use a normalized international number and email uses a valid address.
  • variables: at most 50 keys; keys start with a letter and values are strings up to 500 characters.
  • clientReference: optional customer reference up to 128 characters.

202 response

{
  "messageId": "msg_...",
  "state": "ACCEPTED",
  "acceptedAt": "2026-07-26T12:00:00.000Z",
  "estimatedCharge": {
    "amountMinor": 27,
    "currency": "INR",
    "status": "provisional",
    "priceVersionId": "sms_inr_..."
  },
  "requestId": "req_..."
}

GET /v1/messages/{messageId}

A message ID begins with msg_. The response contains messageId, state, channel, acceptedAt, optional updatedAt, and a billing object with status, amountMinor, and currency. Unknown and cross-tenant IDs return a non-enumerating not-found result.

GET /v1/balances

Required query: currency, exactly three uppercase letters. The response includes Organization ID, currency, availableMinor, reservedMinor, postedMinor, asOf, projection version, reconciliation status, and request ID. These are projections; immutable ledger events remain authoritative.

GET /v1/usage

Required query fields are currency, from, and to. Times are epoch milliseconds, the range must stay within one UTC calendar month, cannot exceed 31 days, and cannot extend materially into the future. limit defaults to 50 and accepts 1–100. Pass the opaque nextCursor to retrieve the next page.

Each entry includes entry ID, type (reservation, settlement, or release), message ID, amount in minor units, status, occurrence time, and optional related-entry ID.

Money and time

All monetary amounts are integers in the currency's minor unit; never interpret them as floating-point major units. Times in JSON responses are ISO 8601 UTC strings, while usage query bounds are epoch milliseconds.

Read errors and retries