⌘K
Integrations

Wire the current `/api/validate*` routes into your app, batch runner, or operator tooling.

RtU Integration

Use the current Souma proxy routes when you want your product or internal tooling to submit RtU checks through the same application surface the dashboard uses.

Current integration shape

  1. Submit one or more URLs with a usage purpose
  2. Souma accepts the batch and returns a validation_id per request
  3. Read results back through polling or SSE
  4. Surface completed checks in the same review workflow your operators use in the dashboard

Current proxy routes

RouteMethodUse
/api/validatePOSTSubmit one or more validations
/api/validate/resultsGETFetch paginated result history
/api/validate/result/:idGETPoll a single validation
/api/validate/streamGETStream updates for one or more validation IDs

Authentication

These routes require a Souma API key in the Authorization header:

Authorization: Bearer YOUR_API_KEY

Generate the key from Dashboard > Integration > API Keys or during the workspace setup flow.

Submit a batch

curl -X POST http://localhost:3000/api/validate \
  -H "Authorization: Bearer sk_prod_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "validations": [
      {
        "request_id": "550e8400-e29b-41d4-a716-446655440000",
        "url": "https://example.com/article",
        "purpose": "AI model training"
      }
    ]
  }'

Response shape

{
  "results": [
    {
      "request_id": "550e8400-e29b-41d4-a716-446655440000",
      "validation_id": "val_abc123",
      "status": "COMPLETED",
      "url": "https://example.com/article",
      "usage_purpose": "AI model training",
      "allowed_for_use": "PERMITTED",
      "confidence_score": 0.92,
      "llm_reasoning": "The site's Terms of Service explicitly permit...",
      "conditions": ["Attribution required"],
      "policy_source_urls": ["https://example.com/terms"],
      "created_at": "2026-03-20T10:30:00Z",
      "completed_at": "2026-03-20T10:30:02Z"
    }
  ]
}

Notice the naming difference:

  • request uses purpose
  • response returns the normalized field as usage_purpose

Batch strategy for large URL lists

Do not send one enormous URL list and block the UI while it runs. The current checker uses:

  • batch size: 8 URLs
  • concurrency: 2 active requests
  • timeout budget: 24-25 seconds per submission call

That is a good default for production too.

const VALIDATION_BATCH_SIZE = 8
const VALIDATION_BATCH_CONCURRENCY = 2

Polling a single result

curl -X GET http://localhost:3000/api/validate/result/val_abc123 \
  -H "Authorization: Bearer sk_prod_xxx"

Listing recent results

curl -X GET "http://localhost:3000/api/validate/results?limit=50&offset=0&status=COMPLETED" \
  -H "Authorization: Bearer sk_prod_xxx"

Real-time streaming

For long-running validations, use Server-Sent Events to get results as they complete:

const ids = result.results.map((r) => r.validation_id)
const params = ids.map((id) => `validation_ids=${id}`).join('&')
const eventSource = new EventSource(
  `/api/validate/stream?${params}`
)

eventSource.addEventListener('result', (event) => {
  const updated = JSON.parse(event.data)
  console.log(updated.url, updated.allowed_for_use)
})

eventSource.addEventListener('done', () => {
  eventSource.close()
})

Timeouts and 504s

The current proxy returns 504 when the upstream call exceeds its timeout budget. In practice that means:

  • the batch was too large
  • one or more URLs were slow to fetch
  • the validation should continue asynchronously instead of blocking the request

Recommended handling:

  1. keep batches small
  2. retry only the failed batch, not the entire workload
  3. persist partial successes immediately
  4. switch to polling or SSE once the batch is accepted

Next steps