Validate RCS payloads programmatically. Integrate into CI/CD pipelines, ESP platforms, or internal tooling — without pasting JSON into a browser.
No API key needed to try it. Anonymous requests are rate-limited to 10/minute.
curl -X POST https://rcscheck.dev/api/v1/validate \
-H "Content-Type: application/json" \
-d '{
"payload": {
"contentMessage": {
"text": "Hello from RCS!",
"fallback": { "text": "Hello!" }
}
},
"aggregator": "google"
}'{
"ok": true,
"valid": true,
"messageType": "text",
"aggregator": "google",
"summary": {
"errors": 0,
"warnings": 0,
"info": 1,
"passed": 30,
"total": 31
},
"errors": [],
"warnings": [],
"info": [
{
"ruleId": "SUGG-010",
"severity": "info",
"description": "...",
"path": "contentMessage.suggestions",
"fix": "..."
}
],
"meta": {
"validatedAt": "2026-05-31T10:00:00.000Z",
"durationMs": 2,
"apiVersion": "v1",
"docs": "https://rcscheck.dev/api-docs"
}
}Get a free API key to unlock higher rate limits. Pass it as a Bearer token or X-Api-Key header.
# Get a free API key
curl -X POST https://rcscheck.dev/api/v1/keys \
-H "Content-Type: application/json" \
-d '{ "email": "you@company.com", "name": "My CI pipeline" }'
# Use the key
curl -X POST https://rcscheck.dev/api/v1/validate \
-H "Authorization: Bearer rcs_live_..." \
-H "Content-Type: application/json" \
-d '{ "payload": { ... }, "aggregator": "twilio" }'⚠ API keys are shown once at creation and never retrievable again. Store them in environment variables or a secrets manager.
Rate limit headers are returned on every response: X-RateLimit-Remaining, X-RateLimit-Reset, X-RateLimit-Tier. On 429, check Retry-After.
https://rcscheck.dev/api/v1/validateValidates an RCS payload against the GSMA spec and the selected aggregator's rules. Returns a full ValidationReport.
https://rcscheck.dev/api/v1/keysRequest a free API key. One key per email address. The key is returned once in the response body.
const response = await fetch("https://rcscheck.dev/api/v1/validate", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer " + process.env.RCSCHECK_API_KEY,
},
body: JSON.stringify({
payload: myRcsPayload,
aggregator: "google",
strict: true, // fail CI on warnings too
}),
});
const result = await response.json();
if (!result.valid) {
console.error("RCS payload is invalid:");
result.errors.forEach((e) => {
console.error(` [${e.ruleId}] ${e.description}`);
console.error(` Fix: ${e.fix}`);
});
process.exit(1);
}import os, requests, sys
response = requests.post(
"https://rcscheck.dev/api/v1/validate",
headers={
"Content-Type": "application/json",
"Authorization": f"Bearer {os.environ['RCSCHECK_API_KEY']}",
},
json={
"payload": my_rcs_payload,
"aggregator": "twilio",
"strict": True,
},
)
result = response.json()
if not result["valid"]:
for error in result["errors"]:
print(f"[{error['ruleId']}] {error['description']}")
print(f" Fix: {error['fix']}")
sys.exit(1)- name: Validate RCS payload
run: |
RESULT=$(curl -s -X POST https://rcscheck.dev/api/v1/validate \
-H "Authorization: Bearer ${{ secrets.RCSCHECK_API_KEY }}" \
-H "Content-Type: application/json" \
-d @rcs-payload.json)
VALID=$(echo $RESULT | jq -r '.valid')
if [ "$VALID" != "true" ]; then
echo "RCS payload validation failed:"
echo $RESULT | jq '.errors[]'
exit 1
fiRun the following migration in your Supabase SQL editor to enable API key storage.
create table api_keys (
id uuid primary key default gen_random_uuid(),
key_hash text unique not null, -- SHA-256 of the full key
key_prefix text not null, -- first 16 chars, safe to display
name text not null,
email text not null,
tier text not null default 'free',
is_active boolean not null default true,
requests_this_month integer not null default 0,
created_at timestamptz not null default now(),
last_used_at timestamptz,
revoked_at timestamptz
);
create index on api_keys (key_hash);
create index on api_keys (email);
alter table api_keys enable row level security;
create policy "Service role only" on api_keys
for all using (auth.role() = 'service_role');