CLASHUP API Documentation

CLASHUP provides a REST API for sending and verifying one-time passwords (OTPs) via email. All API requests use JSON and return standardized JSON responses.

Base URL: https://api.clashup.site/api/v1

Authentication

All API requests require an API key sent in the X-API-Key header.

curl -X POST https://api.clashup.site/api/v1/otp/send \
  -H "X-API-Key: cu_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"channel": "email", "recipient": "user@example.com"}'

How to get an API key:

  1. Register and verify your account at clashup.site/register
  2. Create an application in the dashboard
  3. Generate an API key for your application
  4. Copy and securely store the key (shown only once)

Local Development

Browser apps served from http://localhost, http://127.0.0.1, or http://[::1] can call the production API directly. Create an application and API key in the dashboard, then send the key in every request.

fetch('https://api.clashup.site/api/v1/otp/send', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-API-Key': 'cu_live_your_api_key'
  },
  body: JSON.stringify({
    channel: 'email',
    recipient: 'user@example.com'
  })
});

Keep your key private

Use this browser setup for local development and trusted internal tools. Never embed a live API key in a public website, mobile app, or code repository; send those requests through your own backend instead.

Rate Limiting

API requests are rate-limited per API key. Rate limit headers are included in every response.

HeaderDescription
X-RateLimit-LimitMax requests per window
X-RateLimit-RemainingRequests remaining in current window
X-RateLimit-ResetWindow reset time (unix timestamp)

OTP endpoints: 30 requests per minute per IP. If exceeded, you'll receive a 429 Too Many Requests response.

Error Handling

All errors return a consistent JSON format:

{
  "success": false,
  "message": "Validation failed",
  "statusCode": 400,
  "errors": [
    { "field": "email", "message": "Please provide a valid email" }
  ]
}
CodeDescription
400Bad Request - Invalid parameters
401Unauthorized - Missing or invalid API key
403Forbidden - Insufficient permissions
404Not Found - Resource doesn't exist
429Too Many Requests - Rate limit exceeded
500Server Error - Something went wrong

Send OTP

POST /api/v1/otp/send

Generates and sends a one-time password to the specified recipient.

Request Body

FieldTypeRequiredDescription
channelstringYesemail or sms
recipientstringYesEmail address or phone number
metadataobjectNoCustom key-value metadata

Example Request

curl -X POST https://api.clashup.site/api/v1/otp/send \
  -H "X-API-Key: cu_live_abc123..." \
  -H "Content-Type: application/json" \
  -d '{
    "channel": "email",
    "recipient": "user@example.com",
    "metadata": { "purpose": "login" }
  }'

Success Response

{
  "success": true,
  "message": "OTP sent successfully",
  "statusCode": 200,
  "data": {
    "requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "channel": "email",
    "recipient": "user@example.com",
    "status": "pending",
    "expiresAt": "2025-01-01T00:10:00.000Z"
  }
}

Verify OTP

POST /api/v1/otp/verify

Verifies an OTP code against a pending request.

Request Body

FieldTypeRequiredDescription
requestIdstringYesThe requestId from the send response
otpstringYesThe OTP code entered by the user

Example Request

curl -X POST https://api.clashup.site/api/v1/otp/verify \
  -H "X-API-Key: cu_live_abc123..." \
  -H "Content-Type: application/json" \
  -d '{
    "requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "otp": "123456"
  }'

Success Response

{
  "success": true,
  "message": "OTP verified successfully",
  "statusCode": 200,
  "data": {
    "requestId": "a1b2c3d4-...",
    "status": "verified",
    "verifiedAt": "2025-01-01T00:05:30.000Z"
  }
}

Important Notes

  • OTPs expire after 10 minutes by default
  • Maximum 3 verification attempts per OTP request
  • After max attempts, the OTP is marked as failed
  • OTP values are hashed - they cannot be retrieved, only verified

Webhook Events

Configure webhooks in the dashboard to receive real-time notifications for these events:

EventDescription
otp.sentOTP was sent successfully
otp.verifiedOTP was verified successfully
otp.failedOTP verification failed (max attempts)
otp.expiredOTP expired without verification

Webhook Payload

{
  "event": "otp.verified",
  "timestamp": "2025-01-01T00:05:30.000Z",
  "data": {
    "requestId": "a1b2c3d4-...",
    "channel": "email",
    "recipient": "user@example.com",
    "status": "verified"
  }
}

Verifying Webhook Signatures

Every webhook request includes an X-Clashup-Signature header containing an HMAC-SHA256 signature.

const crypto = require('crypto');

function verifySignature(payload, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

// In your webhook handler:
app.post('/webhook', (req, res) => {
  const signature = req.headers['x-clashup-signature'];
  const isValid = verifySignature(
    JSON.stringify(req.body),
    signature,
    'your_webhook_secret'
  );
  if (!isValid) return res.status(401).send('Invalid');
  // Process the event...
  res.status(200).send('OK');
});

Health Check

GET /api/health

Returns API status. No authentication required.

{
  "success": true,
  "message": "CLASHUP API is running",
  "data": {
    "status": "operational",
    "version": "1.0.0",
    "uptime": 86400,
    "mongodb": "connected"
  }
}