Chronary Waitlist API
The Waitlist API from Chronary — 4 operation(s) for waitlist.
The Waitlist API from Chronary — 4 operation(s) for waitlist.
Every API here is available over the APIs.io API and to AI agents over MCP.
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
find_apisBrowse and filter every API in the catalog.get_api_artifactsOne API's artifacts, grouped by type.get_openapiThe primary OpenAPI for this API.find_similar_apisAPIs that look like this one.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.curl "https://apis.io/api/v1/apis/chronary-ai:chronary-ai-waitlist-api"
curl "https://apis.io/api/v1/apis?limit=25"
Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: Chronary Waitlist API
version: 1.0.0
description: 'Calendar-as-a-service API for AI agents.
Manage calendars, events, and availability for AI and human agents.
All endpoints require an API key passed as a Bearer token.
**Authentication:** `Authorization: Bearer chr_sk_...` or `Authorization: Bearer chr_ak_...`
**Rate limit:** 10 requests/second per API key. Exceeds return HTTP 429.
**Quotas:** Monthly operation limits by plan — see Billing & plans and Rate limits.
**Agent bootstrap:** Custom extensions prefixed `x-agent-*` describe the self-signup flow for AI agents. These are not part of any registered OpenAPI extension — they are a Chronary convention.'
contact:
name: Chronary Support
email: support@chronary.ai
url: https://docs.chronary.ai
servers:
- url: https://api.chronary.ai
description: Production
security:
- BearerAuth: []
tags:
- name: Waitlist
paths:
/v1/waitlist:
post:
operationId: joinWaitlist
summary: Join the waitlist
description: 'Join the Chronary soft-launch waitlist. Creates a row in the `waitlist` intake table — no
organization is created until the prospect is approved by a founder and clicks the signed
invite link sent to their email.
Idempotent on repeat hits: the same email returns 200 with the existing entry instead of 409.
An active (non-waitlisted) account at the same email returns 409 `email_taken`.
Rate limit: per-IP and per-email via the public rate limiter.'
tags:
- Waitlist
security: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/WaitlistJoinRequest'
responses:
'200':
description: Email already on the waitlist; idempotent re-hit.
content:
application/json:
schema:
$ref: '#/components/schemas/WaitlistJoinResponse'
'201':
description: Waitlist entry created. Confirmation email queued.
content:
application/json:
schema:
$ref: '#/components/schemas/WaitlistJoinResponse'
'400':
description: Validation error — invalid request body or query parameters
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: An active account already exists for this email, or `tos_version` is stale.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: Rate limited — 10 requests per second per key exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v1/capacity:
get:
operationId: getCapacity
summary: Public soft-launch capacity gauge
description: 'Returns the percentage of soft-launch slots currently occupied. Public, unauthenticated,
IP rate-limited. Used by the marketing-site homepage to drive the capacity indicator and
flip the CTA between "Get early access" (open) and "Join waitlist" (full).
Absolute slot counts are intentionally not exposed.
After GA cutover the gauge is meaningless and always returns `{percent_full: 0, status: "open"}`.'
tags:
- Waitlist
security: []
responses:
'200':
description: Current capacity gauge.
content:
application/json:
schema:
$ref: '#/components/schemas/CapacityResponse'
'429':
description: Rate limited — 10 requests per second per key exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v1/invite/verify:
get:
operationId: verifyInvite
summary: Verify a soft-launch invite token
description: 'Validates a signed invite token (purpose=`invite_claim`) and returns the email + expiry
so the console can pre-fill the claim form. Read-only — does not consume the token.
Public, IP+token rate-limited.'
tags:
- Waitlist
security: []
parameters:
- schema:
type: string
minLength: 20
example: eyJhbGciOiJIUzI1NiIs…
required: true
name: token
in: query
responses:
'200':
description: Token is valid and entry is in `approved` state.
content:
application/json:
schema:
$ref: '#/components/schemas/InviteVerifyResponse'
'400':
description: Token is missing or malformed.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Entry has already been claimed or revoked.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'410':
description: Token has expired.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: Rate limited — 10 requests per second per key exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v1/invite/claim:
post:
operationId: claimInvite
summary: Claim a soft-launch invite
description: 'Consumes a signed invite token and provisions an active org with `plan=pro`,
`plan_source=soft_launch_invite`, `plan_expires_at=ga_date`. Mints a live + test API key
and transitions the waitlist entry to `claimed`.
OTP is intentionally skipped — token possession (delivered to the email captured at
intake) is the email-ownership proof. Public, IP+token rate-limited.'
tags:
- Waitlist
security: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/InviteClaimRequest'
responses:
'201':
description: Org created. Live + test API keys returned (only chance to see them).
content:
application/json:
schema:
$ref: '#/components/schemas/InviteClaimResponse'
'400':
description: Token is missing or malformed.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Email already has an active account, or invite already claimed.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'410':
description: Token has expired.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: Rate limited — 10 requests per second per key exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
components:
schemas:
CapacityResponse:
type: object
properties:
percent_full:
type: integer
minimum: 0
maximum: 100
example: 42
description: Percent of soft-launch slots currently occupied. 0–100.
status:
type: string
enum:
- open
- full
example: open
description: '`open` when new auto-approvals are accepted; `full` when at capacity.'
required:
- percent_full
- status
InviteClaimRequest:
type: object
properties:
token:
type: string
minLength: 20
maxLength: 4096
example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.…
required:
- token
InviteVerifyResponse:
type: object
properties:
email:
type: string
format: email
example: dev@acme.ai
expires_at:
type: string
example: '2026-05-22T12:00:00.000Z'
required:
- email
- expires_at
Error:
type: object
properties:
error:
type: object
properties:
type:
type: string
example: invalid_request
message:
type: string
example: The field "name" is required.
request_id:
type: string
example: req_01H9X4M2P5R8T6V0
required_plan:
type: string
example: pro
description: 'plan_required: the plan that unlocks the feature'
feature:
type: string
description: 'plan_required: the gated feature'
metric:
type: string
description: 'quota_exceeded and count caps: the metric at its limit (a PLAN_LIMITS key, accepted by POST /v1/billing/upgrade-requests)'
limit:
type: integer
description: 'quota_exceeded and count caps: the plan''s limit for `metric`'
upgrade_url:
type: string
description: Where a human upgrades the plan
docs_url:
type: string
contact_url:
type: string
description: 'Contract-managed plans: where to contact sales'
retry_after:
type: integer
description: Seconds until the request may be retried
required:
- type
- message
- request_id
required:
- error
InviteClaimResponse:
type: object
properties:
org_id:
type: string
example: aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
agent_id:
type: string
example: agt_abc123
api_key:
type: string
example: chr_sk_…
plan:
type: string
enum:
- pro
example: pro
plan_expires_at:
type:
- string
- 'null'
example: '2026-12-01T00:00:00.000Z'
required:
- org_id
- agent_id
- api_key
- plan
- plan_expires_at
WaitlistJoinRequest:
type: object
properties:
email:
type: string
format: email
example: dev@acme.ai
name:
type: string
minLength: 2
maxLength: 100
example: Acme AI
tos_version:
type: string
minLength: 1
example: '2026-10-28'
intent:
type: string
maxLength: 200
example: Building an AI scheduling agent for sales teams.
description: '"What are you building?" — free-text, capped at 200 chars.'
required:
- email
WaitlistEntry:
type: object
properties:
id:
type: string
example: aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
email:
type: string
format: email
example: dev@acme.ai
intent:
type:
- string
- 'null'
example: Building an AI scheduling agent.
status:
type: string
example: pending
created_at:
type: string
example: '2026-05-09T12:00:00.000Z'
required:
- id
- email
- intent
- status
- created_at
WaitlistJoinResponse:
type: object
properties:
data:
$ref: '#/components/schemas/WaitlistEntry'
message:
type: string
example: You're on the list. Check your email for a confirmation.
required:
- data
- message
securitySchemes:
BearerAuth:
type: http
scheme: bearer
description: 'API key with `chr_sk_*` for org-level access or `chr_ak_*` for agent-scoped access. Pass in the Authorization header: `Authorization: Bearer chr_sk_...`'
SessionAuth:
type: apiKey
in: cookie
name: chronary_session
description: Console session JWT (HS256), issued by sign-in and sent as the `chronary_session` cookie (a Bearer JWT is also accepted). This is NOT a chr_sk_*/chr_ak_* API key — API keys are rejected with 401 on these endpoints.
x-agent-self-signup:
url: https://api.chronary.ai/v1/agent/sign-up
verify_url: https://api.chronary.ai/v1/agent/verify
restricted_key_returned: true
human_in_the_loop: otp_email
rate_limit: 5 requests per 60s per client IP
x-agent-bootstrap-script:
npx: npx @chronary/agent-init@latest
shell: https://chronary.ai/agent-init.sh
description: One-liner that performs sign-up, prompts for OTP, verifies, and creates a smoke calendar. Accepts CHRONARY_EMAIL and CHRONARY_OTP env vars for non-interactive flows.
x-llms-txt: https://docs.chronary.ai/llms.txt
x-llms-full-txt: https://docs.chronary.ai/llms-full.txt
x-mcp-server-card: https://chronary.ai/.well-known/mcp/server-card.json
x-api-catalog: https://chronary.ai/.well-known/api-catalog