{"components":{"schemas":{"CaptureProposal":{"description":"The person a note is about, proposed for the coach to confirm. Nothing is saved.","properties":{"candidates":{"description":"Every person in the book this might be, ascending ids.","items":{"type":"integer"},"type":"array"},"next_step":{"properties":{"due_on":{"format":"date","type":["string","null"]},"text":{"type":"string"}},"type":["object","null"]},"note":{"description":"The transcript, lightly tidied.","type":"string"},"person":{"properties":{"match_id":{"description":"The person in the book this is, or null for someone new.","type":["integer","null"]},"name":{"type":["string","null"]},"organization":{"type":["string","null"]},"title":{"type":["string","null"]}},"type":"object"},"put_in_pipeline":{"description":"They discussed possible paid coaching work.","type":"boolean"},"tier":{"enum":["every_2_weeks","monthly","quarterly","twice_a_year","yearly",null],"type":["string","null"]}},"type":"object"},"Client":{"description":"A person you coach, or might. Everything in the pipeline is a client.","properties":{"email":{"description":"The client's email address.","type":"string"},"entered_stage_at":{"description":"When the client entered its current stage.","format":"date-time","readOnly":true,"type":"string"},"id":{"description":"Throughway's identifier for this client.","readOnly":true,"type":"integer"},"inserted_at":{"description":"When the client was created.","format":"date-time","readOnly":true,"type":"string"},"last_contact_at":{"description":"When you last had contact.","format":"date-time","readOnly":true,"type":"string"},"name":{"description":"The client's full name, as you'd write it on a card.","type":"string"},"organization":{"description":"The organization the client works for.","type":"string"},"outcome_note":{"description":"How the engagement ended.","type":"string"},"red_flags":{"description":"Anything to watch out for.","type":"string"},"running_notes":{"description":"Your rolling notes on this client.","type":"string"},"source":{"description":"How this client came to you.","type":"string"},"stage":{"description":"Where the client sits in the pipeline. Changing it records a stage transition. Null means the person is in the book only, off the board.","enum":["nurturing","in_conversation","chemistry_scheduled","deciding","onboarding","active","complete"],"type":"string"},"timezone":{"description":"IANA time zone, e.g. `America/New_York`.","type":"string"},"updated_at":{"description":"When the client last changed.","format":"date-time","readOnly":true,"type":"string"}},"type":"object"},"Document":{"description":"A client's Throughway page or Google Doc, which you can write, or a file or link, which you can only read. Anything you create is private.","properties":{"body":{"description":"Markdown. Converted to HTML for a page and to Google Docs formatting for a Google Doc. An update replaces the whole body; there is no append. Null for a file, a link, or a Google Doc Throughway can't reach. Never in list rows.","type":"string"},"client_id":{"description":"Which client it belongs to. An update can't move it.","type":"integer"},"hidden":{"description":"Hidden from the coach's Files and Timeline: coach (they hid it) or auto (a signature image or calendar attachment). Null when visible.","enum":["coach","auto",null],"readOnly":true,"type":["string","null"]},"id":{"description":"Throughway's identifier.","readOnly":true,"type":"integer"},"inserted_at":{"description":"When the document was created.","format":"date-time","readOnly":true,"type":"string"},"kind":{"description":"page and google_doc are writable. A list also shows file and link, read-only.","enum":["page","google_doc","file","link"],"type":"string"},"title":{"description":"For a Google Doc, also its name in Drive.","type":"string"},"updated_at":{"description":"When the document last changed.","format":"date-time","readOnly":true,"type":"string"},"url":{"description":"The Google Doc's link, or the page's link in Throughway.","readOnly":true,"type":"string"},"visibility":{"description":"Always private on create. Only the coach shares, in the app.","enum":["private","shared"],"readOnly":true,"type":"string"}},"type":"object"},"Error":{"properties":{"error":{"properties":{"code":{"enum":["bad_request","unauthorized","forbidden","not_found","validation_failed","google_not_connected","client_folder_missing","google_doc_unreachable","google_failed","ai_cap_reached","proposal_failed","not_due","photo_exists","photo_too_large","unsupported_media_type"],"type":"string"},"fields":{"description":"Present only for `validation_failed`.","type":"object"},"message":{"type":"string"}},"type":"object"}},"type":"object"},"Group":{"description":"One of your groups.","properties":{"id":{"type":"integer"},"name":{"type":"string"}},"type":"object"},"Interaction":{"description":"A logged contact with a client — a note, a call, a meeting, a message. This is what a client's timeline calls a note.","properties":{"client_id":{"description":"Which client this note is about. Set when you log it; an update cannot move it.","type":"integer"},"id":{"description":"Throughway's identifier for this note.","readOnly":true,"type":"integer"},"inserted_at":{"description":"When the note was logged.","format":"date-time","readOnly":true,"type":"string"},"note":{"description":"The note itself, plain text, stored and returned exactly as you send it.","type":"string"},"occurred_at":{"description":"When it happened, ISO 8601. Omit it and you get now.","format":"date-time","type":"string"},"source":{"description":"Who logged this note: `coach` when the coach logged it in Throughway, `agent` when an AI logged it through this API. Set by Throughway; a value you send is ignored.","enum":["coach","agent"],"readOnly":true,"type":"string"},"type":{"description":"What kind of contact this was.","enum":["call","email","meeting","message","note"],"type":"string"},"updated_at":{"description":"When the note last changed.","format":"date-time","readOnly":true,"type":"string"}},"type":"object"},"LooseEnd":{"description":"Someone you met or wrote to who isn't in the book yet.","properties":{"email":{"type":"string"},"id":{"type":"integer"},"last_met_on":{"format":"date","type":["string","null"]},"name":{"type":["string","null"]},"organization":{"description":"A guess from their address.","type":["string","null"]},"source":{"enum":["calendar","gmail"],"type":"string"}},"type":"object"},"NextStep":{"description":"Something to do for a person.","properties":{"body":{"type":"string"},"done":{"type":"boolean"},"due_on":{"format":"date","type":["string","null"]},"id":{"type":"integer"}},"type":"object"},"Person":{"description":"Someone in the coach's people book, as the iPhone app shows them: how to reach them, when they are next due, their open next steps and last notes. REST only; not an MCP tool.","properties":{"archived_at":{"description":"When they were archived, or null. One person only.","format":"date-time","readOnly":true,"type":["string","null"]},"background":{"description":"What the coach keeps in mind about them, or null. One person only. An empty string or null clears it.","type":["string","null"]},"bill_to":{"description":"Who their invoices are made out to, or null. One person only.","type":["string","null"]},"billing_email":{"description":"Where their invoices are sent, or null. One person only.","type":["string","null"]},"coming_up":{"description":"What is still ahead, soonest first: `meeting`, `follow_up`, `check_in_series` or `next_step`. `at` is an ISO datetime (a next step's a date) or null; `title` the meeting's session label or event title, a follow-up's text or subject, a step's body, null for a series; `detail` per kind. One person only.","items":{"properties":{"at":{"type":"string"},"detail":{"type":"object"},"id":{"type":"integer"},"kind":{"type":"string"},"title":{"type":"string"}},"type":"object"},"readOnly":true,"type":"array"},"days_in_stage":{"description":"Whole days since they entered their stage, in the coach's time zone. Null with no stage.","readOnly":true,"type":["integer","null"]},"due_on":{"description":"The day they are next due, in the coach's time zone. Null when untiered.","format":"date","readOnly":true,"type":"string"},"email":{"description":"Their primary email address.","type":"string"},"facebook_username":{"description":"Their Facebook username. A profile link is accepted and stored as the username.","type":"string"},"group_ids":{"description":"The ids of the groups they are in, in `groups`' order. Sent, it is their exact membership; an id that is not one of your groups is refused and nothing is written.","items":{"type":"integer"},"type":"array"},"groups":{"description":"The names of the groups they are in, A–Z. One person only.","items":{"type":"string"},"readOnly":true,"type":"array"},"id":{"description":"Throughway's identifier for this person.","readOnly":true,"type":"integer"},"last_touch":{"description":"The latest contact as `{kind, at}`, or null.","readOnly":true,"type":"object"},"linkedin_url":{"description":"Their LinkedIn profile, stored as `linkedin.com/in/…`. A profile link, `@name` or bare name is accepted; a company page or any other link is refused.","type":"string"},"look_for_transcripts":{"description":"Whether their meetings' transcripts are looked for. One person only.","type":"boolean"},"name":{"description":"The person's full name.","type":"string"},"next_steps":{"description":"Their open next steps, soonest due first. One person only, never in list rows.","items":{"properties":{"body":{"type":"string"},"done":{"type":"boolean"},"due_on":{"format":"date","type":"string"},"id":{"type":"integer"}},"type":"object"},"readOnly":true,"type":"array"},"notes":{"description":"Their last 3 notes, newest first. One person only, never in list rows.","items":{"properties":{"at":{"type":"string"},"body":{"type":"string"},"id":{"type":"integer"}},"type":"object"},"readOnly":true,"type":"array"},"notes_count":{"description":"How many notes they have in all. One person only.","readOnly":true,"type":"integer"},"organization":{"description":"Where they work.","type":"string"},"phone":{"description":"Their phone number, as written.","type":"string"},"phone_apps":{"description":"The apps their phone is also on, from `whatsapp` and `signal`; `[]` when none. Cleared with the phone.","items":{"enum":["whatsapp","signal"],"type":"string"},"type":"array"},"photo_url":{"description":"Their photo, an absolute URL, or null when they have none.","readOnly":true,"type":["string","null"]},"preferred_method":{"description":"The coach's preferred way to reach them, or null.","enum":["text","call","email","whatsapp","signal","linkedin","messenger",null],"type":["string","null"]},"snooze_until":{"description":"Held back until this day, or null.","format":"date","readOnly":true,"type":"string"},"source":{"description":"Where this person came from, e.g. `iPhone Contacts`, or null. One person only.","type":["string","null"]},"stage":{"description":"Their pipeline stage, or null when they are in the book only. One person only.","enum":["nurturing","in_conversation","chemistry_scheduled","deciding","onboarding","active","complete","not_a_fit",null],"readOnly":true,"type":["string","null"]},"tier":{"description":"How often to keep in touch: every_2_weeks, monthly, quarterly, twice_a_year or yearly. Null is untiered.","enum":["every_2_weeks","monthly","quarterly","twice_a_year","yearly",null],"type":["string","null"]},"timezone":{"description":"Their own time zone, e.g. `Europe/Lisbon`, or null. One person only.","type":["string","null"]},"title":{"description":"Their role, e.g. `COO`.","type":"string"},"updated_at":{"description":"When the person last changed.","format":"date-time","readOnly":true,"type":"string"},"ways_to_reach":{"description":"`{available, primary, preferred, preferred_available}`: the ways their details allow, the one to use first, the stored preference and whether it is available.","readOnly":true,"type":"object"}},"type":"object"},"PersonNote":{"description":"A note about a person.","properties":{"at":{"description":"When it happened.","format":"date-time","type":"string"},"body":{"description":"The note, plain text.","type":["string","null"]},"id":{"type":"integer"}},"type":"object"},"ReachOut":{"description":"The day's Reach out, as Today shows it.","properties":{"calendar":{"description":"Whether today's meetings could be read. `meetings` is empty unless `ok`.","enum":["ok","not_connected","unavailable"],"type":"string"},"date":{"description":"The day this is for.","format":"date","type":"string"},"due":{"description":"The day's three, most overdue first.","items":{"properties":{"due_label":{"description":"e.g. `due today`, `3 days late`.","type":"string"},"due_on":{"format":"date","type":"string"},"due_tone":{"enum":["neutral","warning","error"],"type":"string"},"last_note":{"description":"Their latest note, its text cut to 140 characters.","properties":{"at":{"format":"date-time","type":"string"},"excerpt":{"type":["string","null"]}},"type":["object","null"]},"person":{"$ref":"#/components/schemas/Person"}},"type":"object"},"type":"array"},"follow_up_texts":{"description":"The follow-up texts due by now, oldest first, waiting to be texted or skipped.","items":{"properties":{"body":{"description":"The message to send.","type":"string"},"due_at":{"format":"date-time","type":"string"},"id":{"type":"integer"},"person":{"$ref":"#/components/schemas/Person"},"session_label":{"description":"The session it follows, e.g. `Session 6`, or null.","type":["string","null"]}},"type":"object"},"type":"array"},"meetings":{"description":"Today's meetings with someone in the book, in start order.","items":{"properties":{"join_url":{"type":["string","null"]},"person":{"$ref":"#/components/schemas/Person"},"starts_at":{"format":"date-time","type":"string"},"title":{"type":["string","null"]}},"type":"object"},"type":"array"},"more":{"description":"How many more are due, rolling to the coming days.","type":"integer"},"next_steps":{"description":"The open next steps due by this day, oldest due first.","items":{"properties":{"body":{"type":"string"},"due_on":{"format":"date","type":"string"},"id":{"type":"integer"},"person":{"$ref":"#/components/schemas/Person"}},"type":"object"},"type":"array"}},"type":"object"},"Session":{"description":"A coaching session, call or meeting with a client — its notes, saved summary and transcript. Read-only.","properties":{"body":{"description":"Your notes from the session.","readOnly":true,"type":"string"},"client_id":{"description":"Which client the session was with.","readOnly":true,"type":"integer"},"ended_at":{"description":"When the session ended. Null while it is in progress.","format":"date-time","readOnly":true,"type":"string"},"id":{"description":"Throughway's identifier for this session.","readOnly":true,"type":"integer"},"inserted_at":{"description":"When the session was created.","format":"date-time","readOnly":true,"type":"string"},"kind":{"description":"What kind of session this was.","enum":["session","chemistry_call","imported","stakeholder_interview","meeting"],"readOnly":true,"type":"string"},"length_minutes":{"description":"How long the session was, in minutes. Null when no length is known yet.","readOnly":true,"type":"integer"},"started_at":{"description":"When the session started.","format":"date-time","readOnly":true,"type":"string"},"status":{"description":"Whether the session is still in progress or has ended.","enum":["in_progress","ended"],"readOnly":true,"type":"string"},"summary":{"description":"The session's saved summary.","readOnly":true,"type":"string"},"supervision":{"description":"Your auto supervision of this session, as Markdown: the write-up's summary, what worked and what is worth sitting with, with quotes. Null when you have no auto supervision of this session or it has no write-up yet. Omitted from list rows unless you pass include=supervision.","readOnly":true,"type":"string"},"transcript":{"description":"The transcript as plain text, or null. Omitted from list rows unless you pass include=transcript.","readOnly":true,"type":"string"},"transcript_entries":{"description":"The transcript as speaker-labelled turns, or null. Omitted from list rows unless you pass include=transcript.","items":{"properties":{"end_time":{"type":"string"},"speaker":{"type":"string"},"start_time":{"type":"string"},"text":{"type":"string"}},"type":"object"},"readOnly":true,"type":"array"},"updated_at":{"description":"When the session last changed.","format":"date-time","readOnly":true,"type":"string"}},"type":"object"},"TimelineEvent":{"description":"One thing that happened with a client. Every event carries the same six keys.","properties":{"at":{"description":"When it happened.","format":"date-time","type":"string"},"body":{"description":"The note's text. Non-null for `interaction` events only.","type":["string","null"]},"detail":{"description":"A small per-kind object, `{}` when there is nothing to add.","type":"object"},"id":{"description":"The record's id, or null when the event is not a row you can fetch.","type":["integer","null"]},"kind":{"description":"What kind of event this is, e.g. `interaction`, `session`.","type":"string"},"title":{"description":"A one-line heading for the event.","type":["string","null"]}},"type":"object"}},"securitySchemes":{"bearerAuth":{"scheme":"bearer","type":"http"}}},"info":{"description":"Read and change your coaching practice. Authenticate with an API key minted in Settings › Your AI.","title":"Throughway API","version":"1.0.0"},"openapi":"3.1.0","paths":{"/api/v1/people/{id}/done":{"post":{"operationId":"person_done","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{},"required":[],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Person"}}},"description":"Success."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"Log that you reached out: a \"Reached out\" note, so they are next due one interval from today."}},"/api/v1/people/{id}/photo":{"put":{"operationId":"set_person_photo","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"image/jpeg":{"schema":{"format":"binary","type":"string"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Person"}}},"description":"Success."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"415":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"Give a person a photo when they have none. The body is the JPEG itself (`Content-Type: image/jpeg`, at most 5 MB); a person who already has one answers 409 `photo_exists`."}},"/api/v1/people/{id}/archive":{"post":{"operationId":"archive_person","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{},"required":[],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Person"}}},"description":"Success."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"Archive a person: out of the book and off Today until unarchived. Already archived answers them unchanged."}},"/api/v1/next_steps/{id}":{"patch":{"operationId":"update_next_step","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"done":{"description":"true completes it; false reopens it.","type":"boolean"}},"required":["done"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NextStep"}}},"description":"Success."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"Mark a next step done, or reopen it."}},"/api/v1/people":{"get":{"operationId":"list_people","parameters":[{"description":"Case-insensitive substring over name, organization, title and every email address.","in":"query","name":"q","required":false,"schema":{"type":"string"}},{"description":"One tier: every_2_weeks, monthly, quarterly, twice_a_year, yearly, or none for the untiered.","in":"query","name":"tier","required":false,"schema":{"type":"string"}},{"description":"ISO 8601 — only people changed at or after this. Adds `deleted_ids`: the people deleted or archived since.","in":"query","name":"updated_since","required":false,"schema":{"type":"string"}},{"description":"The `next_cursor` from the previous page.","in":"query","name":"cursor","required":false,"schema":{"type":"string"}},{"description":"Page size. Defaults to 50, capped at 200.","in":"query","name":"limit","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Person"},"type":"array"},"next_cursor":{"description":"Pass as `cursor` for the next page.","type":["string","null"]}},"type":"object"}}},"description":"Success."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"The people book, A–Z by name. With `updated_since`, also `deleted_ids`: the people deleted or archived since then."},"post":{"operationId":"create_person","requestBody":{"content":{"application/json":{"schema":{"properties":{"background":{"description":"What the coach keeps in mind about them, or null. One person only. An empty string or null clears it.","type":["string","null"]},"bill_to":{"description":"Who their invoices are made out to, or null. One person only.","type":["string","null"]},"billing_email":{"description":"Where their invoices are sent, or null. One person only.","type":["string","null"]},"email":{"description":"Their primary email address.","type":"string"},"facebook_username":{"description":"Their Facebook username. A profile link is accepted and stored as the username.","type":"string"},"group_ids":{"description":"The ids of the groups they are in, in `groups`' order. Sent, it is their exact membership; an id that is not one of your groups is refused and nothing is written.","items":{"type":"integer"},"type":"array"},"linkedin_url":{"description":"Their LinkedIn profile, stored as `linkedin.com/in/…`. A profile link, `@name` or bare name is accepted; a company page or any other link is refused.","type":"string"},"look_for_transcripts":{"description":"Whether their meetings' transcripts are looked for. One person only.","type":"boolean"},"name":{"description":"The person's full name.","type":"string"},"organization":{"description":"Where they work.","type":"string"},"phone":{"description":"Their phone number, as written.","type":"string"},"phone_apps":{"description":"The apps their phone is also on, from `whatsapp` and `signal`; `[]` when none. Cleared with the phone.","items":{"enum":["whatsapp","signal"],"type":"string"},"type":"array"},"preferred_method":{"description":"The coach's preferred way to reach them, or null.","enum":["text","call","email","whatsapp","signal","linkedin","messenger",null],"type":["string","null"]},"source":{"description":"Where this person came from, e.g. `iPhone Contacts`, or null. One person only.","type":["string","null"]},"tier":{"description":"How often to keep in touch: every_2_weeks, monthly, quarterly, twice_a_year or yearly. Null is untiered.","enum":["every_2_weeks","monthly","quarterly","twice_a_year","yearly",null],"type":["string","null"]},"timezone":{"description":"Their own time zone, e.g. `Europe/Lisbon`, or null. One person only.","type":["string","null"]},"title":{"description":"Their role, e.g. `COO`.","type":"string"}},"required":["name"],"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Person"}}},"description":"Success."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"Add someone to the people book. They are not put on the board."}},"/api/v1/people/{id}/take_off_board":{"post":{"operationId":"take_person_off_board","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{},"required":[],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Person"}}},"description":"Success."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"Take a potential client off the pipeline board, keeping them in the book. Someone not on the board, or an active or past client, is 422 on `stage`."}},"/api/v1/notes/{id}":{"delete":{"operationId":"delete_note","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{},"required":[],"type":"object"}}},"required":true},"responses":{"204":{"description":"Success."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"Delete a note."},"patch":{"operationId":"update_note","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"body":{"description":"The note, plain text.","type":"string"}},"required":["body"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonNote"}}},"description":"Success."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"Change a note's text."}},"/api/v1/reach_out":{"get":{"operationId":"get_reach_out","parameters":[{"description":"YYYY-MM-DD, within a day of the coach's today. Defaults to today.","in":"query","name":"date","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReachOut"}}},"description":"Success."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"The day's three people to reach out to — the same three as Today, so either spends the day's slots — with today's meetings, the next steps due and the follow-up due texts."}},"/api/v1/groups":{"get":{"operationId":"list_groups","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Group"},"type":"array"}},"type":"object"}}},"description":"Success."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"Your groups, A–Z by name."},"post":{"operationId":"create_group","requestBody":{"content":{"application/json":{"schema":{"properties":{"name":{"description":"The group's name.","type":"string"}},"required":["name"],"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Group"}}},"description":"Success."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"Add a group. A blank name, or one you already have in any case, is 422 on `name`."}},"/api/v1/clients":{"get":{"operationId":"list_clients","parameters":[{"description":"One stage, or several comma-separated. Only clients in those stages are returned.","explode":false,"in":"query","name":"stage","required":false,"schema":{"items":{"enum":["nurturing","in_conversation","chemistry_scheduled","deciding","onboarding","active","complete"],"type":"string"},"type":"array"},"style":"form"},{"description":"Case-insensitive substring over name, email and organization.","in":"query","name":"q","required":false,"schema":{"type":"string"}},{"description":"ISO 8601 timestamp — only clients changed since then.","in":"query","name":"updated_since","required":false,"schema":{"type":"string"}},{"description":"Page size. Defaults to 50, capped at 200.","in":"query","name":"limit","required":false,"schema":{"type":"integer"}},{"description":"The `next_cursor` from the previous page.","in":"query","name":"cursor","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Client"},"type":"array"},"next_cursor":{"description":"Pass as `cursor` for the next page.","type":["string","null"]}},"type":"object"}}},"description":"Success."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"List clients, filtered and paginated."},"post":{"operationId":"create_client","requestBody":{"content":{"application/json":{"schema":{"properties":{"email":{"description":"The client's email address.","type":"string"},"name":{"description":"The client's full name, as you'd write it on a card.","type":"string"},"organization":{"description":"The organization the client works for.","type":"string"},"outcome_note":{"description":"How the engagement ended.","type":"string"},"red_flags":{"description":"Anything to watch out for.","type":"string"},"running_notes":{"description":"Your rolling notes on this client.","type":"string"},"source":{"description":"How this client came to you.","type":"string"},"stage":{"description":"Where the client sits in the pipeline. Changing it records a stage transition. Null means the person is in the book only, off the board.","enum":["nurturing","in_conversation","chemistry_scheduled","deciding","onboarding","active","complete"],"type":"string"},"timezone":{"description":"IANA time zone, e.g. `America/New_York`.","type":"string"}},"required":["name"],"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Client"}}},"description":"Success."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"Create a client."}},"/api/v1/loose_ends/{id}/ignore":{"post":{"operationId":"ignore_loose_end","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{},"required":[],"type":"object"}}},"required":true},"responses":{"204":{"description":"Success."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"Never suggest this address again."}},"/api/v1/people/{id}/snooze":{"post":{"operationId":"snooze_person","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"skip":{"description":"true skips them one interval of their tier from today. Needs a tier.","type":"boolean"},"until":{"description":"A day after today, YYYY-MM-DD.","format":"date","type":"string"}},"required":[],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Person"}}},"description":"Success."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"Hold a person back until a later day, or skip them till next time."}},"/api/v1/interactions":{"get":{"operationId":"list_interactions","parameters":[{"description":"Only this client's notes.","in":"query","name":"client_id","required":false,"schema":{"type":"integer"}},{"description":"One type, or several comma-separated: call, email, meeting, message, note.","explode":false,"in":"query","name":"type","required":false,"schema":{"items":{"enum":["call","email","meeting","message","note"],"type":"string"},"type":"array"},"style":"form"},{"description":"ISO 8601 — only notes that occurred at or after this.","in":"query","name":"occurred_since","required":false,"schema":{"type":"string"}},{"description":"Page size. Defaults to 50, capped at 200.","in":"query","name":"limit","required":false,"schema":{"type":"integer"}},{"description":"The `next_cursor` from the previous page.","in":"query","name":"cursor","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Interaction"},"type":"array"},"next_cursor":{"description":"Pass as `cursor` for the next page.","type":["string","null"]}},"type":"object"}}},"description":"Success."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"List logged notes, filtered and paginated. Newest logged first."},"post":{"operationId":"create_interaction","requestBody":{"content":{"application/json":{"schema":{"properties":{"client_id":{"description":"Which client this note is about. Set when you log it; an update cannot move it.","type":"integer"},"note":{"description":"The note itself, plain text, stored and returned exactly as you send it.","type":"string"},"occurred_at":{"description":"When it happened, ISO 8601. Omit it and you get now.","format":"date-time","type":"string"},"type":{"description":"What kind of contact this was.","enum":["call","email","meeting","message","note"],"type":"string"}},"required":["client_id","type"],"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Interaction"}}},"description":"Success."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"Log a note, call, meeting or message against a client."}},"/api/v1/captures/propose":{"post":{"operationId":"propose_capture","requestBody":{"content":{"application/json":{"schema":{"properties":{"context":{"description":"Optional. `person_id`: the person the note was started from, who is then the match. `calendar_event_id`: the meeting it follows (accepted, not yet used).","type":"object"},"transcript":{"description":"The note's transcript, plain text.","type":"string"}},"required":["transcript"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaptureProposal"}}},"description":"Success."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"Read a note's transcript and propose the person it is about — matched against the book or new — with a tier, a next step and the tidied note. Nothing is saved. Audio is never accepted."}},"/api/v1/clients/{id}/timeline":{"get":{"operationId":"get_client_timeline","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}},{"description":"How many events. Defaults to 50, capped at 200.","in":"query","name":"limit","required":false,"schema":{"type":"integer"}},{"description":"ISO 8601 — only events strictly earlier than this. A filter, not a cursor.","in":"query","name":"before","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/TimelineEvent"},"type":"array"},"has_more":{"description":"Whether more events matched than `limit` returned. Page with `before`, not a cursor.","type":"boolean"}},"type":"object"}}},"description":"Success."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"Everything that has happened with a client, newest first — notes, sessions, stage changes, emails, files."}},"/api/v1/follow_ups/{id}/texted":{"post":{"operationId":"mark_follow_up_texted","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{},"required":[],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"follow_up":{"properties":{"id":{"type":"integer"},"status":{"enum":["texted","skipped","cancelled"],"type":"string"}},"type":"object"}},"type":"object"}}},"description":"Success."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"Mark a due follow-up text as sent: a \"Texted\" note, which counts as reaching out. Already texted, skipped or cancelled answers its status as it stands."}},"/api/v1/people/{id}/follow_ups":{"post":{"operationId":"schedule_person_text","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"body":{"description":"The text to send.","type":"string"},"due_at":{"description":"When it is due, ISO 8601, in the future.","format":"date-time","type":"string"}},"required":["body","due_at"],"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Person"}}},"description":"Success."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"Schedule a text to a person, due at a later time. They need a phone on file."}},"/api/v1/loose_ends/{id}/add":{"post":{"operationId":"add_loose_end","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"tier":{"description":"every_2_weeks, monthly, quarterly, twice_a_year, yearly, or null for untiered.","enum":["every_2_weeks","monthly","quarterly","twice_a_year","yearly",null],"type":["string","null"]}},"required":[],"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Person"}}},"description":"Success."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"Add a suggested person to the people book, off the board, with a tier or none."}},"/api/v1/people/{id}/check_ins":{"post":{"operationId":"start_person_check_ins","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"every_days":{"description":"Every 1, 2 or 3 days. Defaults to 2.","type":"integer"},"prompt":{"description":"What each check-in should ask about; the AI drafts the text from it.","type":"string"}},"required":["prompt"],"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Person"}}},"description":"Success."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"Start AI-drafted check-in texts at 9:00, until their next session or two weeks out. One open series per person; they need a phone on file."}},"/api/v1/follow_ups/{id}/skip":{"post":{"operationId":"skip_follow_up","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{},"required":[],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"follow_up":{"properties":{"id":{"type":"integer"},"status":{"enum":["texted","skipped","cancelled"],"type":"string"}},"type":"object"}},"type":"object"}}},"description":"Success."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"Skip a due follow-up text, logging nothing. Already texted, skipped or cancelled answers its status as it stands."}},"/api/v1/people/{id}/timeline":{"get":{"operationId":"get_person_timeline","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}},{"description":"How many events. Defaults to 50, capped at 200.","in":"query","name":"limit","required":false,"schema":{"type":"integer"}},{"description":"ISO 8601 — only events strictly earlier than this. A filter, not a cursor.","in":"query","name":"before","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/TimelineEvent"},"type":"array"},"has_more":{"description":"Whether more events matched than `limit` returned. Page with `before`, not a cursor.","type":"boolean"}},"type":"object"}}},"description":"Success."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"What has happened with a person, newest first — notes, sessions, emails, failed follow-ups. Nothing still ahead: that is the person's `coming_up`."}},"/api/v1/people/{id}/notes":{"get":{"operationId":"list_person_notes","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}},{"description":"Page size. Defaults to 50, capped at 200.","in":"query","name":"limit","required":false,"schema":{"type":"integer"}},{"description":"The `next_cursor` from the previous page.","in":"query","name":"cursor","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/PersonNote"},"type":"array"},"next_cursor":{"description":"Pass as `cursor` for the next page.","type":["string","null"]}},"type":"object"}}},"description":"Success."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"A person's notes, newest logged first."},"post":{"operationId":"create_person_note","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"body":{"description":"The note, plain text.","type":"string"}},"required":["body"],"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonNote"}}},"description":"Success."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"Log a note about a person."}},"/api/v1/people/{id}/tier":{"put":{"operationId":"set_person_tier","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"tier":{"description":"every_2_weeks, monthly, quarterly, twice_a_year, yearly, or null for untiered.","enum":["every_2_weeks","monthly","quarterly","twice_a_year","yearly",null],"type":["string","null"]}},"required":["tier"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Person"}}},"description":"Success."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"Set how often to keep in touch, or clear it with null."}},"/api/v1/people/{id}":{"delete":{"operationId":"delete_person","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{},"required":[],"type":"object"}}},"required":true},"responses":{"204":{"description":"Success."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"Delete a person and everything about them. A delta sync then lists them in `deleted_ids`."},"get":{"operationId":"get_person","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Person"}}},"description":"Success."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"One person, with their open next steps, last 3 notes and how many notes they have."},"patch":{"operationId":"update_person","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"background":{"description":"What the coach keeps in mind about them, or null. One person only. An empty string or null clears it.","type":["string","null"]},"bill_to":{"description":"Who their invoices are made out to, or null. One person only.","type":["string","null"]},"billing_email":{"description":"Where their invoices are sent, or null. One person only.","type":["string","null"]},"email":{"description":"Their primary email address.","type":"string"},"facebook_username":{"description":"Their Facebook username. A profile link is accepted and stored as the username.","type":"string"},"group_ids":{"description":"The ids of the groups they are in, in `groups`' order. Sent, it is their exact membership; an id that is not one of your groups is refused and nothing is written.","items":{"type":"integer"},"type":"array"},"linkedin_url":{"description":"Their LinkedIn profile, stored as `linkedin.com/in/…`. A profile link, `@name` or bare name is accepted; a company page or any other link is refused.","type":"string"},"look_for_transcripts":{"description":"Whether their meetings' transcripts are looked for. One person only.","type":"boolean"},"name":{"description":"The person's full name.","type":"string"},"organization":{"description":"Where they work.","type":"string"},"phone":{"description":"Their phone number, as written.","type":"string"},"phone_apps":{"description":"The apps their phone is also on, from `whatsapp` and `signal`; `[]` when none. Cleared with the phone.","items":{"enum":["whatsapp","signal"],"type":"string"},"type":"array"},"preferred_method":{"description":"The coach's preferred way to reach them, or null.","enum":["text","call","email","whatsapp","signal","linkedin","messenger",null],"type":["string","null"]},"source":{"description":"Where this person came from, e.g. `iPhone Contacts`, or null. One person only.","type":["string","null"]},"tier":{"description":"How often to keep in touch: every_2_weeks, monthly, quarterly, twice_a_year or yearly. Null is untiered.","enum":["every_2_weeks","monthly","quarterly","twice_a_year","yearly",null],"type":["string","null"]},"timezone":{"description":"Their own time zone, e.g. `Europe/Lisbon`, or null. One person only.","type":["string","null"]},"title":{"description":"Their role, e.g. `COO`.","type":"string"}},"required":[],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Person"}}},"description":"Success."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"Change a person's details. Only the fields you send change."}},"/api/v1/people/{id}/unarchive":{"post":{"operationId":"unarchive_person","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{},"required":[],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Person"}}},"description":"Success."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"Bring an archived person back into the book."}},"/api/v1/documents/{id}":{"delete":{"operationId":"delete_document","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"deleted":{"enum":[true],"type":"boolean"},"id":{"description":"The id of the record just deleted.","type":"integer"}},"required":["deleted","id"],"type":"object"}}},"description":"Success."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"Remove it from the client. A Google Doc goes to the coach's Drive trash."},"get":{"operationId":"get_document","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Document"}}},"description":"Success."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"One document, with its body as Markdown."},"patch":{"operationId":"update_document","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"body":{"description":"Markdown. Converted to HTML for a page and to Google Docs formatting for a Google Doc. An update replaces the whole body; there is no append. Null for a file, a link, or a Google Doc Throughway can't reach. Never in list rows.","type":"string"},"title":{"description":"For a Google Doc, also its name in Drive.","type":"string"}},"required":[],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Document"}}},"description":"Success."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"Rename it, replace its body, or both."}},"/api/v1/documents":{"get":{"operationId":"list_documents","parameters":[{"description":"Required. Only this client's documents.","in":"query","name":"client_id","required":false,"schema":{"type":"integer"}},{"description":"One kind, or several comma-separated: page, google_doc, file, link.","explode":false,"in":"query","name":"kind","required":false,"schema":{"items":{"enum":["page","google_doc","file","link"],"type":"string"},"type":"array"},"style":"form"},{"description":"Page size. Defaults to 50, capped at 200.","in":"query","name":"limit","required":false,"schema":{"type":"integer"}},{"description":"The `next_cursor` from the previous page.","in":"query","name":"cursor","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Document"},"type":"array"},"next_cursor":{"description":"Pass as `cursor` for the next page.","type":["string","null"]}},"type":"object"}}},"description":"Success."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"A client's documents, newest first. Metadata only, no bodies."},"post":{"operationId":"create_document","requestBody":{"content":{"application/json":{"schema":{"properties":{"body":{"description":"Markdown. Converted to HTML for a page and to Google Docs formatting for a Google Doc. An update replaces the whole body; there is no append. Null for a file, a link, or a Google Doc Throughway can't reach. Never in list rows.","type":"string"},"client_id":{"description":"Which client it belongs to. An update can't move it.","type":"integer"},"kind":{"description":"page and google_doc are writable. A list also shows file and link, read-only.","enum":["page","google_doc","file","link"],"type":"string"},"title":{"description":"For a Google Doc, also its name in Drive.","type":"string"}},"required":["client_id","kind","title"],"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Document"}}},"description":"Success."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"A new page, or a new Google Doc in the client's Drive folder."}},"/api/v1/loose_ends":{"get":{"operationId":"list_loose_ends","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/LooseEnd"},"type":"array"}},"type":"object"}}},"description":"Success."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"The people you met or wrote to who aren't in the book yet, waiting to be added or ignored."}},"/api/v1/sessions/{id}":{"get":{"operationId":"get_session","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Session"}}},"description":"Success."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"Fetch one session, transcript and your auto supervision included."}},"/api/v1/clients/{id}":{"get":{"operationId":"get_client","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Client"}}},"description":"Success."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"Fetch one client."},"patch":{"operationId":"update_client","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"email":{"description":"The client's email address.","type":"string"},"name":{"description":"The client's full name, as you'd write it on a card.","type":"string"},"organization":{"description":"The organization the client works for.","type":"string"},"outcome_note":{"description":"How the engagement ended.","type":"string"},"red_flags":{"description":"Anything to watch out for.","type":"string"},"running_notes":{"description":"Your rolling notes on this client.","type":"string"},"source":{"description":"How this client came to you.","type":"string"},"stage":{"description":"Where the client sits in the pipeline. Changing it records a stage transition. Null means the person is in the book only, off the board.","enum":["nurturing","in_conversation","chemistry_scheduled","deciding","onboarding","active","complete"],"type":"string"},"timezone":{"description":"IANA time zone, e.g. `America/New_York`.","type":"string"}},"required":[],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Client"}}},"description":"Success."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"Update a client. Only the fields you send change."}},"/api/v1/people/{id}/next_steps":{"post":{"operationId":"create_next_step","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"body":{"description":"What to do.","type":"string"},"due_on":{"description":"When, YYYY-MM-DD. Optional.","format":"date","type":"string"}},"required":["body"],"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NextStep"}}},"description":"Success."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"Add a next step for a person."}},"/api/v1/interactions/{id}":{"delete":{"operationId":"delete_interaction","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"deleted":{"enum":[true],"type":"boolean"},"id":{"description":"The id of the record just deleted.","type":"integer"}},"required":["deleted","id"],"type":"object"}}},"description":"Success."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"Delete a logged note."},"get":{"operationId":"get_interaction","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Interaction"}}},"description":"Success."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"Fetch one logged note."},"patch":{"operationId":"update_interaction","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"note":{"description":"The note itself, plain text, stored and returned exactly as you send it.","type":"string"},"occurred_at":{"description":"When it happened, ISO 8601. Omit it and you get now.","format":"date-time","type":"string"},"type":{"description":"What kind of contact this was.","enum":["call","email","meeting","message","note"],"type":"string"}},"required":[],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Interaction"}}},"description":"Success."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"Update a logged note. Only the fields you send change; it cannot be moved to another client."}},"/api/v1/sessions":{"get":{"operationId":"list_sessions","parameters":[{"description":"Only this client's sessions.","in":"query","name":"client_id","required":false,"schema":{"type":"integer"}},{"description":"One kind, or several comma-separated: session, chemistry_call, imported, stakeholder_interview, meeting.","explode":false,"in":"query","name":"kind","required":false,"schema":{"items":{"enum":["session","chemistry_call","imported","stakeholder_interview","meeting"],"type":"string"},"type":"array"},"style":"form"},{"description":"ISO 8601 — only sessions that started at or after this.","in":"query","name":"started_since","required":false,"schema":{"type":"string"}},{"description":"ISO 8601 — only sessions that started strictly before this.","in":"query","name":"started_before","required":false,"schema":{"type":"string"}},{"description":"transcript adds transcript and transcript_entries to each row; supervision adds supervision.","explode":false,"in":"query","name":"include","required":false,"schema":{"items":{"enum":["transcript","supervision"],"type":"string"},"type":"array"},"style":"form"},{"description":"Page size. Defaults to 50, capped at 200.","in":"query","name":"limit","required":false,"schema":{"type":"integer"}},{"description":"The `next_cursor` from the previous page.","in":"query","name":"cursor","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Session"},"type":"array"},"next_cursor":{"description":"Pass as `cursor` for the next page.","type":["string","null"]}},"type":"object"}}},"description":"Success."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An error."}},"summary":"List sessions, filtered and paginated. Newest created first. Transcripts and your auto supervision are left out unless you ask for them."}}},"security":[{"bearerAuth":[]}],"servers":[{"url":"https://staging.throughway.app"}]}