Operate an API integration

Use https://stylome.io as the base URL. The OpenAPI schema defines complete response types for all six endpoints. The read endpoints below do not submit text to the detector.

Read limits and prepaid balance

GET /api/v1/limits requires Bearer authentication with account:read. It does not consume the scoring request window.

curl --fail-with-body https://stylome.io/api/v1/limits \
  --header "Authorization: Bearer $STYLOME_API_KEY"

The result has object: "api_limits", measured_at, rate_limit_scope: "account", window_seconds, request_limit, remaining_requests, resets_at, rate_limit_exempt, request_timeout_seconds, idempotency_lifetime_seconds, idempotency_supported, retention_mode, and prepaid. Operator-exempt keys can have null request-limit and reset fields; ordinary integrations must not assume an exemption.

prepaid contains currency, balance_usd, reserved_usd, available_usd, billing_review_required, topup_min_usd, and topup_max_usd. Monetary values are decimal strings. Available credit accounts for reservations; the request window and credit balance are separate constraints.

Read usage

GET /api/v1/usage requires Bearer authentication with usage:read.

Query parameter Rule
start Inclusive timezone-aware timestamp; defaults to seven days before end
end Exclusive timezone-aware timestamp; defaults to now
group_by day (default), model, or key
model Optional model ID; retired IDs are accepted for historical usage
key Optional 16-character lowercase hexadecimal public key ID; never send a secret

Use a start before end, no future end, and a range of at most 90 days. A report with too many groups returns 422; narrow the range or add a filter.

curl --fail-with-body --get https://stylome.io/api/v1/usage \
  --header "Authorization: Bearer $STYLOME_API_KEY" \
  --data-urlencode 'group_by=model'

The response has object: "api_usage", start, end, measured_at, group_by, totals, data, and description. Totals and each bucket report requests, successes, failures, pending, billed_characters, cost_usd, and unpriced_requests; buckets also have value. Reports use operation start time and exclude idempotent replays and failures before ledger creation. Historical unpriced operations have no inferred charge.

Check service status

GET /api/v1/status is public. It returns object: "api_status", status (operational or degraded), checked_at, database (reachable or unavailable), inference (configured or unconfigured), and description. Operational responses use 200; degraded responses use 503. The check can be cached internally for 15 seconds. It checks database reachability and configuration presence; it does not run inference or guarantee model availability.

Rate limits and deadlines

Ordinary accounts share a fixed 120-request, 60-second scoring window across all their keys. Scoring attempts count after authentication and text validation, including failures and idempotent replays. An exhausted window returns 429 with Retry-After in seconds.

RateLimit-Policy describes the window and quota. RateLimit gives the remaining count and time to reset. Compatibility headers are X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset (Unix seconds). X-RateLimit-Exempt: true appears for an operator-exempt key.

Scoring admission and inference have a 110-second deadline. Allow 150 seconds in your client for transport and finalization. Each worker admits eight developer scoring calls. Use bounded exponential backoff with jitter for retryable failures, and honor Retry-After.

Idempotency and safe retries

For a standard-retention key, send a project-wide, case-sensitive opaque Idempotency-Key of 1–255 characters. Use a new value for each logical scoring operation. A completed result replays for 24 hours when normalized text, model, and operating point match. Changing those inputs with the same key returns 409 idempotency_conflict. A pending operation returns 409 idempotency_in_progress with Retry-After.

A successful replay returns X-Idempotent-Replayed: true and the original X-Operation-ID. It consumes the request-rate window but adds no charge. X-Request-ID identifies the current HTTP attempt. Zero-content keys reject idempotency headers with 400 idempotency_not_supported.

A network failure can happen after processing and charging. Preserve the idempotency key for safe standard-retention retries. Do not automatically repeat a scoring POST without an idempotency key. With zero-content keys, the service cannot replay a response; a repeated successful scoring call is another paid operation.

Errors and response headers

Developer API errors use the JSON envelope below. The names and types shown are a schema description, not a recorded service response:

error: {
  code: string,
  message: string,
  request_id: string,
  retryable: boolean,
  param: string | null,
  fields: [{loc: (string | integer)[], msg: string, type: string}] | null
}
HTTP status Action
400 Correct an invalid option or unsupported idempotency header
401 / 403 Check credential, scope, or billing-review status
402 Add prepaid API credit
404 Check the requested resource or path
409 Distinguish a conflicting request from an in-progress operation
422 Correct validation, text length, model, or usage range
429 Wait for Retry-After
500 / 502 / 503 / 504 Check retryable; follow safe-retry rules

Every API attempt returns X-Request-ID. Scoring returns X-Operation-ID once an operation is identified. X-Stylome-Data-Retention is none for zero-content scoring or standard for retained scoring. Scoring responses use Cache-Control: no-store. Keep request IDs for support and redact keys, submitted text, and private receipt capabilities from logs.