Skip to main content

Quickstart

This quickstart is the shortest path from credentials to a successful Red Cloud send with delivery visibility.

Section 1 — What You Will Do

In this quickstart, you will:

  • get an access token
  • confirm the API client is active
  • retrieve an assigned number
  • send a message
  • confirm delivery lifecycle events by webhook

Section 2 — Before You Start

You need three things before the first successful send:

  1. valid API client credentials
  2. at least one assigned Red Cloud number
  3. a webhook endpoint that can receive signed lifecycle events

If you are missing any of those, stop here and resolve them before troubleshooting request syntax.

Section 3 — Prerequisites

Before you start, make sure you have:

  • API client credentials from the Red Cloud portal:
    • client_id = rc_test_client_123
    • client_secret = rc_secret_abc123
  • one assigned number available to your API client:
    • numberId = num_abc123
  • a webhook endpoint to receive lifecycle events
    • a temporary endpoint such as webhook.site is enough for initial testing

Integration variables used in this guide

Set these values locally before you run the examples:

export BASE_URL="https://your-api-host.example.com"
export RC_CLIENT_ID="rc_test_client_123"
export RC_CLIENT_SECRET="rc_secret_abc123"
export RC_NUMBER_ID="num_abc123"

BASE_URL must point at the Red Cloud API host provided for your environment.

Section 4 — Step 1: Get Access Token

Request

curl using HTTP Basic auth

curl -X POST "$BASE_URL/api/auth/token" \
-u "$RC_CLIENT_ID:$RC_CLIENT_SECRET" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials"

curl using body credentials

curl -X POST "$BASE_URL/api/auth/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=$RC_CLIENT_ID" \
-d "client_secret=$RC_CLIENT_SECRET"

Response

{
"access_token": "rc_token_example",
"token_type": "bearer",
"expires_in": 3600
}

Explanation

This token is what authorizes every Authorization: Bearer ... call to the CORE API. Tokens expire after 3600 seconds, so your integration must be ready to refresh them.

Immediate success check

If you do not receive an access_token, do not continue to later steps. Authentication must succeed first.

Section 5 — Step 2: Verify Your Account

Request

curl "$BASE_URL/api/core/whoami" \
-H "Authorization: Bearer rc_token_example"

Response

{
"apiClientId": "rc_test_client_123",
"apiClientName": "Red Cloud Test Client",
"apiClientStatus": "ACTIVE",
"capabilities": [
"numbers:read",
"numbers:search",
"numbers:update"
],
"assignedNumbers": {
"total": 1,
"smsEnabledCount": 1,
"mmsEnabledCount": 1
},
"inboundWebhookConfigured": true,
"deliveryWebhookConfigured": true
}

Explanation

This confirms that authentication is working and that your API client is active. It also tells you whether numbers and webhook configuration are already present.

Immediate success check

Before moving on:

  • apiClientStatus should be ACTIVE
  • assignedNumbers.total should be greater than 0
  • webhook flags tell you whether lifecycle delivery is already configured globally

Section 6 — Step 3: Get Your Number

Request

curl "$BASE_URL/api/core/numbers" \
-H "Authorization: Bearer rc_token_example"

Response

{
"numbers": [
{
"numberId": "num_abc123",
"e164": "+15551234567",
"status": "ACTIVE",
"campaignRegId": "A1B2C3",
"smsEnabled": true,
"mmsEnabled": true,
"webhookInboundOverride": "https://example.com/webhooks/inbound",
"webhookDeliveryOverride": "https://example.com/webhooks/delivery"
}
]
}

Explanation

Choose the numberId you want to send from. This is the internal Red Cloud identifier for the assigned number and is the value that belongs in the send request.

sendFrom is NOT a phone number

Use numberId, not the E.164 phone number. In these examples, sendFrom must be num_abc123, not +15551234567.

Immediate success check

Before sending:

  • confirm the number status is ACTIVE
  • confirm smsEnabled is true for SMS sends
  • keep the numberId value exactly as returned

