API Best Practices
Build reliable API integrations with webhooks, batch, and SSE
Beyond token hygiene, error retries, and respecting rate limits, integration quality comes down to three high-traffic scenarios: webhook triggers, batch operations, and SSE streaming. This page converges the Do / Don't guidance for those three; endpoint details live on their reference pages.
Tokens and Authentication
JWTs have no refresh endpoint: before the session_timeout_days lifetime (default 30 days) expires, log in again via POST /api/v1/login/access-token. Use API Keys for server-to-server calls (least privilege, regular rotation, one key per service) and revoke compromised keys immediately.
Do: store tokens in environment variables or secure storage, use different tokens per environment, monitor token usage. Don't: hardcode tokens in source, commit them to version control, reuse production tokens in development, or share tokens between users.
import os
class TokenManager:
"""Re-authenticate before expiry (no refresh endpoint)."""
def get_token(self):
if not self.token or self.is_expiring_soon():
data = requests.post(
f"{API_BASE_URL}/api/v1/login/access-token",
data={"username": os.getenv("CLOUISLE_USERNAME"), "password": os.getenv("CLOUISLE_PASSWORD")},
).json()["data"]
self.token = data["access_token"]
return self.tokenWebhook Triggers
POST /api/v1/workflows/webhook/{webhook_token} is the only workflow entry that accepts API Key authentication: the token goes in the URL path while the Authorization header must still carry a clou_-prefixed API Key. The workflow must be published with trigger type webhook; tokens and stream URLs are not public or unauthenticated, and workflow access rules still apply. Rotate the token with POST /api/v1/workflows/{workflow_id}/regenerate-webhook-token.
Do: treat the webhook_token as a secret (regenerate on leak), check publish status and trigger type when triggers fail, and make external retry deliveries idempotent or deduplicated. Don't: embed the token in publicly served frontend code, assume webhooks are anonymously callable, or trigger draft or manual-trigger workflows.
curl -X POST "https://your-domain.com/api/v1/workflows/webhook/wh_abc123" \
-H "Authorization: Bearer clou_xxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"customer_email": "customer@example.com", "inquiry_text": "I need help"}'See Workflow Execution.
Batch Operations
Use only the batch endpoints that actually exist (see Conventions) — never guess a generic /batch path: batch delete conversations with DELETE /api/v1/conversations?ids=... (needs delete permission on every conversation, else 3000 or 4000); team-model authorize/revoke with POST / DELETE /api/v1/teams/{team_id}/models/batch (super admin only); retrieval comparison with POST /api/v1/knowledge-bases/{kb_id}/search/batch (one query × up to 10 configurations; one failed configuration doesn't fail the others); file parsing with POST /api/v1/upload/parse/batch (up to 5 files, more returns 1001; on mixed success data holds only the successful items).
Do: batch authorize instead of N single requests, use search/batch to compare retrieval configurations against one embedding, use parse/batch instead of looping the single parse endpoint. Don't: invent /batch paths for arbitrary resources, send more than 5 parse files or 10 search configurations, or assume deleted_count always equals the requested count (inaccessible IDs are ignored or error).
SSE Streaming
Agent chat streams (POST /api/v1/agents/{agent_id}/chat/stream) and workflow run streams (GET /api/v1/workflows/runs/{run_id}/stream) both return text/event-stream: send Accept: text/event-stream and parse event: / data: lines with curl -N or a streaming reader. Workflow runs are async: the run endpoint immediately returns run_id plus stream_url, then consume workflow_start, node_complete, workflow_complete, workflow_error, and similar events from the stream URL.
Do: receive updates via webhooks/SSE instead of polling status endpoints, reconnect workflow event streams with from_sequence=0, and cap stream timeouts and reconnects. Don't: poll GET /runs/{run_id} at high frequency, retry 429s immediately (use exponential backoff), or show raw errors to end users.
curl -N "https://your-domain.com/api/v1/workflows/runs/$RUN_ID/stream?from_sequence=0" \
-H "Authorization: Bearer $CLOUISLE_TOKEN"See Streaming Events and Workflow Execution.
Errors and Rate Limits
Check the response code before using data; validation failures are HTTP 422 with data.errors as a field-to-messages dictionary. Retry with exponential backoff (max 3 attempts) only for retryable errors: never retry 4xx client errors or 2xxx auth errors. Clouisle sends no X-RateLimit-* response headers; rate limiting applies to specific security-sensitive flows (login lockout, TOTP lockout, email quota, model quotas such as 6103 model-quota-exceeded and 5400 email/provider limits) — back off before retrying HTTP 429s.
import time
def retry_with_backoff(func, max_retries=3, delay=1.0):
for attempt in range(max_retries):
try:
return func()
except ApiError as e:
if 2000 <= e.code < 3000 or 4000 <= e.code < 5000:
raise
if attempt == max_retries - 1:
raise
time.sleep(delay)
delay *= 2Caching and Pagination
Fetch large datasets page by page (page / page_size, envelope in Conventions) instead of all at once; cache stable reads client-side; debounce search inputs instead of firing a request per keystroke.
Pre-Production Checklist
- All requests over HTTPS; tokens and keys in secure storage
- JWTs re-authenticated before expiry (no refresh endpoint); API Keys least-privilege and rotated
- Webhook tokens treated as secrets; workflow published with
webhooktrigger before triggering - Only documented batch endpoints used, within the 5-file / 10-configuration caps
- Streaming consumed via SSE plus reconnect, not status polling
- Handlers for 422 validation,
6103/5400quotas, and 429 backoff in place - Error and edge cases verified in a test environment, never with production credentials
Related Docs
- SDK and Code Samples — Generate a client and call the API
- Conventions — Pagination, filtering, sorting, and batch endpoints
- Workflow Execution — Runs, webhooks, and cancellation
- Streaming Events — Parsing SSE events
- Error Handling — HTTP status and business error codes
- Get Started — Your first request
How is this guide?