{"openapi":"3.1.0","info":{"title":"Agōn API","version":"1.0.0","description":"Prayer lists, requests, and sharing for Agōn (agon1230.com). Every call acts as the man who owns the token, and sees exactly what he may see: his own lists and requests, his cohorts' lists, and what brothers shared with him."},"servers":[{"url":"https://agon1230.com"}],"components":{"securitySchemes":{"bearerToken":{"type":"http","scheme":"bearer","description":"An app session (aga_…, from /v1/auth/…: every scope plus \"account\"), or a personal API token (agp_…) made in the member portal with chosen scopes: prayer:read/write, shares:read/write, disciplines:read/write, reminders:read/write."}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","properties":{"code":{"enum":["unauthorized","insufficient_scope","forbidden","not_found","invalid","invalid_json","rate_limited","server_error"]},"message":{"type":"string"}}}}},"List":{"type":"object","properties":{"id":{"type":"integer"},"kind":{"enum":["personal","cohort"]},"name":{"type":"string"},"cohort":{"type":["object","null"],"properties":{"id":{"type":"integer"},"label":{"type":"string"}}},"mine":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"}}},"Request":{"type":"object","properties":{"id":{"type":"integer"},"list_id":{"type":["integer","null"],"description":"The list it was put on through the API (null for older cohort requests from Slack or the portal)"},"external_id":{"type":["string","null"],"description":"Your key for idempotent upserts (only shown on your own requests)"},"author":{"type":["object","null"],"properties":{"user_id":{"type":"integer"},"name":{"type":["string","null"]}}},"subject":{"type":["object","null"],"properties":{"id":{"type":"integer"},"name":{"type":"string"}},"description":"Who or what it's for, on his own lists"},"tags":{"type":"array","items":{"type":"string"},"description":"urgent, praise, long-term, or his own"},"update_count":{"type":"integer"},"latest_update":{"type":["object","null"],"properties":{"body":{"type":"string"},"created_at":{"type":"string","format":"date-time"}}},"mine":{"type":"boolean"},"kind":{"enum":["request","praise"]},"title":{"type":["string","null"]},"body":{"type":["string","null"],"description":"Null on a brother's unspoken request"},"for_name":{"type":"string"},"unspoken":{"type":"boolean"},"visibility":{"enum":["private","cohort","captain"],"description":"private: you (and whoever you share it with); cohort: the men of its cohorts; captain: its cohort's captain only"},"status":{"enum":["active","answered","archived"]},"answered_at":{"type":["string","null"],"format":"date-time"},"answer_note":{"type":["string","null"]},"cohorts":{"type":"array","items":{"type":"integer"},"description":"Cohorts whose list it is on"},"prayed_count":{"type":"integer","description":"Times prayed for that you can see: your own, or everyone's on your request"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"RequestInput":{"type":"object","description":"A title or a body is required.","properties":{"title":{"type":["string","null"],"maxLength":140},"body":{"type":["string","null"],"maxLength":2000},"for_name":{"type":["string","null"],"maxLength":100,"description":"Who it's for (default: your first name)"},"kind":{"enum":["request","praise"],"default":"request"},"unspoken":{"type":"boolean","default":false},"visibility":{"enum":["private","cohort","captain"],"description":"Personal list: private. Cohort list: cohort (default) or captain."},"tags":{"type":"array","items":{"type":"string"},"description":"urgent, praise, long-term, or his own (lowercase)"},"subject_id":{"type":["integer","null"],"description":"A subject on the same list (his own lists)"},"list_id":{"type":"integer","description":"PATCH only: move his request to another of his own lists"}},"additionalProperties":false},"Share":{"type":"object","properties":{"id":{"type":"integer"},"resource_type":{"enum":["request","list"]},"resource_id":{"type":"integer"},"target_type":{"enum":["user","cohort"]},"target_id":{"type":"integer"},"granted_by":{"type":"integer"},"created_at":{"type":"string","format":"date-time"}}}}},"paths":{"/v1/openapi.json":{"get":{"operationId":"getOpenApi","summary":"This document","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/v1/auth/email/start":{"post":{"operationId":"startEmailSignIn","summary":"Email a 6-digit sign-in code (the same answer whether or not the email has an account)","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email"],"properties":{"email":{"type":"string","format":"email"}}}}}},"responses":{"202":{"description":"Sent (if the address can receive it)","content":{"application/json":{"schema":{"type":"object","properties":{"sent":{"const":true}}}}}},"422":{"description":"Not an email address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many attempts from this address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/auth/email/verify":{"post":{"operationId":"verifyEmailSignIn","summary":"Trade the code for an app session. A new email becomes a new account.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email","code"],"properties":{"email":{"type":"string","format":"email"},"code":{"type":"string","pattern":"^[0-9]{6}$"},"name":{"type":"string","description":"For a new account"},"timezone":{"type":"string","description":"IANA zone, for a new account"},"device":{"type":"string"}}}}}},"responses":{"200":{"description":"Signed in","content":{"application/json":{"schema":{"allOf":[{"type":"object","properties":{"access_token":{"type":"string","description":"aga_…, good for expires_in seconds"},"token_type":{"const":"Bearer"},"expires_in":{"type":"integer"},"refresh_token":{"type":"string","description":"agr_…; rotates on every refresh"}}},{"type":"object","properties":{"user":{"type":"object"},"new_user":{"type":"boolean"}}}]}}}},"401":{"description":"Wrong, used, or expired code","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many attempts from this address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/auth/refresh":{"post":{"operationId":"refreshSession","summary":"Trade a refresh token for a new access and refresh token (the old refresh token stops working)","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["refresh_token"],"properties":{"refresh_token":{"type":"string"}}}}}},"responses":{"200":{"description":"Refreshed","content":{"application/json":{"schema":{"type":"object","properties":{"access_token":{"type":"string","description":"aga_…, good for expires_in seconds"},"token_type":{"const":"Bearer"},"expires_in":{"type":"integer"},"refresh_token":{"type":"string","description":"agr_…; rotates on every refresh"}}}}}},"401":{"description":"Sign in again","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many attempts from this address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/auth/providers":{"get":{"operationId":"getSignInProviders","summary":"Which sign-in options this server offers, and the public Google client ids the app needs","security":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"object","properties":{"enabled":{"type":"boolean"}}},"apple":{"type":"object","properties":{"enabled":{"type":"boolean"}}},"slack":{"type":"object","properties":{"enabled":{"type":"boolean"}}},"google":{"type":"object","properties":{"enabled":{"type":"boolean"},"ios_client_id":{"type":["string","null"]},"web_client_id":{"type":["string","null"]},"android_client_id":{"type":["string","null"]}}}}}}}}}}},"/v1/auth/apple":{"post":{"operationId":"signInWithApple","summary":"Trade an Apple identity token for an app session. Matched by Apple ID, then by Apple-verified email; a new email becomes a new account. A \"Hide My Email\" relay address is never matched to an existing account: sign in with your email and link Apple from Me.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["identity_token"],"properties":{"identity_token":{"type":"string","description":"ASAuthorizationAppleIDCredential.identityToken (a JWT)"},"authorization_code":{"type":"string","description":"ASAuthorizationAppleIDCredential.authorizationCode: traded for a refresh token so deleting his account can revoke it with Apple"},"nonce":{"type":"string","description":"The raw nonce, if the app passed its SHA-256 to Apple"},"name":{"type":"string","description":"For a new account (Apple shares his name only the first time)"},"timezone":{"type":"string","description":"IANA zone, for a new account"},"device":{"type":"string"}}}}}},"responses":{"200":{"description":"Signed in","content":{"application/json":{"schema":{"allOf":[{"type":"object","properties":{"access_token":{"type":"string","description":"aga_…, good for expires_in seconds"},"token_type":{"const":"Bearer"},"expires_in":{"type":"integer"},"refresh_token":{"type":"string","description":"agr_…; rotates on every refresh"}}},{"type":"object","properties":{"user":{"type":"object"},"new_user":{"type":"boolean"},"private_email":{"type":"boolean","description":"Apple gave a private relay address"}}}]}}}},"401":{"description":"Apple didn't vouch for this token (signature, issuer, audience, expiry, or nonce)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"link_required: an account already has this relay address; sign in by email and link Apple from Me","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"no_email: Apple shared no email and this Apple ID isn't linked yet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many attempts from this address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Apple's keys couldn't be fetched","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/auth/google":{"post":{"operationId":"signInWithGoogle","summary":"Trade a Google ID token for an app session. Matched by Google account, then by Google-verified email; a new email becomes a new account.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["id_token"],"properties":{"id_token":{"type":"string","description":"The ID token (a JWT) issued to one of this server's Google client ids"},"name":{"type":"string"},"timezone":{"type":"string","description":"IANA zone, for a new account"},"device":{"type":"string"}}}}}},"responses":{"200":{"description":"Signed in","content":{"application/json":{"schema":{"allOf":[{"type":"object","properties":{"access_token":{"type":"string","description":"aga_…, good for expires_in seconds"},"token_type":{"const":"Bearer"},"expires_in":{"type":"integer"},"refresh_token":{"type":"string","description":"agr_…; rotates on every refresh"}}},{"type":"object","properties":{"user":{"type":"object"},"new_user":{"type":"boolean"}}}]}}}},"401":{"description":"Google didn't vouch for this token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Google sign-in isn't set up on this server","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"no_email: the Google email isn't verified","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many attempts from this address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Google's keys couldn't be fetched","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/auth/slack/start":{"get":{"operationId":"startSlackSignIn","summary":"Open this in a browser auth session: it redirects to Slack (OpenID Connect, with state and PKCE). Only the Agōn workspace can sign in.","security":[],"parameters":[{"name":"return_to","in":"query","required":true,"schema":{"type":"string"},"description":"Where to send him back: agon://… or this server's /app/… page. Gets ?code=agx_… on success, or ?error=…&message=…"},{"name":"code_challenge","in":"query","required":true,"schema":{"type":"string"},"description":"base64url(SHA-256(code_verifier)); the exchange must present the verifier"}],"responses":{"302":{"description":"To Slack"},"404":{"description":"Slack sign-in isn't set up on this server"},"422":{"description":"return_to or code_challenge is invalid"},"429":{"description":"Too many attempts from this address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/auth/slack/callback":{"get":{"operationId":"slackSignInCallback","summary":"Slack's redirect back to this server (not called by the app). Redirects to return_to with a one-time code (2 minutes) or an error.","security":[],"parameters":[{"name":"code","in":"query","schema":{"type":"string"}},{"name":"state","in":"query","schema":{"type":"string"}},{"name":"error","in":"query","schema":{"type":"string"}}],"responses":{"302":{"description":"Back to the app"},"400":{"description":"Unknown, expired, or reused state"},"429":{"description":"Too many attempts from this address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/auth/slack/exchange":{"post":{"operationId":"exchangeSlackSignIn","summary":"Trade the one-time code from the Slack redirect (and the PKCE verifier) for an app session","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["code","code_verifier"],"properties":{"code":{"type":"string","description":"agx_…"},"code_verifier":{"type":"string","minLength":43},"timezone":{"type":"string","description":"IANA zone, for a new account"},"device":{"type":"string"}}}}}},"responses":{"200":{"description":"Signed in","content":{"application/json":{"schema":{"allOf":[{"type":"object","properties":{"access_token":{"type":"string","description":"aga_…, good for expires_in seconds"},"token_type":{"const":"Bearer"},"expires_in":{"type":"integer"},"refresh_token":{"type":"string","description":"agr_…; rotates on every refresh"}}},{"type":"object","properties":{"user":{"type":"object"},"new_user":{"type":"boolean"}}}]}}}},"401":{"description":"Wrong, used, or expired code, or the verifier doesn't match","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many attempts from this address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/auth/logout":{"post":{"operationId":"logout","summary":"End this app session","security":[{"bearerToken":["account"]}],"responses":{"204":{"description":"Signed out"},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not an app session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/me":{"patch":{"operationId":"updateMe","summary":"Change his name or time zone","security":[{"bearerToken":["account"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":100},"timezone":{"type":"string"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"user":{"type":"object"}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not an app session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deleteMe","summary":"Delete his account: his own data goes; cohort and billing history stays with the program","security":[{"bearerToken":["account"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["confirm"],"properties":{"confirm":{"const":"DELETE"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"const":true},"memberships":{"type":"integer"}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not an app session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Not confirmed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"operationId":"getMe","summary":"The token's man: his account, the token's scopes, and his cohorts with their lists and brothers","security":[{"bearerToken":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"user":{"type":"object","properties":{"id":{"type":"integer"},"email":{"type":"string"},"name":{"type":"string"},"timezone":{"type":"string"}}},"token":{"type":"object","properties":{"scopes":{"type":"array","items":{"type":"string"}}}},"cohorts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"label":{"type":"string"},"code":{"type":"string"},"lifecycle":{"type":"string"},"list_id":{"type":["integer","null"]},"brothers":{"type":"array","items":{"type":"object","properties":{"user_id":{"type":"integer"},"name":{"type":"string"}}}}}}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/me/link/apple":{"post":{"operationId":"linkApple","summary":"Link an Apple ID to his account, so Sign in with Apple finds it (the way in for a \"Hide My Email\" Apple ID)","security":[{"bearerToken":["account"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["identity_token"],"properties":{"identity_token":{"type":"string"},"nonce":{"type":"string"},"authorization_code":{"type":"string"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"user":{"type":"object"},"linked":{"const":"apple"}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not an app session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"That Apple ID signs in to another account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/me/tools":{"put":{"operationId":"setTools","summary":"Choose his tools (prayer, people, journal, reading: Scripture plans, routines, doors: Eight Doors, examen, and 1230: all in, the 12:30+1) and up to three favorites for his bottom bar","security":[{"bearerToken":["account"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["tools"],"properties":{"tools":{"type":"array","items":{"enum":["prayer","people","journal","1230","reading","routines","doors","examen"]}},"favorites":{"type":["array","null"],"maxItems":3,"items":{"type":"string"},"description":"In order; null: the first three of his tools. Omit to keep them"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"user":{"type":"object"}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not an app session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/home/cohort-invite":{"get":{"operationId":"cohortInvite","summary":"Whether to invite him to a cohort: after a 21-day streak on his own 12:30+1, if he has never been in one (or led one). \"Not now\" puts it away until his streak doubles","security":[{"bearerToken":["account"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"show":{"type":"boolean"},"streak":{"type":"integer"}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/home/cohort-invite/dismiss":{"post":{"operationId":"dismissCohortInvite","summary":"\"Not now\" on the cohort invitation","security":[{"bearerToken":["account"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/home":{"get":{"operationId":"getHome","summary":"Home: one card per tool he uses, with today's one useful thing","security":[{"bearerToken":["account"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"today":{"type":"string","format":"date"},"tools":{"type":"array","items":{"type":"string"}},"cards":{"type":"object","description":"Keyed by tool: 1230, prayer, people, journal"}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not an app session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/me/export":{"get":{"operationId":"exportMyData","summary":"Everything that's yours, as JSON","security":[{"bearerToken":["account"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not an app session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/pillars":{"get":{"operationId":"getPillars","summary":"Scripture and a short why for each pillar of the 12:30+1","security":[{"bearerToken":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"roof":{"type":"object"},"pillars":{"type":"array","items":{"type":"object"}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/library":{"get":{"operationId":"getLibrary","summary":"The pick list of disciplines for each pillar","security":[{"bearerToken":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"pillars":{"type":"array","items":{"type":"object"}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/rule":{"get":{"operationId":"getRule","summary":"His personal 12:30+1, and whether a cohort season is where his account goes now","security":[{"bearerToken":["disciplines:read"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"disciplines":{"type":"array","items":{"type":"object","required":["pillar","title","cadence"],"properties":{"pillar":{"enum":["heart","soul","mind","strength","neighbor"]},"title":{"type":"string","maxLength":200},"cadence":{"enum":["daily","weekly"]},"weekly_target":{"type":"integer","minimum":1,"maximum":7},"days_mask":{"type":"integer","minimum":1,"maximum":127,"description":"Dailies: which days (bit 0 = Monday … bit 6 = Sunday); 127 = every day"},"link":{"enum":["prayer","people","journal","examen","neighbors",null],"description":"Using this tool keeps the discipline: a prayer time, checking off a People reminder, writing in the Journal, praying the Examen, or connecting with one of his Eight Doors"}}}},"since":{"type":["string","null"],"format":"date"},"today":{"type":"string","format":"date"},"season":{"type":["object","null"]}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"operationId":"setRule","summary":"Set his personal 12:30+1 (at least 5, every pillar, 2+ daily). Unchanged disciplines carry on; changed ones end yesterday.","security":[{"bearerToken":["disciplines:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["disciplines"],"properties":{"disciplines":{"type":"array","items":{"type":"object","required":["pillar","title","cadence"],"properties":{"pillar":{"enum":["heart","soul","mind","strength","neighbor"]},"title":{"type":"string","maxLength":200},"cadence":{"enum":["daily","weekly"]},"weekly_target":{"type":"integer","minimum":1,"maximum":7},"days_mask":{"type":"integer","minimum":1,"maximum":127,"description":"Dailies: which days (bit 0 = Monday … bit 6 = Sunday); 127 = every day"},"link":{"enum":["prayer","people","journal","examen","neighbors",null],"description":"Using this tool keeps the discipline: a prayer time, checking off a People reminder, writing in the Journal, praying the Examen, or connecting with one of his Eight Doors"}}}}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"disciplines":{"type":"array","items":{"type":"object","required":["pillar","title","cadence"],"properties":{"pillar":{"enum":["heart","soul","mind","strength","neighbor"]},"title":{"type":"string","maxLength":200},"cadence":{"enum":["daily","weekly"]},"weekly_target":{"type":"integer","minimum":1,"maximum":7},"days_mask":{"type":"integer","minimum":1,"maximum":127,"description":"Dailies: which days (bit 0 = Monday … bit 6 = Sunday); 127 = every day"},"link":{"enum":["prayer","people","journal","examen","neighbors",null],"description":"Using this tool keeps the discipline: a prayer time, checking off a People reminder, writing in the Journal, praying the Examen, or connecting with one of his Eight Doors"}}}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Not a valid 12:30+1","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/disciplines":{"get":{"operationId":"getDay","summary":"His disciplines for a day: due, kept or missed, effort, weekly progress, streak","security":[{"bearerToken":["disciplines:read"]}],"parameters":[{"name":"date","in":"query","schema":{"type":"string"},"description":"YYYY-MM-DD, \"today\" (default), or \"yesterday\""}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","description":"One day of his personal rule","properties":{"date":{"type":"string","format":"date"},"is_today":{"type":"boolean"},"writable":{"type":"boolean","description":"Open for giving account (today, and yesterday until 9am his time)"},"open_days":{"type":"array","items":{"type":"object"}},"account_given":{"type":"boolean"},"still_unset":{"type":"array","items":{"type":"integer"}},"streak":{"type":"integer"},"disciplines":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"title":{"type":"string"},"pillar":{"type":"string"},"cadence":{"type":"string"},"due":{"type":["boolean","null"]},"status":{"enum":["kept","missed","not_set","not_logged"]},"effort":{"enum":["easy","fight","barely",null]},"this_week":{"type":"object"}}}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Bad date","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/disciplines/{id}/status/{date}":{"put":{"operationId":"setStatus","summary":"Kept or missed (with effort) for one discipline on an open day. When every due daily has a status, the day's account is given.","security":[{"bearerToken":["disciplines:write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Discipline id","schema":{"type":"integer","minimum":1}},{"name":"date","in":"path","required":true,"schema":{"type":"string"},"description":"YYYY-MM-DD, \"today\", or \"yesterday\""}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"enum":["kept","missed"]},"effort":{"enum":["easy","fight","barely"],"default":"easy"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"date":{"type":"string"},"updated":{"type":"array","items":{"type":"object"}},"skipped":{"type":"array","items":{"type":"object"}},"account_given":{"type":"boolean"},"just_given":{"type":"boolean"},"still_unset":{"type":"array","items":{"type":"object"}},"streak":{"type":"integer"}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A cohort season is where his account goes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Closed day, or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/streak":{"get":{"operationId":"getStreak","summary":"His streak, and his last days: due, kept, given, still open","security":[{"bearerToken":["disciplines:read"]}],"parameters":[{"name":"days","in":"query","schema":{"type":"integer","minimum":1,"maximum":60,"default":14}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"streak":{"type":"object","properties":{"current":{"type":"integer"},"best":{"type":"integer"}}},"days":{"type":"array","items":{"type":"object"}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/reminders":{"get":{"operationId":"listReminders","summary":"The people he means to reach out to, soonest first","security":[{"bearerToken":["reminders:read"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"reminders":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"person":{"type":"string"},"cadence_days":{"type":"integer"},"next_due":{"type":"string","format":"date"},"note":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"},"contact":{"type":["object","null"],"properties":{"ref":{"type":"string"},"name":{"type":["string","null"]}}}}}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createReminder","summary":"Add someone to reach out to, every cadence_days","security":[{"bearerToken":["reminders:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"type":"object","properties":{"person":{"type":"string","maxLength":100},"cadence_days":{"type":"integer","minimum":1,"maximum":366},"next_due":{"type":"string","format":"date"},"note":{"type":["string","null"],"maxLength":500}}},{"required":["person","cadence_days"]}]}}}},"responses":{"201":{"description":"Added","content":{"application/json":{"schema":{"type":"object","properties":{"reminder":{"type":"object","properties":{"id":{"type":"integer"},"person":{"type":"string"},"cadence_days":{"type":"integer"},"next_due":{"type":"string","format":"date"},"note":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"},"contact":{"type":["object","null"],"properties":{"ref":{"type":"string"},"name":{"type":["string","null"]}}}}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/reminders/{id}":{"patch":{"operationId":"updateReminder","summary":"Change a reminder","security":[{"bearerToken":["reminders:write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Reminder id","schema":{"type":"integer","minimum":1}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"person":{"type":"string","maxLength":100},"cadence_days":{"type":"integer","minimum":1,"maximum":366},"next_due":{"type":"string","format":"date"},"note":{"type":["string","null"],"maxLength":500}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"reminder":{"type":"object","properties":{"id":{"type":"integer"},"person":{"type":"string"},"cadence_days":{"type":"integer"},"next_due":{"type":"string","format":"date"},"note":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"},"contact":{"type":["object","null"],"properties":{"ref":{"type":"string"},"name":{"type":["string","null"]}}}}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"archiveReminder","summary":"Stop reminding him about this person","security":[{"bearerToken":["reminders:write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Reminder id","schema":{"type":"integer","minimum":1}}],"responses":{"204":{"description":"Archived"},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/reminders/{id}/done":{"post":{"operationId":"reminderDone","summary":"He reached out: the next one is due a cadence from today","security":[{"bearerToken":["reminders:write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Reminder id","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"reminder":{"type":"object","properties":{"id":{"type":"integer"},"person":{"type":"string"},"cadence_days":{"type":"integer"},"next_due":{"type":"string","format":"date"},"note":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"},"contact":{"type":["object","null"],"properties":{"ref":{"type":"string"},"name":{"type":["string","null"]}}}}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/journal/keys":{"get":{"operationId":"journalKeys","summary":"His journal keys (wrapped; the server can't open them) and his devices","security":[{"bearerToken":["account"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"keys":{"type":["object","null"],"properties":{"recovery_wrapped":{"type":"string","contentEncoding":"base64","description":"The journal key, sealed under his recovery key"},"public_key":{"type":"string","contentEncoding":"base64","description":"His P-256 public key (for entries shared with him)"},"secret_wrapped":{"type":"string","contentEncoding":"base64","description":"The matching secret key, sealed under the journal key"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"devices":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"public_key":{"type":"string","contentEncoding":"base64","description":"The device's P-256 public key"},"wrapped_key":{"type":["string","null"],"contentEncoding":"base64","description":"The journal key sealed to this device (after approval)"},"status":{"enum":["pending","active"]},"created_at":{"type":"string","format":"date-time"},"approved_at":{"type":["string","null"]},"last_seen_at":{"type":["string","null"]}}}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"operationId":"createJournalKeys","summary":"Set his journal up, once, from his first device","security":[{"bearerToken":["account"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["recovery_wrapped","public_key","secret_wrapped","device"],"properties":{"recovery_wrapped":{"type":"string","contentEncoding":"base64","description":""},"public_key":{"type":"string","contentEncoding":"base64","description":""},"secret_wrapped":{"type":"string","contentEncoding":"base64","description":""},"device":{"type":"object","required":["id","name","public_key"],"properties":{"id":{"type":"string","pattern":"^[a-z0-9]{8,40}$"},"name":{"type":"string","maxLength":80},"public_key":{"type":"string","contentEncoding":"base64","description":"The device's P-256 public key"}}}}}}}},"responses":{"201":{"description":"Set up","content":{"application/json":{"schema":{"type":"object","properties":{"keys":{"type":["object","null"],"properties":{"recovery_wrapped":{"type":"string","contentEncoding":"base64","description":"The journal key, sealed under his recovery key"},"public_key":{"type":"string","contentEncoding":"base64","description":"His P-256 public key (for entries shared with him)"},"secret_wrapped":{"type":"string","contentEncoding":"base64","description":"The matching secret key, sealed under the journal key"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"devices":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"public_key":{"type":"string","contentEncoding":"base64","description":"The device's P-256 public key"},"wrapped_key":{"type":["string","null"],"contentEncoding":"base64","description":"The journal key sealed to this device (after approval)"},"status":{"enum":["pending","active"]},"created_at":{"type":"string","format":"date-time"},"approved_at":{"type":["string","null"]},"last_seen_at":{"type":["string","null"]}}}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Already set up: enroll this device instead","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/journal/keys/recovery":{"put":{"operationId":"replaceJournalRecovery","summary":"A new recovery key (the old one stops working)","security":[{"bearerToken":["account"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["recovery_wrapped"],"properties":{"recovery_wrapped":{"type":"string","contentEncoding":"base64","description":"The journal key sealed under the new recovery key"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"keys":{"type":["object","null"],"properties":{"recovery_wrapped":{"type":"string","contentEncoding":"base64","description":"The journal key, sealed under his recovery key"},"public_key":{"type":"string","contentEncoding":"base64","description":"His P-256 public key (for entries shared with him)"},"secret_wrapped":{"type":"string","contentEncoding":"base64","description":"The matching secret key, sealed under the journal key"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"devices":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"public_key":{"type":"string","contentEncoding":"base64","description":"The device's P-256 public key"},"wrapped_key":{"type":["string","null"],"contentEncoding":"base64","description":"The journal key sealed to this device (after approval)"},"status":{"enum":["pending","active"]},"created_at":{"type":"string","format":"date-time"},"approved_at":{"type":["string","null"]},"last_seen_at":{"type":["string","null"]}}}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not set up","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/journal/devices":{"post":{"operationId":"registerJournalDevice","summary":"Register this device: active if it unlocked with the recovery key, otherwise waiting for approval","security":[{"bearerToken":["account"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"type":"object","required":["id","name","public_key"],"properties":{"id":{"type":"string","pattern":"^[a-z0-9]{8,40}$"},"name":{"type":"string","maxLength":80},"public_key":{"type":"string","contentEncoding":"base64","description":"The device's P-256 public key"}}},{"type":"object","properties":{"active":{"type":"boolean"}}}]}}}},"responses":{"201":{"description":"Registered","content":{"application/json":{"schema":{"type":"object","properties":{"device":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"public_key":{"type":"string","contentEncoding":"base64","description":"The device's P-256 public key"},"wrapped_key":{"type":["string","null"],"contentEncoding":"base64","description":"The journal key sealed to this device (after approval)"},"status":{"enum":["pending","active"]},"created_at":{"type":"string","format":"date-time"},"approved_at":{"type":["string","null"]},"last_seen_at":{"type":["string","null"]}}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Journal not set up","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/journal/devices/{id}":{"get":{"operationId":"journalDevice","summary":"One device (a waiting device checks here for its wrapped key)","security":[{"bearerToken":["account"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Device id","schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"device":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"public_key":{"type":"string","contentEncoding":"base64","description":"The device's P-256 public key"},"wrapped_key":{"type":["string","null"],"contentEncoding":"base64","description":"The journal key sealed to this device (after approval)"},"status":{"enum":["pending","active"]},"created_at":{"type":"string","format":"date-time"},"approved_at":{"type":["string","null"]},"last_seen_at":{"type":["string","null"]}}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"revokeJournalDevice","summary":"Remove a device, or turn down a waiting one","security":[{"bearerToken":["account"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Device id","schema":{"type":"string"}}],"responses":{"204":{"description":"Removed"},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/journal/devices/{id}/approve":{"post":{"operationId":"approveJournalDevice","summary":"Approve a waiting device: send the journal key sealed to its public key","security":[{"bearerToken":["account"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Device id","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["wrapped_key"],"properties":{"wrapped_key":{"type":"string","contentEncoding":"base64","description":""}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"device":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"public_key":{"type":"string","contentEncoding":"base64","description":"The device's P-256 public key"},"wrapped_key":{"type":["string","null"],"contentEncoding":"base64","description":"The journal key sealed to this device (after approval)"},"status":{"enum":["pending","active"]},"created_at":{"type":"string","format":"date-time"},"approved_at":{"type":["string","null"]},"last_seen_at":{"type":["string","null"]}}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Not waiting","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/journal/records":{"get":{"operationId":"pullJournal","summary":"Sealed records changed since a cursor, oldest change first","security":[{"bearerToken":["account"]}],"parameters":[{"name":"since","in":"query","schema":{"type":"integer","minimum":0,"default":0},"description":"The cursor from the previous pull"},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":500,"default":200}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"records":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"e:<id> (an entry) or j:<id> (a journal)"},"version":{"type":"integer"},"seq":{"type":"integer"},"data":{"type":["string","null"],"contentEncoding":"base64","description":"The sealed record (AES-256-GCM); null once deleted"},"deleted":{"type":"boolean"},"updated_at":{"type":"string","format":"date-time"}}}},"cursor":{"type":"integer"},"more":{"type":"boolean"}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"pushJournal","summary":"Write sealed records; a write based on a stale version comes back as a conflict","security":[{"bearerToken":["account"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["records"],"properties":{"records":{"type":"array","maxItems":200,"items":{"type":"object","required":["id","base_version","data"],"properties":{"id":{"type":"string"},"base_version":{"type":"integer","minimum":0,"description":"The version this write is based on (0 for new)"},"data":{"type":["string","null"],"contentEncoding":"base64","description":"Sealed; null deletes it for good"}}}}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"results":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"ok":{"type":"boolean"},"version":{"type":"integer"},"seq":{"type":"integer"},"conflict":{"type":"object","properties":{"id":{"type":"string","description":"e:<id> (an entry) or j:<id> (a journal)"},"version":{"type":"integer"},"seq":{"type":"integer"},"data":{"type":["string","null"],"contentEncoding":"base64","description":"The sealed record (AES-256-GCM); null once deleted"},"deleted":{"type":"boolean"},"updated_at":{"type":"string","format":"date-time"}}}}}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/journal/summary":{"get":{"operationId":"journalSummary","summary":"What the server knows about his journal: how many records, how many bytes","security":[{"bearerToken":["account"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"records":{"type":"integer"},"bytes":{"type":"integer"}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/journal/usage":{"get":{"operationId":"journalUsage","summary":"His journal storage: sealed bytes used, and his quota","security":[{"bearerToken":["account"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"bytes":{"type":"integer"},"quota":{"type":"integer"}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/journal/media":{"post":{"operationId":"startJournalUpload","summary":"Start (or resume) uploading a sealed file: signed upload URLs, one per 4 MB chunk","security":[{"bearerToken":["account"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["id","bytes","chunks"],"properties":{"id":{"type":"string","pattern":"^[a-z0-9]{8,40}$"},"bytes":{"type":"integer","description":"Sealed size"},"chunks":{"type":"integer","minimum":1,"maximum":100}}}}}},"responses":{"201":{"description":"Ready","content":{"application/json":{"schema":{"type":"object","properties":{"media":{"type":"object","properties":{"id":{"type":"string"},"bytes":{"type":"integer"},"chunks":{"type":"integer"},"status":{"enum":["uploading","complete"]},"created_at":{"type":"string","format":"date-time"},"completed_at":{"type":["string","null"]}}},"upload":{"type":"array","items":{"type":"string","format":"uri"},"description":"PUT each sealed chunk here (good for an hour)"}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Already uploaded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Over his storage quota","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Media storage not set up","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/journal/media/{id}":{"get":{"operationId":"downloadJournalMedia","summary":"Signed download URLs for a file's sealed chunks, in order","security":[{"bearerToken":["account"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"File id","schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"media":{"type":"object","properties":{"id":{"type":"string"},"bytes":{"type":"integer"},"chunks":{"type":"integer"},"status":{"enum":["uploading","complete"]},"created_at":{"type":"string","format":"date-time"},"completed_at":{"type":["string","null"]}}},"download":{"type":"array","items":{"type":"string","format":"uri"}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Still uploading","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deleteJournalMedia","summary":"Delete a file for good","security":[{"bearerToken":["account"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"File id","schema":{"type":"string"}}],"responses":{"204":{"description":"Deleted"},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/journal/media/{id}/complete":{"post":{"operationId":"completeJournalUpload","summary":"Every chunk is up: checked against storage, and the file is his","security":[{"bearerToken":["account"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"File id","schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"media":{"type":"object","properties":{"id":{"type":"string"},"bytes":{"type":"integer"},"chunks":{"type":"integer"},"status":{"enum":["uploading","complete"]},"created_at":{"type":"string","format":"date-time"},"completed_at":{"type":["string","null"]}}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Parts missing, or sizes don't add up","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/journal/blob/{token}":{"put":{"operationId":"putJournalBlob","summary":"Development only (Spaces in production): store one sealed chunk; the signed token is the permission","security":[],"parameters":[{"name":"token","in":"path","required":true,"description":"A signed, expiring token naming one chunk","schema":{"type":"string"}}],"responses":{"200":{"description":"Stored"},"403":{"description":"Invalid or expired link","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"operationId":"getJournalBlob","summary":"Development only (Spaces in production): one sealed chunk","security":[],"parameters":[{"name":"token","in":"path","required":true,"description":"A signed, expiring token naming one chunk","schema":{"type":"string"}}],"responses":{"200":{"description":"The sealed bytes","content":{"application/octet-stream":{}}},"404":{"description":"Not found or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/journal/recipients":{"get":{"operationId":"journalRecipients","summary":"His cohorts and the brothers in each who can receive a shared entry (with their public keys)","security":[{"bearerToken":["account"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"cohorts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"label":{"type":"string"},"brothers":{"type":"array","items":{"type":"object","properties":{"user_id":{"type":"integer"},"name":{"type":"string"},"public_key":{"type":["string","null"],"contentEncoding":"base64","description":"Null until he sets up his journal"}}}}}}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/journal/shares":{"get":{"operationId":"journalShares","summary":"Shares he made (who, when, read or not) and shares made to him (sealed)","security":[{"bearerToken":["account"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"granted":{"type":"array","items":{"type":"object"}},"received":{"type":"array","items":{"type":"object"}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createJournalShare","summary":"Share a sealed snapshot of one entry with brothers; each gets the share key sealed to his public key","security":[{"bearerToken":["account"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["id","data","recipients"],"properties":{"id":{"type":"string","pattern":"^[a-z0-9]{8,40}$"},"data":{"type":"string","contentEncoding":"base64","description":"The entry snapshot, sealed with the share key"},"cohort_id":{"type":["integer","null"]},"recipients":{"type":"array","maxItems":100,"items":{"type":"object","required":["user_id","wrapped_key"],"properties":{"user_id":{"type":"integer"},"wrapped_key":{"type":"string","contentEncoding":"base64","description":"The share key sealed to his public key"}}}}}}}}},"responses":{"201":{"description":"Shared","content":{"application/json":{"schema":{"type":"object","properties":{"share":{"type":"object","properties":{"id":{"type":"string"},"recipients":{"type":"integer"}}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not one of his brothers or cohorts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/journal/shares/{id}":{"delete":{"operationId":"revokeJournalShare","summary":"Revoke a share: the sealed snapshot and keys are deleted","security":[{"bearerToken":["account"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"File id","schema":{"type":"string"}}],"responses":{"204":{"description":"Revoked"},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found, or not his","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/journal/shares/{id}/read":{"post":{"operationId":"readJournalShare","summary":"He opened a share made to him","security":[{"bearerToken":["account"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"File id","schema":{"type":"string"}}],"responses":{"204":{"description":"Marked read"},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/journal/wrote":{"post":{"operationId":"journalWrote","summary":"He wrote an entry today: keep any 12:30+1 discipline he linked to the Journal","security":[{"bearerToken":["account"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"kept":{"type":"array","items":{"type":"integer"}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/prayer":{"get":{"operationId":"prayerOverview","summary":"His lists (his own and his cohorts'), each with his settings and counts; his Inbox; how many answered","security":[{"bearerToken":["prayer:read"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"lists":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"look":{"type":"object","description":"How he has it look: color (lists), an emoji or photo icon, a banner photo. URLs are signed and short-lived.","properties":{"color":{"type":["string","null"],"pattern":"^#[0-9a-f]{6}$"},"icon":{"type":["string","null"],"description":"An emoji"},"icon_url":{"type":["string","null"],"format":"uri"},"banner_url":{"type":["string","null"],"format":"uri"}}},"kind":{"enum":["personal","cohort"]},"mine":{"type":"boolean"},"settings":{"type":"object","properties":{"per_session":{"type":"integer","minimum":0,"maximum":20,"description":"Subjects a \"by lists\" session takes from this list (default 1)"},"days_mask":{"type":"integer","minimum":1,"maximum":127,"description":"Days it's in sessions: bit 0 = Monday … bit 6 = Sunday; 127 = every day"},"in_sessions":{"type":"boolean"},"sort":{"type":"integer"},"archived":{"type":"boolean"}}},"subject_count":{"type":"integer"},"request_count":{"type":"integer"}}}},"inbox":{"type":"object","properties":{"id":{"type":["integer","null"]},"count":{"type":"integer"}}},"answered":{"type":"integer"}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/prayer/feeds":{"post":{"operationId":"followPrayerFeed","summary":"Follow an RSS or Atom feed as a prayer list: each item is something to pray for, newest first (one a session by default). The server fetches it hourly","security":[{"bearerToken":["prayer:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri"},"name":{"type":"string","maxLength":100}}}}}},"responses":{"201":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Already following it","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Not a feed, or not reachable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/prayer/lists/{id}":{"get":{"operationId":"prayerList","summary":"One list: its subjects (on a cohort's list, each man), each with its active requests","security":[{"bearerToken":["prayer:read"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"List id","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"list":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"look":{"type":"object","description":"How he has it look: color (lists), an emoji or photo icon, a banner photo. URLs are signed and short-lived.","properties":{"color":{"type":["string","null"],"pattern":"^#[0-9a-f]{6}$"},"icon":{"type":["string","null"],"description":"An emoji"},"icon_url":{"type":["string","null"],"format":"uri"},"banner_url":{"type":["string","null"],"format":"uri"}}},"kind":{"enum":["personal","cohort"]},"mine":{"type":"boolean"},"settings":{"type":"object","properties":{"per_session":{"type":"integer","minimum":0,"maximum":20,"description":"Subjects a \"by lists\" session takes from this list (default 1)"},"days_mask":{"type":"integer","minimum":1,"maximum":127,"description":"Days it's in sessions: bit 0 = Monday … bit 6 = Sunday; 127 = every day"},"in_sessions":{"type":"boolean"},"sort":{"type":"integer"},"archived":{"type":"boolean"}}},"subject_count":{"type":"integer"},"request_count":{"type":"integer"}}},"subjects":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"kind":{"enum":["subject","man","request"],"description":"subject: on his list; man: a man on a cohort's list; request: a request with no subject"},"id":{"type":["integer","null"]},"user_id":{"type":["integer","null"]},"name":{"type":"string"},"note":{"type":["string","null"]},"look":{"type":"object","description":"How he has it look: color (lists), an emoji or photo icon, a banner photo. URLs are signed and short-lived.","properties":{"color":{"type":["string","null"],"pattern":"^#[0-9a-f]{6}$"},"icon":{"type":["string","null"],"description":"An emoji"},"icon_url":{"type":["string","null"],"format":"uri"},"banner_url":{"type":["string","null"],"format":"uri"}}},"contact":{"type":["object","null"],"properties":{"ref":{"type":"string"},"name":{"type":["string","null"]}}},"list":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"color":{"type":["string","null"]}}},"requests":{"type":"array","items":{"$ref":"#/components/schemas/Request"}},"last_prayed_at":{"type":["string","null"],"format":"date-time"}}}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"renamePrayerList","summary":"Rename one of his lists","security":[{"bearerToken":["prayer:write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"List id","schema":{"type":"integer","minimum":1}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","maxLength":100}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found, or not his","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deletePrayerList","summary":"Delete one of his lists and everything on it","security":[{"bearerToken":["prayer:write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"List id","schema":{"type":"integer","minimum":1}}],"responses":{"204":{"description":"Deleted"},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found, or not his","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/prayer/lists/{id}/settings":{"put":{"operationId":"prayerListSettings","summary":"His settings for a list: subjects per session, which days, in sessions or not, archived","security":[{"bearerToken":["prayer:write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"List id","schema":{"type":"integer","minimum":1}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"per_session":{"type":"integer","minimum":0,"maximum":20,"description":"Subjects a \"by lists\" session takes from this list (default 1)"},"days_mask":{"type":"integer","minimum":1,"maximum":127,"description":"Days it's in sessions: bit 0 = Monday … bit 6 = Sunday; 127 = every day"},"in_sessions":{"type":"boolean"},"sort":{"type":"integer"},"archived":{"type":"boolean"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"settings":{"type":"object","properties":{"per_session":{"type":"integer","minimum":0,"maximum":20,"description":"Subjects a \"by lists\" session takes from this list (default 1)"},"days_mask":{"type":"integer","minimum":1,"maximum":127,"description":"Days it's in sessions: bit 0 = Monday … bit 6 = Sunday; 127 = every day"},"in_sessions":{"type":"boolean"},"sort":{"type":"integer"},"archived":{"type":"boolean"}}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/prayer/order":{"put":{"operationId":"orderPrayerLists","summary":"Put his lists in this order","security":[{"bearerToken":["prayer:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["list_ids"],"properties":{"list_ids":{"type":"array","items":{"type":"integer"}}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/prayer/subjects":{"post":{"operationId":"createSubject","summary":"Add a subject (who or what he prays for) to one of his lists","security":[{"bearerToken":["prayer:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["list_id","name"],"properties":{"list_id":{"type":"integer"},"name":{"type":"string","maxLength":100},"note":{"type":["string","null"],"maxLength":2000}}}}}},"responses":{"201":{"description":"Added","content":{"application/json":{"schema":{"type":"object","properties":{"subject":{"type":"object"}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/prayer/subjects/{id}":{"patch":{"operationId":"updateSubject","summary":"Rename, note, move to another list, or archive a subject","security":[{"bearerToken":["prayer:write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Subject id","schema":{"type":"integer","minimum":1}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"note":{"type":["string","null"]},"list_id":{"type":"integer"},"archived":{"type":"boolean"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deleteSubject","summary":"Delete a subject and its requests","security":[{"bearerToken":["prayer:write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Subject id","schema":{"type":"integer","minimum":1}}],"responses":{"204":{"description":"Deleted"},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/prayer/inbox":{"get":{"operationId":"prayerInbox","summary":"What's waiting in his Inbox, to sort onto a list","security":[{"bearerToken":["prayer:read"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"list_id":{"type":"integer"},"requests":{"type":"array","items":{"$ref":"#/components/schemas/Request"}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"addToPrayerInbox","summary":"Quick capture: a request into his Inbox","security":[{"bearerToken":["prayer:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["title"],"properties":{"title":{"type":"string","maxLength":140},"body":{"type":["string","null"]},"tags":{"type":"array","items":{"type":"string"}}}}}}},"responses":{"201":{"description":"Added","content":{"application/json":{"schema":{"type":"object","properties":{"request":{"$ref":"#/components/schemas/Request"}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/prayer/session":{"get":{"operationId":"prayerSession","summary":"A prayer session: urgent requests, his Inbox, then subjects (least recently prayed first)","security":[{"bearerToken":["prayer:read"]}],"parameters":[{"name":"mode","in":"query","schema":{"enum":["lists","time"],"default":"lists"},"description":"lists: each list due today gives its per-session subjects. time: lists take turns until every subject has come up (the app stops at the time)."},{"name":"lists","in":"query","schema":{"type":"string"},"description":"Comma-separated list ids (default: every list in his sessions)"},{"name":"urgent","in":"query","schema":{"enum":["0","1"],"default":"1"}},{"name":"inbox","in":"query","schema":{"enum":["0","1"],"default":"1"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"mode":{"enum":["lists","time"]},"urgent":{"type":"array","items":{"$ref":"#/components/schemas/Request"}},"inbox":{"type":"array","items":{"$ref":"#/components/schemas/Request"}},"subjects":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"kind":{"enum":["subject","man","request"],"description":"subject: on his list; man: a man on a cohort's list; request: a request with no subject"},"id":{"type":["integer","null"]},"user_id":{"type":["integer","null"]},"name":{"type":"string"},"note":{"type":["string","null"]},"look":{"type":"object","description":"How he has it look: color (lists), an emoji or photo icon, a banner photo. URLs are signed and short-lived.","properties":{"color":{"type":["string","null"],"pattern":"^#[0-9a-f]{6}$"},"icon":{"type":["string","null"],"description":"An emoji"},"icon_url":{"type":["string","null"],"format":"uri"},"banner_url":{"type":["string","null"],"format":"uri"}}},"contact":{"type":["object","null"],"properties":{"ref":{"type":"string"},"name":{"type":["string","null"]}}},"list":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"color":{"type":["string","null"]}}},"requests":{"type":"array","items":{"$ref":"#/components/schemas/Request"}},"last_prayed_at":{"type":["string","null"],"format":"date-time"}}}},"more":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"kind":{"enum":["subject","man","request"],"description":"subject: on his list; man: a man on a cohort's list; request: a request with no subject"},"id":{"type":["integer","null"]},"user_id":{"type":["integer","null"]},"name":{"type":"string"},"note":{"type":["string","null"]},"look":{"type":"object","description":"How he has it look: color (lists), an emoji or photo icon, a banner photo. URLs are signed and short-lived.","properties":{"color":{"type":["string","null"],"pattern":"^#[0-9a-f]{6}$"},"icon":{"type":["string","null"],"description":"An emoji"},"icon_url":{"type":["string","null"],"format":"uri"},"banner_url":{"type":["string","null"],"format":"uri"}}},"contact":{"type":["object","null"],"properties":{"ref":{"type":"string"},"name":{"type":["string","null"]}}},"list":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"color":{"type":["string","null"]}}},"requests":{"type":"array","items":{"$ref":"#/components/schemas/Request"}},"last_prayed_at":{"type":["string","null"],"format":"date-time"}}},"description":"By lists: who would come next, in order, if he asks for more"}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/prayer/images":{"post":{"operationId":"newPrayerImage","summary":"A slot for one photo (an icon or banner): PUT the JPEG (5 MB at most) to upload_url, then name its key in a look","security":[{"bearerToken":["prayer:write"]}],"responses":{"201":{"description":"Ready","content":{"application/json":{"schema":{"type":"object","properties":{"key":{"type":"string"},"upload_url":{"type":"string","format":"uri"},"max_bytes":{"type":"integer"},"content_type":{"type":"string"}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Photos unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/prayer/looks":{"put":{"operationId":"setPrayerLook","summary":"Set how a list, subject, or brother looks for him (fields left out stay; null clears)","security":[{"bearerToken":["prayer:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["target","id"],"properties":{"target":{"enum":["list","subject","man"]},"id":{"type":"integer","description":"List id, subject id, or the brother's user id"},"color":{"type":["string","null"]},"icon":{"type":["string","null"]},"icon_image":{"type":["string","null"],"description":"A key from /v1/prayer/images"},"banner_image":{"type":["string","null"]}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"look":{"type":"object","description":"How he has it look: color (lists), an emoji or photo icon, a banner photo. URLs are signed and short-lived.","properties":{"color":{"type":["string","null"],"pattern":"^#[0-9a-f]{6}$"},"icon":{"type":["string","null"],"description":"An emoji"},"icon_url":{"type":["string","null"],"format":"uri"},"banner_url":{"type":["string","null"],"format":"uri"}}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/prayer/prayed":{"post":{"operationId":"prayedFor","summary":"He prayed for a subject and/or requests (keeps a discipline linked to Prayer)","security":[{"bearerToken":["prayer:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"subject_id":{"type":["integer","null"]},"user_id":{"type":["integer","null"],"description":"A brother prayed for by name (a cohort list's man)"},"request_ids":{"type":"array","items":{"type":"integer"}}}}}}},"responses":{"201":{"description":"Recorded","content":{"application/json":{"schema":{"type":"object","properties":{"prayed":{"type":"integer"},"kept_disciplines":{"type":"array","items":{"type":"integer"}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/me/push":{"post":{"operationId":"registerPushDevice","summary":"Register this phone for push notifications (its Expo push token). A phone that changes hands moves to whoever is signed in","security":[{"bearerToken":["account"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["token","platform"],"properties":{"token":{"type":"string"},"platform":{"enum":["ios","android"]},"name":{"type":"string","maxLength":80}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"prompt_push":{"type":"boolean"},"prompt_slack":{"type":"boolean"},"phones":{"type":"integer"}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/me/push/{token}":{"delete":{"operationId":"removePushDevice","summary":"This phone stops getting his notifications (signing out)","security":[{"bearerToken":["account"]}],"parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Removed"},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/me/notify":{"get":{"operationId":"notifySettings","summary":"How he's reminded: the evening prompt by push and/or Slack, and how many phones are registered","security":[{"bearerToken":["account"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"prompt_push":{"type":"boolean"},"prompt_slack":{"type":"boolean"},"phones":{"type":"integer"}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"operationId":"saveNotifySettings","summary":"Change how he's reminded (Slack still goes when push has no phone to reach)","security":[{"bearerToken":["account"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"prompt_push":{"type":"boolean"},"prompt_slack":{"type":"boolean"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"prompt_push":{"type":"boolean"},"prompt_slack":{"type":"boolean"},"phones":{"type":"integer"}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/examen/done":{"post":{"operationId":"examenDone","summary":"He prayed the Daily Examen: keep the discipline he linked to it (his own or his season's), today. No content is sent; what he prays stays in his encrypted journal","security":[{"bearerToken":["account"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"kept_disciplines":{"type":"array","items":{"type":"integer"}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/examen/people":{"get":{"operationId":"examenPeople","summary":"Who he can ask to call him: his captain, and the men in his cohorts","security":[{"bearerToken":["account"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/examen/talk":{"post":{"operationId":"examenTalk","summary":"\"I need to talk\": tell his captain or a man in his cohort he'd like a call tonight (push and Slack). Nothing else is shared; once an evening per person","security":[{"bearerToken":["account"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["to"],"properties":{"to":{"oneOf":[{"const":"captain"},{"type":"integer"}]}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not in a cohort, or not his","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/linkout":{"get":{"operationId":"linkOut","summary":"May this phone link to buying a membership on agon1230.com? On iPhone, only on the US App Store (and only while Mark has it on); never on Android; always on the web","security":[{"bearerToken":["account"]}],"parameters":[{"name":"platform","in":"query","schema":{"enum":["ios","android","web"]}},{"name":"storefront","in":"query","schema":{"type":"string"},"description":"The App Store storefront country, ISO 3166-1 alpha-3 (USA)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"allowed":{"type":"boolean"},"join_url":{"type":["string","null"]},"tag":{"type":"boolean","description":"Add ?utm_source=ios_app&utm_medium=link_out to billing links"}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/reports":{"post":{"operationId":"report","summary":"Report something a brother shared with him (a prayer request or update, a takeaway, an SOS note, a journal entry shared with him) or the man himself. Mark is told at once; the reporter stops seeing it. block: true also blocks the man","security":[{"bearerToken":["account"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["kind","id","reason"],"properties":{"kind":{"enum":["request","update","takeaway","sos","journal_share","man"]},"id":{"type":["integer","string"],"description":"The item's id (a journal share's is text), or the man's user id"},"reason":{"enum":["offensive","harassment","spam","unsafe","other"]},"note":{"type":"string","maxLength":1000},"content":{"type":"string","description":"For an encrypted journal entry: its text, only if he chooses to send it"},"block":{"type":"boolean"}}}}}},"responses":{"201":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"reported":{"type":"boolean"},"hidden":{"type":"boolean"},"blocked":{"type":"boolean"}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not shared with him","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/blocks":{"get":{"operationId":"blocks","summary":"The men he has blocked","security":[{"bearerToken":["account"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/blocks/{userId}":{"put":{"operationId":"block","summary":"Block a man: his shared prayer requests, takeaways, SOS calls, and journal shares are hidden from him. The cohort's captain and Mark are told","security":[{"bearerToken":["account"]}],"parameters":[{"name":"userId","in":"path","required":true,"description":"The man's user id","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not one of his brothers","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"unblock","summary":"Unblock a man","security":[{"bearerToken":["account"]}],"parameters":[{"name":"userId","in":"path","required":true,"description":"The man's user id","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/journal/ai/summary":{"post":{"operationId":"summarizeVoiceNote","summary":"Summarize a voice note's transcript with AI (the voice_ai feature, switched on per man). Transcribing happens on his phone; only this text is sent, on his tap, and nothing is stored","security":[{"bearerToken":["account"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["text"],"properties":{"text":{"type":"string","maxLength":30000}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":["string","null"]},"summary":{"type":"string"},"points":{"type":"array","items":{"type":"string"}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not switched on for him","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Too short or too long","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Not set up on this server","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/doors":{"get":{"operationId":"doors","summary":"Eight Doors: his two grids (home and work), each door's name, level (1 name, 2 story, 3 friend), notes, last connection, and ties; counts and a next step","security":[{"bearerToken":["account"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"home":{"type":"object"},"work":{"type":"object"}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/doors/{grid}/{position}":{"put":{"operationId":"setDoor","summary":"Name a door, or change its level or notes. Its subject on his \"Eight Doors\" prayer list follows its name","security":[{"bearerToken":["account"]}],"parameters":[{"name":"grid","in":"path","required":true,"schema":{"enum":["home","work"]}},{"name":"position","in":"path","required":true,"schema":{"type":"integer","minimum":1,"maximum":8},"description":"1 north, clockwise to 8 northwest"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":100},"level":{"enum":[1,2,3]},"notes":{"type":["string","null"],"maxLength":2000}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"door":{"type":"object"}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"clearDoor","summary":"Clear a door: its name, notes, connections, prayer subject, reminder, and contact link","security":[{"bearerToken":["account"]}],"parameters":[{"name":"grid","in":"path","required":true,"schema":{"enum":["home","work"]}},{"name":"position","in":"path","required":true,"schema":{"type":"integer","minimum":1,"maximum":8}}],"responses":{"204":{"description":"Cleared"},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No door there","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/doors/{id}/connect":{"post":{"operationId":"connectDoor","summary":"He connected with this door today (an optional note). Keeps the discipline he linked to Eight Doors, his own or his season's","security":[{"bearerToken":["account"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Door id","schema":{"type":"integer","minimum":1}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"note":{"type":["string","null"],"maxLength":500}}}}}},"responses":{"201":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"door":{"type":"object"}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not his","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/doors/{id}/connections":{"get":{"operationId":"doorConnections","summary":"When he connected with this door, and his notes (newest first)","security":[{"bearerToken":["account"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Door id","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not his","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/doors/{id}/reminder":{"post":{"operationId":"doorReminder","summary":"A People reminder to reach out to this door every so many days (or change how often)","security":[{"bearerToken":["account"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Door id","schema":{"type":"integer","minimum":1}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"cadence_days":{"type":"integer","minimum":1,"maximum":366}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"door":{"type":"object"}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not his","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/me/bible":{"get":{"operationId":"bibleSettings","summary":"Where \"Read\" opens: his Bible app (YouVersion, Logos, Blue Letter Bible, or the web) and translation","security":[{"bearerToken":["account"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"operationId":"setBibleSettings","summary":"Change his Bible app and translation","security":[{"bearerToken":["account"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"reader":{"enum":["youversion","logos","blb","web"]},"translation":{"type":"string"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/plans":{"get":{"operationId":"readingPlans","summary":"Reading plans he can read (Agōn's, his cohort's), with his enrollment in each","security":[{"bearerToken":["account"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/plans/today":{"get":{"operationId":"todaysReading","summary":"Every plan he's reading: today's day and passages (labels and links into his Bible app; no text), whether he's read it, how far behind, what to read next","security":[{"bearerToken":["account"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/plans/{id}":{"get":{"operationId":"readingPlan","summary":"A plan, day by day (passage labels and links)","security":[{"bearerToken":["account"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Plan id","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/plans/{id}/enroll":{"post":{"operationId":"enrollInPlan","summary":"Start reading a plan (from today, or start_date), optionally with a cohort, and optionally keeping one of his disciplines","security":[{"bearerToken":["account"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Plan id","schema":{"type":"integer","minimum":1}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"start_date":{"type":"string","format":"date"},"start_day":{"type":"integer","minimum":1,"description":"Pick up mid-stream: today is this day of the plan; the days before it count as read elsewhere"},"discipline_id":{"type":["integer","null"]},"slot_id":{"type":["integer","null"]}}}}}},"responses":{"201":{"description":"Enrolled","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Already reading it","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/enrollments/{id}":{"patch":{"operationId":"updateEnrollment","summary":"Change which discipline a plan keeps, which day he's on (today_day: picking up mid-stream; his reads here stay), or stop reading it","security":[{"bearerToken":["account"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Enrollment id","schema":{"type":"integer","minimum":1}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"discipline_id":{"type":["integer","null"]},"today_day":{"type":"integer","minimum":1},"ended":{"type":"boolean"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not his","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/enrollments/{id}/catch-up":{"post":{"operationId":"catchUp","summary":"Skip to today: the days he missed stop counting as behind (he can still read them). Never a miss or a fine","security":[{"bearerToken":["account"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Enrollment id","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not his","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/enrollments/{id}/reads/{day}":{"put":{"operationId":"markRead","summary":"He read a day (today, or yesterday until 9am): keeps his linked discipline for that date. An optional one-line takeaway, shared with his cohort if he says so","security":[{"bearerToken":["account"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Enrollment id","schema":{"type":"integer","minimum":1}},{"name":"day","in":"path","required":true,"schema":{"type":"integer","minimum":1}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"date":{"enum":["today","yesterday"]},"takeaway":{"type":"string","maxLength":280},"share":{"type":"boolean"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not his","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid day","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"unmarkRead","summary":"Take back a read (his discipline's mark stays as it is)","security":[{"bearerToken":["account"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Enrollment id","schema":{"type":"integer","minimum":1}},{"name":"day","in":"path","required":true,"schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not his","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/membership":{"get":{"operationId":"membership","summary":"His membership: status, cohort and week, rate, payment method, invoices and what's coming, the mission jar, his invite link, seats held for friends, and next season (404 not_member). Paying stays on agon1230.com (manage_url)","security":[{"bearerToken":["account"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No membership","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/membership/seats":{"post":{"operationId":"holdSeats","summary":"Hold seats in his slot for friends before his cohort starts; each is emailed an invitation to apply","security":[{"bearerToken":["account"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["people"],"properties":{"people":{"type":"array","items":{"type":"object","required":["name","email"],"properties":{"name":{"type":"string"},"email":{"type":"string","format":"email"}}}}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No membership","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid, or no room","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/membership/seats/{id}":{"delete":{"operationId":"releaseSeat","summary":"Release a seat he held (not once that man has been accepted)","security":[{"bearerToken":["account"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Seat hold id","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not his","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Already accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/membership/renewal":{"put":{"operationId":"renew","summary":"Next season (from week 10): continue with his brothers, switch cohorts, or not this time. Continuing or switching needs recommit: true (the covenant)","security":[{"bearerToken":["account"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["choice"],"properties":{"choice":{"enum":["continue","switch","done"]},"slot_id":{"type":["integer","null"]},"recommit":{"type":"boolean"},"note":{"type":"string","maxLength":1000}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No membership","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Not open yet, or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/cohort":{"get":{"operationId":"cohortBoard","summary":"The last week in each of his cohorts, only what the channel already shows: who gave account, dailies kept of due, weekly targets hit, streaks (404 not_member when he has no cohort)","security":[{"bearerToken":["account"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not in a cohort","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/cohort/contacts":{"get":{"operationId":"cohortContacts","summary":"His brothers' email and phone after the lock-in call, only for men who share them; his captain; what he shares","security":[{"bearerToken":["account"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not in a cohort","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/cohort/contact":{"put":{"operationId":"saveCohortContact","summary":"His phone, and whether his email and phone are shared with his cohort","security":[{"bearerToken":["account"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"phone":{"type":["string","null"],"maxLength":30},"share":{"type":"boolean"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not in a cohort","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/sos":{"get":{"operationId":"openSos","summary":"Open SOS calls in his cohorts from the last day (his own and his brothers')","security":[{"bearerToken":["account"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not in a cohort","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"askSos","summary":"Ask his brothers for prayer or a call (Slack, texts for men who opted in, and their phones). A second ask within 10 minutes adds to the open one","security":[{"bearerToken":["account"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"kind":{"enum":["pray","call"]},"note":{"type":"string","maxLength":500}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not in a cohort","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/sos/{id}/claim":{"post":{"operationId":"claimSos","summary":"\"I've got him\": the first brother to answer takes it, and the man who asked is told","security":[{"bearerToken":["account"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"SOS id","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not from his cohort","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"His own SOS","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/sos/{id}/resolve":{"post":{"operationId":"resolveSos","summary":"He's okay now (only the man who asked)","security":[{"bearerToken":["account"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"SOS id","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not his","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not from his cohort","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/captain":{"get":{"operationId":"captain","summary":"The cohorts he captains, each with this week's call evaluation (404 not_captain otherwise)","security":[{"bearerToken":["account"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"cohorts":{"type":"array","items":{"type":"object"}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not a captain","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/captain/cohorts/{id}":{"get":{"operationId":"captainBoard","summary":"A cohort's board: each man's streak, week and season %, his weeks, calls, last account, fading (and on what), SOS calls, email and phone; the cohort's averages and trend","security":[{"bearerToken":["account"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Cohort id","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not his cohort","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/captain/cohorts/{id}/evaluations":{"get":{"operationId":"captainEvaluations","summary":"The calls he can evaluate (newest first) and what he said about each","security":[{"bearerToken":["account"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Cohort id","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not his to evaluate","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not his cohort","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"operationId":"evaluateCall","summary":"Evaluate (or re-evaluate) a week's call: rating 1-10, anything unusual (only Mark sees it), a safety concern (Mark is alerted), and ideas for the captains to vote on","security":[{"bearerToken":["account"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Cohort id","schema":{"type":"integer","minimum":1}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["week","rating"],"properties":{"week":{"type":"integer"},"rating":{"type":"integer","minimum":1,"maximum":10},"unusual":{"type":"string","maxLength":4000},"concern":{"type":"boolean"},"ideas":{"type":"string","maxLength":4000,"description":"Blank lines between ideas"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not his cohort","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid, or that call hasn't happened","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/captain/cohorts/{id}/grace":{"get":{"operationId":"captainGrace","summary":"Grace requests from his men in this cohort: waiting ones first, then the last few decided","security":[{"bearerToken":["account"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Cohort id","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not his cohort","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/captain/grace/{id}":{"post":{"operationId":"decideGrace","summary":"Approve or deny one of his men's grace requests. The man hears back; Mark is told and can still change it","security":[{"bearerToken":["account"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Grace request id","schema":{"type":"integer","minimum":1}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["approve"],"properties":{"approve":{"type":"boolean"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not one of his men","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Already decided","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/captain/cohorts/{id}/watchman":{"get":{"operationId":"captainWatchman","summary":"Who keeps the cohort's prayer list (the Watchman), and the men who can","security":[{"bearerToken":["account"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Cohort id","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not his cohort","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"operationId":"setWatchman","summary":"Set the Watchman (one of his men), or none (the captain keeps it)","security":[{"bearerToken":["account"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Cohort id","schema":{"type":"integer","minimum":1}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"member_id":{"type":["integer","null"]}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not his cohort","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Not one of his men","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/captain/cohorts/{id}/plan":{"put":{"operationId":"setCohortPlan","summary":"Set (or clear) the reading plan his cohort reads together this season (from its first day). Each man is enrolled when he next opens his reading","security":[{"bearerToken":["account"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Cohort id","schema":{"type":"integer","minimum":1}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"plan_id":{"type":["integer","null"]}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not his cohort","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Not one of Agōn's plans","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/captain/ideas":{"get":{"operationId":"captainIdeas","summary":"The captains' open ideas, best first, with his vote on each","security":[{"bearerToken":["account"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not a captain","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/captain/ideas/{id}/vote":{"post":{"operationId":"voteIdea","summary":"Vote an idea up (1) or down (-1); the same vote again takes it back","security":[{"bearerToken":["account"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Idea id","schema":{"type":"integer","minimum":1}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"vote":{"enum":[1,-1]}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not a captain","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"No such idea","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/season":{"get":{"operationId":"season","summary":"His cohort season: the cohort, his Sabbath, grace days left and his grace requests (404 not_in_season when he has none)","security":[{"bearerToken":["disciplines:read"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"cohort":{"type":["object","null"]},"today":{"type":"string","format":"date"},"sabbath":{"type":["integer","null"],"description":"6 Saturday, 7 Sunday"},"grace_left":{"type":"integer"},"grace":{"type":"array","items":{"type":"object"}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not in a season","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/season/upcoming":{"get":{"operationId":"upcomingSeason","summary":"Before his cohort season counts (signed up, or before his first counted day): his cohort, when it starts, his 12:30+1 as set up on agon1230.com (a draft or locked in), and where to edit it. upcoming is null once his season is counting, or if he isn't in one","security":[{"bearerToken":["disciplines:read"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"upcoming":{"type":["object","null"]}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/season/upcoming/rule":{"put":{"operationId":"saveDraftRule","summary":"Change his draft 12:30+1 before his lock-in call (as on his signup page): his cohort's rules and shared disciplines apply","security":[{"bearerToken":["disciplines:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["disciplines"],"properties":{"disciplines":{"type":"array","items":{"type":"object","required":["pillar","title"],"properties":{"pillar":{"enum":["heart","soul","mind","strength","neighbor"]},"title":{"type":"string","maxLength":200},"cadence":{"enum":["daily","weekly"]},"weekly_target":{"type":"integer"},"days_mask":{"type":"integer"}}}}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Not a draft, or it breaks the cohort's rules","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/season/upcoming/rule/from-personal":{"post":{"operationId":"draftFromPersonal","summary":"Make his own 12:30+1 (kept in the app) his cohort draft; his cohort's shared disciplines are kept. His personal streak carries into his season","security":[{"bearerToken":["disciplines:write"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"No personal rule, not a draft, or it breaks the cohort's rules","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/season/day":{"get":{"operationId":"seasonDay","summary":"One day of his season: each discipline (due, status, effort, weekly progress), the open days, and whether the account is given","security":[{"bearerToken":["disciplines:read"]}],"parameters":[{"name":"date","in":"query","schema":{"type":"string"},"description":"YYYY-MM-DD, today, or yesterday (default today)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not in a season","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Not in his season","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"operationId":"giveSeasonAccount","summary":"Give (or change) his account for an open day: kept/missed and effort per discipline; weekly reps. Once every due daily has a status the account is given and his cohort channel is told","security":[{"bearerToken":["disciplines:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"date":{"type":"string"},"items":{"type":"array","items":{"type":"object","required":["id","status"],"properties":{"id":{"type":"integer"},"status":{"enum":["kept","missed"]},"effort":{"enum":["easy","fight","barely"]}}}}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not in a season","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A closed day, or bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/season/disciplines/{id}/link":{"put":{"operationId":"linkSeasonDiscipline","summary":"Link one of his season's disciplines to Prayer, People, or Journal (or unlink: null). A prayer time, reaching out, or a journal entry in the app then keeps it for the day. The rule itself is unchanged","security":[{"bearerToken":["disciplines:write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Discipline id","schema":{"type":"integer","minimum":1}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"link":{"enum":["prayer","people","journal","examen","neighbors",null]}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"integer"},"link":{"enum":["prayer","people","journal","examen","neighbors",null]}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not in a season","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Not his, or an unknown link","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/season/sabbath":{"put":{"operationId":"setSeasonSabbath","summary":"His Sabbath: Saturday (6), Sunday (7), or none (null). In season it starts with the next week","security":[{"bearerToken":["disciplines:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"weekday":{"type":["integer","null"],"enum":[6,7,null]}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not in a season","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/season/grace":{"post":{"operationId":"askSeasonGrace","summary":"Ask for grace days (sick, traveling)","security":[{"bearerToken":["disciplines:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["start"],"properties":{"start":{"type":"string","format":"date"},"end":{"type":"string","format":"date"},"reason":{"type":"string","maxLength":500}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"grace":{"type":"object"}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not in a season","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid, or not enough grace days left","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/contacts/links":{"put":{"operationId":"linkContact","summary":"Link a person (People), prayer subject, or brother to a card in his phone's contacts. Only the link and name are kept; numbers stay on his phone","security":[{"bearerToken":["account"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["target","id","contact_ref"],"properties":{"target":{"enum":["person","subject","man","door"]},"id":{"type":"integer","description":"Reminder id, subject id, the brother's user id, or door id"},"contact_ref":{"type":"string","maxLength":200,"description":"The contact's id on his phone"},"name":{"type":["string","null"]}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"contact":{"type":["object","null"],"description":"A link to a card in his phone's contacts","properties":{"ref":{"type":"string"},"name":{"type":["string","null"]}}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/contacts/links/{target}/{id}":{"delete":{"operationId":"unlinkContact","summary":"Remove a contact link","security":[{"bearerToken":["account"]}],"parameters":[{"name":"target","in":"path","required":true,"schema":{"enum":["person","subject","man","door"]}},{"name":"id","in":"path","required":true,"description":"Reminder, subject, user, or door id","schema":{"type":"integer","minimum":1}}],"responses":{"204":{"description":"Removed"},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/routines":{"get":{"operationId":"routines","summary":"His routines, in order, each with today's state and its streak","security":[{"bearerToken":["account"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"today":{"type":"string","format":"date"},"routines":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"title":{"type":"string"},"description":{"type":["string","null"]},"days_mask":{"type":"integer","description":"bit 0 = Monday … bit 6 = Sunday; 0 = anytime"},"start_minutes":{"type":["array","null"],"items":{"type":["integer","null"]},"description":"Start time per weekday (minutes after midnight), Monday first"},"remind":{"type":"boolean"},"color":{"type":["string","null"]},"icon":{"type":["string","null"]},"sort":{"type":"integer"},"step_count":{"type":"integer"},"total_seconds":{"type":"integer"},"due_today":{"type":"boolean"},"start_today":{"type":["integer","null"]},"done_today":{"type":"boolean"},"streak":{"type":"integer"},"steps":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"position":{"type":"integer"},"title":{"type":"string","maxLength":200},"seconds":{"type":["integer","null"],"minimum":1,"maximum":14400,"description":"Null: a checklist item, no timer"},"icon":{"type":["string","null"]},"notes":{"type":["string","null"],"maxLength":4000},"action":{"enum":["pray","journal","post","link","read","examen",null],"description":"pray: a prayer session; journal: a new entry; post: his run summary to his cohorts; link: open link_url; read: today's Scripture reading"},"link_url":{"type":["string","null"]},"discipline_id":{"type":["integer","null"],"description":"One of his 12:30+1 disciplines, kept when he finishes this step"},"reflect":{"type":"boolean","description":"Ask him for a reflection at this step (saved to his encrypted journal by the app)"}}}}}}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createRoutine","summary":"A new routine with its steps","security":[{"bearerToken":["account"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","maxLength":100},"description":{"type":["string","null"]},"days_mask":{"type":"integer"},"start_time":{"type":["integer","null"],"description":"The same start every day (minutes after midnight)"},"start_minutes":{"type":["array","null"],"items":{"type":["integer","null"]}},"remind":{"type":"boolean"},"color":{"type":["string","null"]},"icon":{"type":["string","null"]},"steps":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"position":{"type":"integer"},"title":{"type":"string","maxLength":200},"seconds":{"type":["integer","null"],"minimum":1,"maximum":14400,"description":"Null: a checklist item, no timer"},"icon":{"type":["string","null"]},"notes":{"type":["string","null"],"maxLength":4000},"action":{"enum":["pray","journal","post","link","read","examen",null],"description":"pray: a prayer session; journal: a new entry; post: his run summary to his cohorts; link: open link_url; read: today's Scripture reading"},"link_url":{"type":["string","null"]},"discipline_id":{"type":["integer","null"],"description":"One of his 12:30+1 disciplines, kept when he finishes this step"},"reflect":{"type":"boolean","description":"Ask him for a reflection at this step (saved to his encrypted journal by the app)"}}},"description":"Replaces every step; keep a step's id to keep it (and its history)"}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"routine":{"type":"object","properties":{"id":{"type":"integer"},"title":{"type":"string"},"description":{"type":["string","null"]},"days_mask":{"type":"integer","description":"bit 0 = Monday … bit 6 = Sunday; 0 = anytime"},"start_minutes":{"type":["array","null"],"items":{"type":["integer","null"]},"description":"Start time per weekday (minutes after midnight), Monday first"},"remind":{"type":"boolean"},"color":{"type":["string","null"]},"icon":{"type":["string","null"]},"sort":{"type":"integer"},"step_count":{"type":"integer"},"total_seconds":{"type":"integer"},"due_today":{"type":"boolean"},"start_today":{"type":["integer","null"]},"done_today":{"type":"boolean"},"streak":{"type":"integer"},"steps":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"position":{"type":"integer"},"title":{"type":"string","maxLength":200},"seconds":{"type":["integer","null"],"minimum":1,"maximum":14400,"description":"Null: a checklist item, no timer"},"icon":{"type":["string","null"]},"notes":{"type":["string","null"],"maxLength":4000},"action":{"enum":["pray","journal","post","link","read","examen",null],"description":"pray: a prayer session; journal: a new entry; post: his run summary to his cohorts; link: open link_url; read: today's Scripture reading"},"link_url":{"type":["string","null"]},"discipline_id":{"type":["integer","null"],"description":"One of his 12:30+1 disciplines, kept when he finishes this step"},"reflect":{"type":"boolean","description":"Ask him for a reflection at this step (saved to his encrypted journal by the app)"}}}}}},"runs":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"routine_id":{"type":"integer"},"date":{"type":"string","format":"date"},"started_at":{"type":"string","format":"date-time"},"ended_at":{"type":["string","null"],"format":"date-time"},"completed":{"type":"boolean"},"posted":{"type":"boolean"},"steps":{"type":"array","items":{"type":"object","properties":{"position":{"type":"integer"},"step_id":{"type":["integer","null"]},"title":{"type":"string"},"planned_seconds":{"type":["integer","null"]},"status":{"enum":["done","skip"]},"seconds":{"type":"integer"}}}}}}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/routines/order":{"put":{"operationId":"orderRoutines","summary":"Put his routines in this order","security":[{"bearerToken":["account"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["routine_ids"],"properties":{"routine_ids":{"type":"array","items":{"type":"integer"}}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/routines/today":{"get":{"operationId":"routinesToday","summary":"Today's routines in start-time order, and whether each is done","security":[{"bearerToken":["account"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"today":{"type":"string"},"routines":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"title":{"type":"string"},"description":{"type":["string","null"]},"days_mask":{"type":"integer","description":"bit 0 = Monday … bit 6 = Sunday; 0 = anytime"},"start_minutes":{"type":["array","null"],"items":{"type":["integer","null"]},"description":"Start time per weekday (minutes after midnight), Monday first"},"remind":{"type":"boolean"},"color":{"type":["string","null"]},"icon":{"type":["string","null"]},"sort":{"type":"integer"},"step_count":{"type":"integer"},"total_seconds":{"type":"integer"},"due_today":{"type":"boolean"},"start_today":{"type":["integer","null"]},"done_today":{"type":"boolean"},"streak":{"type":"integer"},"steps":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"position":{"type":"integer"},"title":{"type":"string","maxLength":200},"seconds":{"type":["integer","null"],"minimum":1,"maximum":14400,"description":"Null: a checklist item, no timer"},"icon":{"type":["string","null"]},"notes":{"type":["string","null"],"maxLength":4000},"action":{"enum":["pray","journal","post","link","read","examen",null],"description":"pray: a prayer session; journal: a new entry; post: his run summary to his cohorts; link: open link_url; read: today's Scripture reading"},"link_url":{"type":["string","null"]},"discipline_id":{"type":["integer","null"],"description":"One of his 12:30+1 disciplines, kept when he finishes this step"},"reflect":{"type":"boolean","description":"Ask him for a reflection at this step (saved to his encrypted journal by the app)"}}}}}}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/routines/{id}":{"get":{"operationId":"routine","summary":"One routine: its steps and its last 30 runs","security":[{"bearerToken":["account"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Routine id","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"routine":{"type":"object","properties":{"id":{"type":"integer"},"title":{"type":"string"},"description":{"type":["string","null"]},"days_mask":{"type":"integer","description":"bit 0 = Monday … bit 6 = Sunday; 0 = anytime"},"start_minutes":{"type":["array","null"],"items":{"type":["integer","null"]},"description":"Start time per weekday (minutes after midnight), Monday first"},"remind":{"type":"boolean"},"color":{"type":["string","null"]},"icon":{"type":["string","null"]},"sort":{"type":"integer"},"step_count":{"type":"integer"},"total_seconds":{"type":"integer"},"due_today":{"type":"boolean"},"start_today":{"type":["integer","null"]},"done_today":{"type":"boolean"},"streak":{"type":"integer"},"steps":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"position":{"type":"integer"},"title":{"type":"string","maxLength":200},"seconds":{"type":["integer","null"],"minimum":1,"maximum":14400,"description":"Null: a checklist item, no timer"},"icon":{"type":["string","null"]},"notes":{"type":["string","null"],"maxLength":4000},"action":{"enum":["pray","journal","post","link","read","examen",null],"description":"pray: a prayer session; journal: a new entry; post: his run summary to his cohorts; link: open link_url; read: today's Scripture reading"},"link_url":{"type":["string","null"]},"discipline_id":{"type":["integer","null"],"description":"One of his 12:30+1 disciplines, kept when he finishes this step"},"reflect":{"type":"boolean","description":"Ask him for a reflection at this step (saved to his encrypted journal by the app)"}}}}}},"runs":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"routine_id":{"type":"integer"},"date":{"type":"string","format":"date"},"started_at":{"type":"string","format":"date-time"},"ended_at":{"type":["string","null"],"format":"date-time"},"completed":{"type":"boolean"},"posted":{"type":"boolean"},"steps":{"type":"array","items":{"type":"object","properties":{"position":{"type":"integer"},"step_id":{"type":["integer","null"]},"title":{"type":"string"},"planned_seconds":{"type":["integer","null"]},"status":{"enum":["done","skip"]},"seconds":{"type":"integer"}}}}}}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"updateRoutine","summary":"Change a routine (fields left out stay; steps replaces every step)","security":[{"bearerToken":["account"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Routine id","schema":{"type":"integer","minimum":1}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","maxLength":100},"description":{"type":["string","null"]},"days_mask":{"type":"integer"},"start_time":{"type":["integer","null"],"description":"The same start every day (minutes after midnight)"},"start_minutes":{"type":["array","null"],"items":{"type":["integer","null"]}},"remind":{"type":"boolean"},"color":{"type":["string","null"]},"icon":{"type":["string","null"]},"steps":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"position":{"type":"integer"},"title":{"type":"string","maxLength":200},"seconds":{"type":["integer","null"],"minimum":1,"maximum":14400,"description":"Null: a checklist item, no timer"},"icon":{"type":["string","null"]},"notes":{"type":["string","null"],"maxLength":4000},"action":{"enum":["pray","journal","post","link","read","examen",null],"description":"pray: a prayer session; journal: a new entry; post: his run summary to his cohorts; link: open link_url; read: today's Scripture reading"},"link_url":{"type":["string","null"]},"discipline_id":{"type":["integer","null"],"description":"One of his 12:30+1 disciplines, kept when he finishes this step"},"reflect":{"type":"boolean","description":"Ask him for a reflection at this step (saved to his encrypted journal by the app)"}}},"description":"Replaces every step; keep a step's id to keep it (and its history)"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"routine":{"type":"object","properties":{"id":{"type":"integer"},"title":{"type":"string"},"description":{"type":["string","null"]},"days_mask":{"type":"integer","description":"bit 0 = Monday … bit 6 = Sunday; 0 = anytime"},"start_minutes":{"type":["array","null"],"items":{"type":["integer","null"]},"description":"Start time per weekday (minutes after midnight), Monday first"},"remind":{"type":"boolean"},"color":{"type":["string","null"]},"icon":{"type":["string","null"]},"sort":{"type":"integer"},"step_count":{"type":"integer"},"total_seconds":{"type":"integer"},"due_today":{"type":"boolean"},"start_today":{"type":["integer","null"]},"done_today":{"type":"boolean"},"streak":{"type":"integer"},"steps":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"position":{"type":"integer"},"title":{"type":"string","maxLength":200},"seconds":{"type":["integer","null"],"minimum":1,"maximum":14400,"description":"Null: a checklist item, no timer"},"icon":{"type":["string","null"]},"notes":{"type":["string","null"],"maxLength":4000},"action":{"enum":["pray","journal","post","link","read","examen",null],"description":"pray: a prayer session; journal: a new entry; post: his run summary to his cohorts; link: open link_url; read: today's Scripture reading"},"link_url":{"type":["string","null"]},"discipline_id":{"type":["integer","null"],"description":"One of his 12:30+1 disciplines, kept when he finishes this step"},"reflect":{"type":"boolean","description":"Ask him for a reflection at this step (saved to his encrypted journal by the app)"}}}}}},"runs":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"routine_id":{"type":"integer"},"date":{"type":"string","format":"date"},"started_at":{"type":"string","format":"date-time"},"ended_at":{"type":["string","null"],"format":"date-time"},"completed":{"type":"boolean"},"posted":{"type":"boolean"},"steps":{"type":"array","items":{"type":"object","properties":{"position":{"type":"integer"},"step_id":{"type":["integer","null"]},"title":{"type":"string"},"planned_seconds":{"type":["integer","null"]},"status":{"enum":["done","skip"]},"seconds":{"type":"integer"}}}}}}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deleteRoutine","summary":"Delete a routine and its history","security":[{"bearerToken":["account"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Routine id","schema":{"type":"integer","minimum":1}}],"responses":{"204":{"description":"Deleted"},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/routines/{id}/duplicate":{"post":{"operationId":"duplicateRoutine","summary":"Copy a routine","security":[{"bearerToken":["account"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Routine id","schema":{"type":"integer","minimum":1}}],"responses":{"201":{"description":"Copied","content":{"application/json":{"schema":{"type":"object","properties":{"routine":{"type":"object","properties":{"id":{"type":"integer"},"title":{"type":"string"},"description":{"type":["string","null"]},"days_mask":{"type":"integer","description":"bit 0 = Monday … bit 6 = Sunday; 0 = anytime"},"start_minutes":{"type":["array","null"],"items":{"type":["integer","null"]},"description":"Start time per weekday (minutes after midnight), Monday first"},"remind":{"type":"boolean"},"color":{"type":["string","null"]},"icon":{"type":["string","null"]},"sort":{"type":"integer"},"step_count":{"type":"integer"},"total_seconds":{"type":"integer"},"due_today":{"type":"boolean"},"start_today":{"type":["integer","null"]},"done_today":{"type":"boolean"},"streak":{"type":"integer"},"steps":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"position":{"type":"integer"},"title":{"type":"string","maxLength":200},"seconds":{"type":["integer","null"],"minimum":1,"maximum":14400,"description":"Null: a checklist item, no timer"},"icon":{"type":["string","null"]},"notes":{"type":["string","null"],"maxLength":4000},"action":{"enum":["pray","journal","post","link","read","examen",null],"description":"pray: a prayer session; journal: a new entry; post: his run summary to his cohorts; link: open link_url; read: today's Scripture reading"},"link_url":{"type":["string","null"]},"discipline_id":{"type":["integer","null"],"description":"One of his 12:30+1 disciplines, kept when he finishes this step"},"reflect":{"type":"boolean","description":"Ask him for a reflection at this step (saved to his encrypted journal by the app)"}}}}}},"runs":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"routine_id":{"type":"integer"},"date":{"type":"string","format":"date"},"started_at":{"type":"string","format":"date-time"},"ended_at":{"type":["string","null"],"format":"date-time"},"completed":{"type":"boolean"},"posted":{"type":"boolean"},"steps":{"type":"array","items":{"type":"object","properties":{"position":{"type":"integer"},"step_id":{"type":["integer","null"]},"title":{"type":"string"},"planned_seconds":{"type":["integer","null"]},"status":{"enum":["done","skip"]},"seconds":{"type":"integer"}}}}}}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/routines/{id}/runs":{"post":{"operationId":"startRoutineRun","summary":"He starts a routine","security":[{"bearerToken":["account"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Routine id","schema":{"type":"integer","minimum":1}}],"responses":{"201":{"description":"Started","content":{"application/json":{"schema":{"type":"object","properties":{"run":{"type":"object","properties":{"id":{"type":"integer"},"routine_id":{"type":"integer"},"date":{"type":"string","format":"date"},"started_at":{"type":"string","format":"date-time"},"ended_at":{"type":["string","null"],"format":"date-time"},"completed":{"type":"boolean"},"posted":{"type":"boolean"},"steps":{"type":"array","items":{"type":"object","properties":{"position":{"type":"integer"},"step_id":{"type":["integer","null"]},"title":{"type":"string"},"planned_seconds":{"type":["integer","null"]},"status":{"enum":["done","skip"]},"seconds":{"type":"integer"}}}}}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/routines/runs/{id}/steps/{position}":{"put":{"operationId":"recordRoutineStep","summary":"One step's result (done or skipped, and its time); a done step keeps its 12:30+1 discipline","security":[{"bearerToken":["account"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Run id","schema":{"type":"integer","minimum":1}},{"name":"position","in":"path","required":true,"schema":{"type":"integer","minimum":0}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"enum":["done","skip"]},"seconds":{"type":"integer"},"note":{"type":"string","maxLength":4000,"description":"Only when his journal can't hold it: the app saves reflections to his encrypted journal when it can"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"kept_disciplines":{"type":"array","items":{"type":"integer"}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/routines/runs/{id}/finish":{"post":{"operationId":"finishRoutineRun","summary":"He finished (completed) or stopped partway","security":[{"bearerToken":["account"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Run id","schema":{"type":"integer","minimum":1}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"completed":{"type":"boolean","default":true}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"routine":{"type":"object","properties":{"id":{"type":"integer"},"title":{"type":"string"},"description":{"type":["string","null"]},"days_mask":{"type":"integer","description":"bit 0 = Monday … bit 6 = Sunday; 0 = anytime"},"start_minutes":{"type":["array","null"],"items":{"type":["integer","null"]},"description":"Start time per weekday (minutes after midnight), Monday first"},"remind":{"type":"boolean"},"color":{"type":["string","null"]},"icon":{"type":["string","null"]},"sort":{"type":"integer"},"step_count":{"type":"integer"},"total_seconds":{"type":"integer"},"due_today":{"type":"boolean"},"start_today":{"type":["integer","null"]},"done_today":{"type":"boolean"},"streak":{"type":"integer"},"steps":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"position":{"type":"integer"},"title":{"type":"string","maxLength":200},"seconds":{"type":["integer","null"],"minimum":1,"maximum":14400,"description":"Null: a checklist item, no timer"},"icon":{"type":["string","null"]},"notes":{"type":["string","null"],"maxLength":4000},"action":{"enum":["pray","journal","post","link","read","examen",null],"description":"pray: a prayer session; journal: a new entry; post: his run summary to his cohorts; link: open link_url; read: today's Scripture reading"},"link_url":{"type":["string","null"]},"discipline_id":{"type":["integer","null"],"description":"One of his 12:30+1 disciplines, kept when he finishes this step"},"reflect":{"type":"boolean","description":"Ask him for a reflection at this step (saved to his encrypted journal by the app)"}}}}}},"runs":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"routine_id":{"type":"integer"},"date":{"type":"string","format":"date"},"started_at":{"type":"string","format":"date-time"},"ended_at":{"type":["string","null"],"format":"date-time"},"completed":{"type":"boolean"},"posted":{"type":"boolean"},"steps":{"type":"array","items":{"type":"object","properties":{"position":{"type":"integer"},"step_id":{"type":["integer","null"]},"title":{"type":"string"},"planned_seconds":{"type":["integer","null"]},"status":{"enum":["done","skip"]},"seconds":{"type":"integer"}}}}}}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/routines/runs/{id}/summary":{"get":{"operationId":"routineRunSummary","summary":"The filled-in summary for his cohort, and which cohort channels it goes to","security":[{"bearerToken":["account"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Run id","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"run_id":{"type":"integer"},"text":{"type":"string"},"cohorts":{"type":"array","items":{"type":"object"}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/routines/runs/{id}/post":{"post":{"operationId":"postRoutineRun","summary":"Post the run's summary to his cohorts' Slack channels","security":[{"bearerToken":["account"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Run id","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"posted_to":{"type":"array","items":{"type":"string"}},"text":{"type":"string"}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Not in a cohort with a channel","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Slack unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/requests/{id}/updates":{"get":{"operationId":"requestUpdates","summary":"A request's updates, newest first","security":[{"bearerToken":["prayer:read"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Request id","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"updates":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"body":{"type":"string"},"created_at":{"type":"string","format":"date-time"}}}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"addRequestUpdate","summary":"Add an update to his request (the newest shows on top)","security":[{"bearerToken":["prayer:write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Request id","schema":{"type":"integer","minimum":1}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["body"],"properties":{"body":{"type":"string","maxLength":2000}}}}}},"responses":{"201":{"description":"Added","content":{"application/json":{"schema":{"type":"object","properties":{"request":{"$ref":"#/components/schemas/Request"}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not his","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/requests/{id}/merge":{"post":{"operationId":"mergeRequest","summary":"Fold this request (an Inbox note) into another of his requests as an update","security":[{"bearerToken":["prayer:write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Request id","schema":{"type":"integer","minimum":1}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["into"],"properties":{"into":{"type":"integer"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"request":{"$ref":"#/components/schemas/Request"}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not his","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/lists":{"get":{"operationId":"listLists","summary":"His personal lists, his cohorts' lists, and lists shared with him","security":[{"bearerToken":["prayer:read"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"lists":{"type":"array","items":{"$ref":"#/components/schemas/List"}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createList","summary":"Make a personal list","security":[{"bearerToken":["prayer:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","maxLength":100}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"list":{"$ref":"#/components/schemas/List"}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Missing scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/lists/{id}":{"get":{"operationId":"getList","summary":"One list","security":[{"bearerToken":["prayer:read"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"List id","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"list":{"$ref":"#/components/schemas/List"}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found or not visible","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/lists/{id}/requests/{external_id}":{"put":{"operationId":"upsertRequest","summary":"Create or update your request with this external id on this list (idempotent)","security":[{"bearerToken":["prayer:write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"List id","schema":{"type":"integer","minimum":1}},{"name":"external_id","in":"path","required":true,"description":"Your key for this request (1–200 characters), unique per list for you","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestInput"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","properties":{"request":{"$ref":"#/components/schemas/Request"}}}}}},"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"request":{"$ref":"#/components/schemas/Request"}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Missing scope, or a list shared with you read-only","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"List not found or not visible","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/requests":{"get":{"operationId":"queryRequests","summary":"Requests you can see, newest first, with filters and cursor paging","security":[{"bearerToken":["prayer:read"]}],"parameters":[{"name":"list","in":"query","schema":{"type":"integer"},"description":"A list id (a cohort list means everything on that cohort)"},{"name":"cohort","in":"query","schema":{"type":"integer"},"description":"A cohort id"},{"name":"author","in":"query","schema":{"type":"string"},"description":"A user id, or \"me\""},{"name":"status","in":"query","schema":{"enum":["active","answered","archived"]}},{"name":"since","in":"query","schema":{"type":"string","format":"date-time"},"description":"Created at or after (ISO 8601 date or time)"},{"name":"until","in":"query","schema":{"type":"string","format":"date-time"},"description":"Created before (ISO 8601 date or time)"},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string"},"description":"next_cursor from the previous page"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"requests":{"type":"array","items":{"$ref":"#/components/schemas/Request"}},"next_cursor":{"type":["string","null"]}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid filter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/requests/{id}":{"get":{"operationId":"getRequest","summary":"One request","security":[{"bearerToken":["prayer:read"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Request id","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"request":{"$ref":"#/components/schemas/Request"}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found or not visible","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deleteRequest","summary":"Delete one of your requests","security":[{"bearerToken":["prayer:write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Request id","schema":{"type":"integer","minimum":1}}],"responses":{"204":{"description":"Deleted"},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not yours","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"updateRequest","summary":"Change your request: text, kind, unspoken, visibility, status, tags, subject, or list (your own lists)","security":[{"bearerToken":["prayer:write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Request id","schema":{"type":"integer","minimum":1}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/RequestInput"},{"type":"object","properties":{"status":{"enum":["active","answered","archived"]}}}]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"request":{"$ref":"#/components/schemas/Request"}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not yours, or missing scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found or not visible","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/requests/{id}/answer":{"post":{"operationId":"answerRequest","summary":"Mark your request answered, with a note","security":[{"bearerToken":["prayer:write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Request id","schema":{"type":"integer","minimum":1}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"note":{"type":"string","maxLength":2000}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"request":{"$ref":"#/components/schemas/Request"}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not yours, or missing scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found or not visible","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/requests/{id}/prayed":{"post":{"operationId":"recordPrayed","summary":"Record that you prayed for a request you can see","security":[{"bearerToken":["prayer:write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Request id","schema":{"type":"integer","minimum":1}}],"responses":{"201":{"description":"Recorded","content":{"application/json":{"schema":{"type":"object","properties":{"request_id":{"type":"integer"},"prayed_at":{"type":"string","format":"date-time"},"times_you_prayed":{"type":"integer"}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found or not visible","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/shares":{"get":{"operationId":"listShares","summary":"Shares you granted and shares granted to you (live ones)","security":[{"bearerToken":["shares:read"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"granted":{"type":"array","items":{"$ref":"#/components/schemas/Share"}},"received":{"type":"array","items":{"$ref":"#/components/schemas/Share"}}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createShare","summary":"Share one of your requests or lists with a brother (user) or one of your cohorts","security":[{"bearerToken":["shares:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["resource_type","resource_id","target_type","target_id"],"properties":{"resource_type":{"enum":["request","list"]},"resource_id":{"type":"integer"},"target_type":{"enum":["user","cohort"]},"target_id":{"type":"integer","description":"A brother's user id (see /v1/me) or one of your cohort ids"}}}}}},"responses":{"201":{"description":"Shared","content":{"application/json":{"schema":{"type":"object","properties":{"share":{"$ref":"#/components/schemas/Share"}}}}}},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not yours, or not a brother / not your cohort","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/shares/{id}":{"delete":{"operationId":"revokeShare","summary":"Revoke a share you granted","security":[{"bearerToken":["shares:write"]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Share id","schema":{"type":"integer","minimum":1}}],"responses":{"204":{"description":"Revoked"},"401":{"description":"No live token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found, or not yours","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (per token, per minute)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}