openapi: 3.0.3 info: title: cons API version: "1" description: | cons evaluates Scheme over HTTP. Send source and get back the value of every top-level form, the output, execution stats and structured errors. HTTP status codes describe the request, not the program: an evaluation that ran is always 200, whatever its outcome. The outcome is in `status`. servers: - url: https://api.cons.stneto.dev components: securitySchemes: apiKey: type: http scheme: bearer description: An API key from the app's API keys page (`cons_...`). headers: RateLimit-Limit: description: Requests allowed in the current window. schema: type: integer RateLimit-Remaining: description: Requests left in the current window. schema: type: integer RateLimit-Reset: description: Seconds until the window resets. schema: type: integer Retry-After: description: Seconds to wait before retrying. schema: type: integer schemas: EvalRequest: type: object required: - source properties: source: type: string description: Scheme source. At most 64 KB on the API, 4 KB on the demo. timeout_ms: type: integer minimum: 1 maximum: 5000 description: Wall-clock limit. API default 1000, max 5000. The demo uses 500 and allows at most 500. Result: type: object required: - index - line - col - value - value_truncated - json properties: index: type: integer description: 0-based position of the form in the source. line: type: integer col: type: integer value: type: string nullable: true description: Printed (`write`) form, exact for every type. `null` when the value is unspecified. value_truncated: type: boolean json: nullable: true description: | Typed copy of the value: numbers, strings (strings and symbols), booleans, arrays (proper lists). `null` for improper lists, procedures and unspecified values. JS clients lose precision past 2^53; use `value` for exact bignums. Stats: type: object required: - wall_ms - cpu_ms - steps - memory_bytes properties: wall_ms: type: number cpu_ms: type: number description: CPU time used; what's billed, as max(1, ceil(cpu_ms)). steps: type: integer nullable: true description: null when the process was killed. memory_bytes: type: integer nullable: true description: null when the process was killed. EvalError: type: object required: - type - message - index - line - col properties: type: type: string description: Stable identifier to match on. enum: - syntax_error - unbound_variable - wrong_type - arity_mismatch - not_a_procedure - division_by_zero - arithmetic_error - user_error - timeout - step_limit - memory_limit - integer_too_large - too_complex - source_too_large - internal_error message: type: string index: type: integer nullable: true description: The form that failed. line: type: integer nullable: true col: type: integer nullable: true EvalResponse: type: object required: - status - results - stdout - stdout_truncated - stats - error - request_id properties: status: type: string enum: - ok - error - timeout - limit_exceeded results: type: array description: The forms that finished, in order. items: $ref: "#/components/schemas/Result" stdout: type: string stdout_truncated: type: boolean stats: $ref: "#/components/schemas/Stats" error: allOf: - $ref: "#/components/schemas/EvalError" nullable: true request_id: type: string example: req_8k2j4h5g6f7d8s9a0p1o Error: type: object required: - error - request_id properties: error: type: object required: - type - message properties: type: type: string enum: - invalid_json - invalid_request - unauthorized - forbidden_origin - not_found - source_too_large - request_too_large - rate_limited - too_many_in_flight - cpu_quota_exceeded - busy - internal_error message: type: string request_id: type: string nullable: true Health: type: object required: - status - request_id properties: status: type: string enum: - ok request_id: type: string Limits: type: object required: - plan - rate_limit - in_flight - cpu - max_timeout_ms - request_id properties: plan: type: string example: free description: The account's plan. rate_limit: type: object required: - limit - remaining - used - reset_s properties: limit: type: integer remaining: type: integer used: type: integer reset_s: type: integer in_flight: type: object required: - limit - current properties: limit: type: integer current: type: integer cpu: type: object required: - month - quota_ms - used_ms - remaining_ms - reset_s properties: month: type: string example: 2026-10 quota_ms: type: integer used_ms: type: integer remaining_ms: type: integer reset_s: type: integer max_timeout_ms: type: integer request_id: type: string responses: BadJson: description: The body isn't valid JSON (`invalid_json`). content: application/json: schema: $ref: "#/components/schemas/Error" Unauthorized: description: Missing, malformed, unknown or revoked key (`unauthorized`). content: application/json: schema: $ref: "#/components/schemas/Error" TooLarge: description: Source over the limit (`source_too_large`) or body over 1 MB (`request_too_large`). content: application/json: schema: $ref: "#/components/schemas/Error" Invalid: description: Missing or non-string `source`, or bad `timeout_ms` (`invalid_request`). content: application/json: schema: $ref: "#/components/schemas/Error" Busy: description: Every evaluation slot is taken (`busy`). Retry shortly. content: application/json: schema: $ref: "#/components/schemas/Error" paths: /v1/health: get: summary: Liveness check responses: "200": description: The service is up. content: application/json: schema: $ref: "#/components/schemas/Health" /v1/eval: post: summary: Evaluate a program security: - apiKey: [] requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/EvalRequest" responses: "200": description: The program ran. Check `status` for the outcome. headers: RateLimit-Limit: $ref: "#/components/headers/RateLimit-Limit" RateLimit-Remaining: $ref: "#/components/headers/RateLimit-Remaining" RateLimit-Reset: $ref: "#/components/headers/RateLimit-Reset" content: application/json: schema: $ref: "#/components/schemas/EvalResponse" "400": $ref: "#/components/responses/BadJson" "401": $ref: "#/components/responses/Unauthorized" "413": $ref: "#/components/responses/TooLarge" "422": $ref: "#/components/responses/Invalid" "429": description: | Per-key rate limit (`rate_limited`, 60/min), too many concurrent evals for the account (`too_many_in_flight`, 4), or the monthly CPU quota is used up (`cpu_quota_exceeded`). headers: Retry-After: $ref: "#/components/headers/Retry-After" content: application/json: schema: $ref: "#/components/schemas/Error" "503": $ref: "#/components/responses/Busy" /v1/limits: get: summary: Current rate limit, concurrency and CPU quota description: Doesn't count against the rate limit. security: - apiKey: [] responses: "200": description: The caller's limits. content: application/json: schema: $ref: "#/components/schemas/Limits" "401": $ref: "#/components/responses/Unauthorized" /v1/demo: post: summary: Anonymous evaluation for the site's try-it box description: | No key, tighter limits (500 ms, 1M steps, 4 KB source, 50 compound expressions). Only the site's origin may call it, and each IP gets 10 runs a minute and 100 a day. requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/EvalRequest" responses: "200": description: The program ran. content: application/json: schema: $ref: "#/components/schemas/EvalResponse" "400": $ref: "#/components/responses/BadJson" "403": description: The request didn't come from the site's origin (`forbidden_origin`). content: application/json: schema: $ref: "#/components/schemas/Error" "413": $ref: "#/components/responses/TooLarge" "422": $ref: "#/components/responses/Invalid" "429": description: Per-IP rate limit (`rate_limited`). headers: Retry-After: $ref: "#/components/headers/Retry-After" content: application/json: schema: $ref: "#/components/schemas/Error" "503": $ref: "#/components/responses/Busy"