API v1

Subscription

Read your workspace's plan, billing status, renewal date, credits and limits from your own systems. One GET, no parameters. This is the same endpoint Chatmount's own support agent reads when a customer asks what plan they're on.

Endpoint

text
GET https://services.chatmount.co/v1/subscription

Authenticate with an API key in the Authorization: Bearer header, exactly as for chat. The workspace is the one the key belongs to: a workspace key answers for its workspace, a per-agent key for that agent’s workspace. Rate limits are per key and shared with chat; see Rate limits.

Response body

json
{
  "workspace": { "id": "ws_…", "name": "Acme Clinic", "slug": "acme-clinic" },
  "plan": { "id": "plus", "name": "Pro", "interval": "monthly" },
  "status": "active",
  "is_subscribed": true,
  "billing": { "state": "active", "grace_ends_at": null, "last_payment_failed_at": null },
  "trial": { "active": false, "ends_at": null },
  "period": { "start": "2026-09-01T00:00:00.000Z", "end": "2026-10-01T00:00:00.000Z" },
  "renews_at": "2026-10-01T00:00:00.000Z",
  "ends_at": "2026-10-01T00:00:00.000Z",
  "cancel_at_period_end": false,
  "scheduled_change": null,
  "amount": { "value": 699900, "currency": "INR" },
  "credits": { "used": 412, "limit": 4000, "remaining": 3588, "period_start": "2026-09-01" },
  "limits": { "agents": 1, "channels": 5, "api_keys": 5, "daily_messages": 10000, "leads_per_month": 500 },
  "checked_at": "2026-09-23T10:12:04.311Z"
}
  • plan — id is the internal tier (go, plus, pro, agency, enterprise, free); name is what the dashboard shows. interval is monthly, yearly, or null on free.
  • status — the one word to branch on. See Status values.
  • period — the current billing cycle. renews_at is set only while the subscription will renew; ends_at is the paid-through date regardless.
  • cancel_at_period_end — the customer cancelled and keeps access until ends_at.
  • scheduled_change — a queued downgrade: { plan, plan_name, interval, effective_at }, else null.
  • amount — what the processor charges per interval, in the smallest unit (paise or cents). null on free and trial.
  • credits — used and remaining for this cycle. limit is null when unlimited.
  • limits — the plan’s caps: active agents, channels, API keys, messages per day per agent, leads per month.
  • checked_at — when this snapshot was computed. Billing events reach us through the processor’s webhook within seconds, so the snapshot is current without a live processor call.

Status values

StatusMeaning
trialIn the 7-day trial. plan.id is the plan that bills when it ends; trial.ends_at says when.
activePaid and renewing. renews_at is set.
cancellingCancelled; access continues until ends_at, then the workspace drops to free.
past_dueA charge failed. Service continues until billing.grace_ends_at.
suspendedThe grace period ran out. Chat and API are paused until a card is updated.
freeNo paid plan.

Examples

cURL
curl https://services.chatmount.co/v1/subscription \
  -H "Authorization: Bearer cm_live_your_api_key"
Node
const res = await fetch("https://services.chatmount.co/v1/subscription", {
  headers: { Authorization: `Bearer ${process.env.CHATMOUNT_API_KEY}` },
});
const sub = await res.json();

if (sub.status === "past_due") notifyBillingOwner(sub.billing.grace_ends_at);
if (sub.credits.remaining !== null && sub.credits.remaining < 100) topUp();

Let your agent answer it

This endpoint is a working example of Connected APIs: Chatmount’s own support agent is linked to it, so a signed-in customer can ask the widget “what plan am I on?” and the call runs in their browser with their own session. On WhatsApp and Instagram the agent verifies the customer’s email with a 6-digit code first, then reads the same endpoint server-side. The exact wiring, which you can copy for your own API:

text
On the website            Connection  https://www.chatmount.co/api  ·  auth: none (cookies)
                          Endpoint    my_plan → GET /v1/subscription  ·  runs in the browser
                          Channels    Website widget · Help page

On WhatsApp & Instagram   Connection  https://services.chatmount.co  ·  auth: Bearer <any Chatmount API key>
                          Endpoint    my_plan → GET /v1/subscription  ·  runs on the server
                          Identity    Requires verified email   ← the endpoint then vouches for the visitor
                          Channels    WhatsApp · Instagram

See it running, and the four things that make it work, on Connected APIs.

Verified identity assertion

When an endpoint has Requires verified email on and runs on the server, Chatmount attaches two headers to the call after the visitor has passed the 6-digit email code:

  • X-Chatmount-Identity — base64url JSON: { v, connection, chatbot, session, email, iat, exp }. Valid for 5 minutes.
  • X-Chatmount-Identity-Signature — hex HMAC-SHA256 of that token with the connection’s identity signing secret, shown in the connection’s settings.

Verify the signature and you know the email was confirmed by a code in this very conversation, whoever is holding the API key. {{_verifiedEmail}} is still available for templating if you would rather pass it in the URL or body.

Verify on your side (Node)
import { createHmac, timingSafeEqual } from "node:crypto";

// From the connection's settings → "Identity signing secret".
const SECRET = process.env.CHATMOUNT_IDENTITY_SECRET;

export function verifiedEmail(req) {
  const token = req.headers["x-chatmount-identity"];
  const sig = req.headers["x-chatmount-identity-signature"];
  if (!token || !sig) return null;
  const expected = createHmac("sha256", SECRET).update(token).digest("hex");
  if (expected.length !== sig.length || !timingSafeEqual(Buffer.from(expected), Buffer.from(sig))) return null;
  const claims = JSON.parse(Buffer.from(token, "base64url").toString("utf8"));
  if (claims.exp * 1000 < Date.now()) return null;
  return claims.email; // verified by Chatmount's email OTP in this conversation
}

This endpoint accepts the same headers: with a valid assertion it returns the snapshot for the asserted account, plus account and identity fields, which is how Chatmount’s own agent answers a customer on WhatsApp. Without one, it answers for the key’s own workspace, and any ?email= is refused with 403 identity_assertion_required.

Errors

  • 401 — missing, revoked or expired key.
  • 404 workspace_not_found — the key is not linked to a workspace (legacy keys with no agent).
  • 429 rate_limited — over the per-key limit; read X-RateLimit-Reset.

Related