Verify Signature

Ensure the integrity of API responses with cryptographic signatures

Overview

All responses from the Omni API include a cryptographic signature that allows you to verify the response came from our service and hasn't been tampered with. This is particularly important for content moderation, where the integrity of the results is critical.

Why Verify Signatures?

Verifying signatures helps protect against:

  • Man-in-the-middle attacks
  • Response tampering
  • Forged moderation results

How It Works

Each API response includes a signature field that contains an HMAC-SHA256 signature of the response payload. The signature is computed using your account's signature secret, which you can find in your Omni dashboard.

To verify the signature, you need to:

  1. Create a copy of the response without the signature field
  2. Sort the keys of the response object
  3. Convert the response to a JSON string
  4. Compute the HMAC-SHA256 signature using your signature secret
  5. Compare the computed signature with the one in the response

Signature Verification Examples

JavaScript

verify-signature.js
const crypto = require('crypto');

function verifySignature(response, signatureSecret) {
  // Create a copy of the response without the signature
  const payload = { ...response };
  const receivedSignature = payload.signature;
  delete payload.signature;
  
  // Compute the signature
  const payloadStr = JSON.stringify(payload, Object.keys(payload).sort());
  const expectedSignature = crypto
    .createHmac('sha256', signatureSecret)
    .update(payloadStr)
    .digest('hex');
  
  // Compare signatures
  return crypto.timingSafeEqual(
    Buffer.from(expectedSignature, 'hex'),
    Buffer.from(receivedSignature, 'hex')
  );
}

// Example usage
const apiResponse = {
  id: "modr-123456",
  model: "text-moderation-latest",
  results: [
    // ... moderation results
  ],
  flagged: false,
  signature: "abcdef1234567890"
};

const signatureSecret = "your_signature_secret";
const isValid = verifySignature(apiResponse, signatureSecret);

console.log(`Signature is ${isValid ? 'valid' : 'invalid'}`);

Python

verify_signature.py
import hmac
import hashlib
import json

def verify_signature(response, signature_secret):
    # Create a copy of the response without the signature
    payload = response.copy()
    received_signature = payload.pop("signature", None)
    
    # Compute the signature
    payload_str = json.dumps(payload, sort_keys=True)
    expected_signature = hmac.new(
        signature_secret.encode("utf-8"), 
        payload_str.encode("utf-8"), 
        hashlib.sha256
    ).hexdigest()
    
    # Compare signatures
    return hmac.compare_digest(expected_signature, received_signature)

# Example usage
api_response = {
    "id": "modr-123456",
    "model": "text-moderation-latest",
    "results": [
        # ... moderation results
    ],
    "flagged": False,
    "signature": "abcdef1234567890"
}

signature_secret = "your_signature_secret"
is_valid = verify_signature(api_response, signature_secret)

print(f"Signature is {'valid' if is_valid else 'invalid'}")

PHP

verify_signature.php
<?php

function verifySignature($response, $signatureSecret) {
    // Create a copy of the response without the signature
    $payload = $response;
    $receivedSignature = $payload['signature'];
    unset($payload['signature']);
    
    // Compute the signature
    ksort($payload); // Sort keys
    $payloadStr = json_encode($payload);
    $expectedSignature = hash_hmac('sha256', $payloadStr, $signatureSecret);
    
    // Compare signatures
    return hash_equals($expectedSignature, $receivedSignature);
}

// Example usage
$apiResponse = [
    'id' => 'modr-123456',
    'model' => 'text-moderation-latest',
    'results' => [
        // ... moderation results
    ],
    'flagged' => false,
    'signature' => 'abcdef1234567890'
];

$signatureSecret = 'your_signature_secret';
$isValid = verifySignature($apiResponse, $signatureSecret);

echo "Signature is " . ($isValid ? 'valid' : 'invalid');

Obtaining Your Signature Secret

You can find your signature secret in your Omni dashboard under the API settings section. The signature secret is different from your API key and should be kept secure.

Security Note

Your signature secret is a sensitive credential. Never expose it in client-side code or public repositories. Always verify signatures on your server, not in client-side applications.

Next Steps