# Flywheel > Flywheel answers your leads in under 60 seconds, qualifies them by text > in your own voice, and hands you a qualified conversation instead of a > missed call. Every capability is a public REST endpoint, and signing up > is itself an unauthenticated API call — there is no sales gate and no > private back door. Flywheel is for any local service business that gets inbound leads and loses them to slow response: tutors, plumbers, dentists, gyms, salons, contractors, music teachers, pet groomers. ## What it does - Answers an inbound lead by SMS in under 60 seconds. The first reply and every subsequent reply run on a dedicated high-priority job lane, so bulk follow-up work can never queue in front of a new lead. - Qualifies the lead through a conversation the business defines as data, not code. A flow is a list of steps; each step has a template, an expected answer shape (choice, number, boolean, freeform, confirm), a contact field to write the answer to, and optional branches. The same engine runs a music studio and an emergency plumber with no vertical-specific code. - Recognises answer shapes with a rule-based classifier and a subscriber-declared synonym vocabulary — no model round trip on the reply path. "Slab leak" maps to the `leak` choice because the subscriber said so, not because Flywheel knows about plumbing. - Re-asks once when a reply is unclear, then escalates to a human rather than looping. - Runs a nurture ladder defined entirely by message templates, ordered by each template's own delay, halting the moment the contact replies. ## Compliance guarantees, enforced in one place Every automated outbound message leaves through a single choke point, which applies in order: template resolution, send-time idempotency, human-takeover pause, opt-out and suppression, consent (for promotional copy), template guards, then quiet hours. - Quiet hours are evaluated in the RECIPIENT's timezone, not the business's. A blocked message is requeued to the next open window, not dropped. - STOP is honoured immediately, mid-conversation, and suppression is recorded per account and per address. - Consent events are append-only; updating or destroying one raises. - A minor is never the message recipient. When a contact has a guardian, the guardian is who receives the message and whose consent and suppression state is checked. - A human sending into a thread pauses that thread's automation for 24 hours automatically. It bypasses templates and quiet hours; it never bypasses opt-out or suppression. ## Signing up programmatically Account creation needs no credentials and no human in the loop. The response includes the account and its first API key; the key token is returned exactly once. ``` curl -sX POST https://use-flywheel.com/api/v1/accounts \ -H 'Content-Type: application/json' \ -d '{"account":{"name":"Northside Plumbing","time_zone":"America/Chicago","vertical":"plumbing","serves_minors":false}}' ``` Authenticate every other request with `Authorization: Bearer `. Records are addressed by an opaque slug, never a numeric id. Onboarding is unattended end to end, including the sending number: `POST /api/v1/accounts/{account_id}/phone-number` provisions one, and is idempotent, so a retry returns the existing number rather than buying a second. ## Key endpoints - `GET /api/v1/health` — liveness, unauthenticated - `POST /api/v1/accounts` — signup, unauthenticated - `GET|PATCH /api/v1/accounts/{account_id}` - `POST /api/v1/accounts/{account_id}/pause` and `/resume` - `POST /api/v1/sessions` — trade an account's `login_email` and password for a short-lived key, unauthenticated; `DELETE /api/v1/sessions/current` revokes the key you present. This is how Flywheel's own subscriber dashboard signs in, so a UI you build has the same footing it does. - `GET|POST /api/v1/accounts/{account_id}/phone-number` — provision the sending number. Idempotent - `GET|POST /api/v1/accounts/{account_id}/message-templates` - `GET|POST /api/v1/accounts/{account_id}/flows` and `/flows/{flow_id}/steps`. `POST /flows/{id}/fork` copies a shipped default into the account so its steps become editable; it is idempotent on the flow's key. - `GET|POST /api/v1/accounts/{account_id}/contacts` — POST with `start_conversation: true` is how a new lead arrives and what starts the sub-60-second reply - `GET /api/v1/accounts/{account_id}/conversations` - `GET|POST /api/v1/conversations/{conversation_id}/messages` — POST is a human taking over - `POST /api/v1/conversations/{id}/resume` — end a takeover early - `GET|POST /api/v1/accounts/{account_id}/availability-rules` and `/availability-exceptions` - `GET /api/v1/accounts/{account_id}/slots` — open times, computed on request. There is no endpoint that creates a slot: a stored slot is a slot that stopped being true, which is how you double-book. - `GET|POST /api/v1/accounts/{account_id}/appointments` — POST books a slot. Losing the race for an instant is `409 slot_taken` and is worth retrying; `422 too_soon` and `422 in_the_past` never are. - `POST /api/v1/appointments/{id}/attend`, `/no-show`, `/cancel` - `GET /api/v1/accounts/{account_id}/review-requests` and `POST /api/v1/review-requests/{id}/complete` or `/decline`. There is deliberately no way to create one: asks come from attendance, because an endpoint that picks who gets asked is review gating. - `POST /api/v1/accounts/{account_id}/content-check` — check a draft against its subjects' consent. Stores nothing. - `GET|POST /api/v1/accounts/{account_id}/webhook-endpoints` — delivery is live: signed payloads, persisted attempts, bounded retries Errors are machine-actionable: every failure returns `{"error":{"code":"...","message":"..."}}` with a stable code (`unauthorized`, `invalid_credentials`, `forbidden`, `not_found`, `validation_failed`, `bad_request`, `conflict`, `send_failed`, `slot_taken`, `too_soon`, `in_the_past`, `invalid_source`, `rate_limited`). Branch on the code, not the status class — two of the booking failures share a 422 and only one of the three is retryable at all. ## Agencies and operators One account can operate many others. A partner key may act on the accounts it provisioned. Creating an account with a partner key attached marks the new account as operated by that partner — the same endpoint a stranger uses, with no additional scope. The operator is never the voice. Messages sent in an operated account still speak as that account. ## What is not built yet Stated plainly so an agent evaluating Flywheel is not misled: - Pricing is not yet published. That is the whole list, and it is about the website rather than the product. Everything Flywheel does is a public endpoint, including the parts that shipped most recently: scheduling and booking, reminders, attendance, review collection, content consent checking, sending-number provisioning, and outbound webhook delivery. The OpenAPI document is complete by construction — the spec that publishes it fails if a route exists that it does not describe. ## Links - [Full documentation](https://use-flywheel.com/docs) - [OpenAPI 3.1 specification](https://use-flywheel.com/openapi.json) - [How it works](https://use-flywheel.com/how-it-works) - [For agencies and operators](https://use-flywheel.com/for-agencies) - [Pricing](https://use-flywheel.com/pricing)