Section 7 — Step 4: Send Your First Message

Request

curl -X POST "$BASE_URL/api/core/messages/send" \
-H "Authorization: Bearer rc_token_example" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: idem_order_789" \
-d '{
"sendFrom": "'"$RC_NUMBER_ID"'",
"to": ["+15551234567"],
"messageType": "SMS",
"text": "Hello from Red Cloud",
"externalReference": "order_789"
}'

Response

{
"results": [
{
"to": "+15551234567",
"messageId": "msg_abc123",
"status": "QUEUED"
}
],
"errors": []
}

Explanation

  • Idempotency-Key is required
  • results contains accepted recipients
  • errors contains recipients that were rejected
  • a send can partially succeed, so always inspect both arrays

Immediate success check

Your first successful request should produce:

  • at least one item in results
  • a messageId
  • initial status QUEUED

A QUEUED response means Red Cloud accepted the request. It does not mean the handset has received the message yet.

Section 8 — Step 5: Receive Delivery Events

Explanation

Delivery events arrive asynchronously by webhook. A successful send request only means the message was accepted into the Red Cloud system. Delivery and failure lifecycle updates come later through webhook events such as message.queued, message.sent, message.delivery, and message.failed.

What to watch for first

For a healthy first integration, you should expect to observe a sequence like:

  1. message.queued
  2. message.sent
  3. message.delivery or message.failed

Your integration should treat webhook delivery as the lifecycle source of truth after the send request is accepted.

Section 9 — Minimal Webhook Example

Request

Configure your delivery webhook endpoint to receive signed POST requests.

Response

Your endpoint receives JSON payloads such as:

{
"eventType": "message.delivery",
"direction": "outbound",
"occurredAt": 1775002218105,
"apiClientId": "rc_test_client_123",
"messageId": "msg_abc123",
"sequence": 3,
"data": {
"messageId": "msg_abc123",
"externalReference": "order_789",
"sendFrom": "+15551234567",
"to": "+15551234567",
"status": "delivered",
"error": null
}
}

Explanation

Red Cloud signs webhook payloads with:

  • X-RedCloud-Timestamp
  • X-RedCloud-Signature

Verify signatures with:

HMAC_SHA256(secret, "${timestamp}.${rawBody}")

Node.js example

import crypto from "node:crypto";
import express from "express";

const app = express();
const webhookSecret = process.env.RC_WEBHOOK_SECRET ?? "rc_secret_abc123";

app.use(
express.json({
verify(req, _res, buffer) {
req.rawBody = buffer.toString("utf8");
},
}),
);

app.post("/webhooks/red-cloud", (req, res) => {
const timestamp = req.header("X-RedCloud-Timestamp");
const signature = req.header("X-RedCloud-Signature");
const rawBody = req.rawBody ?? "";

if (!timestamp || !signature) {
return res.status(400).json({ error: "Missing signing headers" });
}

const expectedSignature = crypto
.createHmac("sha256", webhookSecret)
.update(`${timestamp}.${rawBody}`)
.digest("hex");

if (signature !== expectedSignature) {
return res.status(401).json({ error: "Invalid signature" });
}

console.log("Verified webhook payload:", req.body);

return res.status(200).json({ ok: true });
});

app.listen(3000, () => {
console.log("Webhook listener ready on http://localhost:3000/webhooks/red-cloud");
});

Section 10 — Quick Troubleshooting

If the flow fails, check in this order:

  1. token request
    • bad credentials or inactive client usually fail here
  2. /whoami
    • confirms the token is valid and the client is active
  3. /api/core/numbers
    • confirms a usable numberId is available
  4. send request
    • most early request mistakes are missing Idempotency-Key, invalid sendFrom, or invalid recipient format
  5. webhook receipt
    • if the send is accepted but no lifecycle events arrive, the problem is usually webhook reachability or signature handling

Section 11 — What Happens Next

Next, use these pages: