{"openapi":"3.1.0","info":{"title":"Training program links","version":"1.0.0","description":"Anonymous immutable program creation on enabled training-family hosts. No account, subscription or model call. Legacy encoded URLs remain supported by the builder. Unlisted links are public to anyone with the token and do not appear in the template grid. Do not put private health information in shared programs."},"servers":[{"url":"/","description":"Use the selected enabled training site origin."}],"paths":{"/api/training/programs":{"post":{"operationId":"createTrainingProgram","summary":"Create a program and get a short /workout/{token} link","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["title","program"],"additionalProperties":false,"properties":{"title":{"type":"string","minLength":1,"maxLength":160},"program":{"$schema":"https://json-schema.org/draft/2020-12/schema","title":"Training ProgramV1","type":"object","additionalProperties":false,"required":["v","u","m","c","weeks"],"properties":{"v":{"const":1},"u":{"enum":["lb","kg"]},"m":{"type":"object","maxProperties":100,"propertyNames":{"minLength":1,"maxLength":160},"additionalProperties":{"anyOf":[{"type":"string","maxLength":48},{"type":"number","minimum":-1000000,"maximum":1000000}],"description":"Strings are preserved exactly, including decimals, ranges and AMRAP. Finite numbers become their decimal string representation on read."}},"c":{"type":"array","minItems":1,"maxItems":52,"items":{"type":"object","required":["n"],"additionalProperties":false,"properties":{"n":{"type":"string","maxLength":120}}}},"weeks":{"type":"array","minItems":1,"maxItems":52,"items":{"type":"object","required":["c","days"],"additionalProperties":false,"properties":{"c":{"type":"integer","minimum":0,"maximum":51,"description":"Must reference an existing entry in c."},"days":{"type":"array","minItems":1,"maxItems":7,"items":{"type":"object","required":["label","rows"],"additionalProperties":false,"properties":{"label":{"type":"string","maxLength":120},"rows":{"type":"array","minItems":0,"maxItems":40,"items":{"type":"object","additionalProperties":false,"required":["ex","mode","sets","reps","load","pct","rpe","rest"],"properties":{"ex":{"type":"string","maxLength":160},"mode":{"type":"string","maxLength":48},"sets":{"anyOf":[{"type":"string","maxLength":48},{"type":"number","minimum":-1000000,"maximum":1000000}],"description":"Strings are preserved exactly, including decimals, ranges and AMRAP. Finite numbers become their decimal string representation on read."},"reps":{"anyOf":[{"type":"string","maxLength":48},{"type":"number","minimum":-1000000,"maximum":1000000}],"description":"Strings are preserved exactly, including decimals, ranges and AMRAP. Finite numbers become their decimal string representation on read."},"load":{"anyOf":[{"type":"string","maxLength":48},{"type":"number","minimum":-1000000,"maximum":1000000}],"description":"Strings are preserved exactly, including decimals, ranges and AMRAP. Finite numbers become their decimal string representation on read."},"pct":{"anyOf":[{"type":"string","maxLength":48},{"type":"number","minimum":-1000000,"maximum":1000000}],"description":"Strings are preserved exactly, including decimals, ranges and AMRAP. Finite numbers become their decimal string representation on read."},"rpe":{"anyOf":[{"type":"string","maxLength":48},{"type":"number","minimum":-1000000,"maximum":1000000}],"description":"Strings are preserved exactly, including decimals, ranges and AMRAP. Finite numbers become their decimal string representation on read."},"rest":{"anyOf":[{"type":"string","maxLength":48},{"type":"number","minimum":-1000000,"maximum":1000000}],"description":"Strings are preserved exactly, including decimals, ranges and AMRAP. Finite numbers become their decimal string representation on read."}}}}}}}}}}},"description":"Decoded legacy ProgramV1. Maximum 2000 total exercise rows and 262144 UTF-8 request bytes. Empty rows and single-week authored programs are valid. Generated catalog programs have separate quality requirements."},"source":{"enum":["agent","builder"],"default":"agent"},"agent":{"enum":["chatgpt","claude","perplexity","cursor","grok","other"]}}}}}},"responses":{"200":{"description":"Identical title/program/source already stored on this site; the same token is returned.","content":{"application/json":{"schema":{"type":"object","required":["id","token","title","program","source","agent","created_at","share_url","api_url"],"properties":{"id":{"type":"integer","minimum":1},"token":{"type":"string","pattern":"^[A-Za-z0-9_-]{24}$"},"title":{"type":"string","minLength":1,"maxLength":160},"program":{"$schema":"https://json-schema.org/draft/2020-12/schema","title":"Training ProgramV1","type":"object","additionalProperties":false,"required":["v","u","m","c","weeks"],"properties":{"v":{"const":1},"u":{"enum":["lb","kg"]},"m":{"type":"object","maxProperties":100,"propertyNames":{"minLength":1,"maxLength":160},"additionalProperties":{"anyOf":[{"type":"string","maxLength":48},{"type":"number","minimum":-1000000,"maximum":1000000}],"description":"Strings are preserved exactly, including decimals, ranges and AMRAP. Finite numbers become their decimal string representation on read."}},"c":{"type":"array","minItems":1,"maxItems":52,"items":{"type":"object","required":["n"],"additionalProperties":false,"properties":{"n":{"type":"string","maxLength":120}}}},"weeks":{"type":"array","minItems":1,"maxItems":52,"items":{"type":"object","required":["c","days"],"additionalProperties":false,"properties":{"c":{"type":"integer","minimum":0,"maximum":51,"description":"Must reference an existing entry in c."},"days":{"type":"array","minItems":1,"maxItems":7,"items":{"type":"object","required":["label","rows"],"additionalProperties":false,"properties":{"label":{"type":"string","maxLength":120},"rows":{"type":"array","minItems":0,"maxItems":40,"items":{"type":"object","additionalProperties":false,"required":["ex","mode","sets","reps","load","pct","rpe","rest"],"properties":{"ex":{"type":"string","maxLength":160},"mode":{"type":"string","maxLength":48},"sets":{"anyOf":[{"type":"string","maxLength":48},{"type":"number","minimum":-1000000,"maximum":1000000}],"description":"Strings are preserved exactly, including decimals, ranges and AMRAP. Finite numbers become their decimal string representation on read."},"reps":{"anyOf":[{"type":"string","maxLength":48},{"type":"number","minimum":-1000000,"maximum":1000000}],"description":"Strings are preserved exactly, including decimals, ranges and AMRAP. Finite numbers become their decimal string representation on read."},"load":{"anyOf":[{"type":"string","maxLength":48},{"type":"number","minimum":-1000000,"maximum":1000000}],"description":"Strings are preserved exactly, including decimals, ranges and AMRAP. Finite numbers become their decimal string representation on read."},"pct":{"anyOf":[{"type":"string","maxLength":48},{"type":"number","minimum":-1000000,"maximum":1000000}],"description":"Strings are preserved exactly, including decimals, ranges and AMRAP. Finite numbers become their decimal string representation on read."},"rpe":{"anyOf":[{"type":"string","maxLength":48},{"type":"number","minimum":-1000000,"maximum":1000000}],"description":"Strings are preserved exactly, including decimals, ranges and AMRAP. Finite numbers become their decimal string representation on read."},"rest":{"anyOf":[{"type":"string","maxLength":48},{"type":"number","minimum":-1000000,"maximum":1000000}],"description":"Strings are preserved exactly, including decimals, ranges and AMRAP. Finite numbers become their decimal string representation on read."}}}}}}}}}}},"description":"Decoded legacy ProgramV1. Maximum 2000 total exercise rows and 262144 UTF-8 request bytes. Empty rows and single-week authored programs are valid. Generated catalog programs have separate quality requirements."},"source":{"enum":["agent","builder","generated"]},"agent":{"anyOf":[{"enum":["chatgpt","claude","perplexity","cursor","grok","other"]},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"deduplicated":{"type":"boolean"},"share_url":{"type":"string","format":"uri","description":"Open this exact returned URL in the browser. Its path is /workout/{token} on the selected training host."},"api_url":{"type":"string","format":"uri","description":"Read the program through this exact returned URL."}}}}}},"201":{"description":"Immutable program, token, share_url, api_url, source and creation time. Store the returned share_url; do not invent a token.","content":{"application/json":{"schema":{"type":"object","required":["id","token","title","program","source","agent","created_at","share_url","api_url"],"properties":{"id":{"type":"integer","minimum":1},"token":{"type":"string","pattern":"^[A-Za-z0-9_-]{24}$"},"title":{"type":"string","minLength":1,"maxLength":160},"program":{"$schema":"https://json-schema.org/draft/2020-12/schema","title":"Training ProgramV1","type":"object","additionalProperties":false,"required":["v","u","m","c","weeks"],"properties":{"v":{"const":1},"u":{"enum":["lb","kg"]},"m":{"type":"object","maxProperties":100,"propertyNames":{"minLength":1,"maxLength":160},"additionalProperties":{"anyOf":[{"type":"string","maxLength":48},{"type":"number","minimum":-1000000,"maximum":1000000}],"description":"Strings are preserved exactly, including decimals, ranges and AMRAP. Finite numbers become their decimal string representation on read."}},"c":{"type":"array","minItems":1,"maxItems":52,"items":{"type":"object","required":["n"],"additionalProperties":false,"properties":{"n":{"type":"string","maxLength":120}}}},"weeks":{"type":"array","minItems":1,"maxItems":52,"items":{"type":"object","required":["c","days"],"additionalProperties":false,"properties":{"c":{"type":"integer","minimum":0,"maximum":51,"description":"Must reference an existing entry in c."},"days":{"type":"array","minItems":1,"maxItems":7,"items":{"type":"object","required":["label","rows"],"additionalProperties":false,"properties":{"label":{"type":"string","maxLength":120},"rows":{"type":"array","minItems":0,"maxItems":40,"items":{"type":"object","additionalProperties":false,"required":["ex","mode","sets","reps","load","pct","rpe","rest"],"properties":{"ex":{"type":"string","maxLength":160},"mode":{"type":"string","maxLength":48},"sets":{"anyOf":[{"type":"string","maxLength":48},{"type":"number","minimum":-1000000,"maximum":1000000}],"description":"Strings are preserved exactly, including decimals, ranges and AMRAP. Finite numbers become their decimal string representation on read."},"reps":{"anyOf":[{"type":"string","maxLength":48},{"type":"number","minimum":-1000000,"maximum":1000000}],"description":"Strings are preserved exactly, including decimals, ranges and AMRAP. Finite numbers become their decimal string representation on read."},"load":{"anyOf":[{"type":"string","maxLength":48},{"type":"number","minimum":-1000000,"maximum":1000000}],"description":"Strings are preserved exactly, including decimals, ranges and AMRAP. Finite numbers become their decimal string representation on read."},"pct":{"anyOf":[{"type":"string","maxLength":48},{"type":"number","minimum":-1000000,"maximum":1000000}],"description":"Strings are preserved exactly, including decimals, ranges and AMRAP. Finite numbers become their decimal string representation on read."},"rpe":{"anyOf":[{"type":"string","maxLength":48},{"type":"number","minimum":-1000000,"maximum":1000000}],"description":"Strings are preserved exactly, including decimals, ranges and AMRAP. Finite numbers become their decimal string representation on read."},"rest":{"anyOf":[{"type":"string","maxLength":48},{"type":"number","minimum":-1000000,"maximum":1000000}],"description":"Strings are preserved exactly, including decimals, ranges and AMRAP. Finite numbers become their decimal string representation on read."}}}}}}}}}}},"description":"Decoded legacy ProgramV1. Maximum 2000 total exercise rows and 262144 UTF-8 request bytes. Empty rows and single-week authored programs are valid. Generated catalog programs have separate quality requirements."},"source":{"enum":["agent","builder","generated"]},"agent":{"anyOf":[{"enum":["chatgpt","claude","perplexity","cursor","grok","other"]},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"deduplicated":{"type":"boolean"},"share_url":{"type":"string","format":"uri","description":"Open this exact returned URL in the browser. Its path is /workout/{token} on the selected training host."},"api_url":{"type":"string","format":"uri","description":"Read the program through this exact returned URL."}}}}}},"400":{"description":"Request is not valid JSON.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string"},"path":{"type":"string"},"retry_after":{"type":"integer"}}}}}},"403":{"description":"Origin is not permitted.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string"},"path":{"type":"string"},"retry_after":{"type":"integer"}}}}}},"404":{"description":"Host is not an enabled training-family site.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string"},"path":{"type":"string"},"retry_after":{"type":"integer"}}}}}},"405":{"description":"Method is not supported. See Allow header.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string"},"path":{"type":"string"},"retry_after":{"type":"integer"}}}}}},"413":{"description":"Request exceeds 256 KiB.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string"},"path":{"type":"string"},"retry_after":{"type":"integer"}}}}}},"415":{"description":"Use application/json without content encoding.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string"},"path":{"type":"string"},"retry_after":{"type":"integer"}}}}}},"422":{"description":"Validation failed; error and path identify the unsupported field.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string"},"path":{"type":"string"},"retry_after":{"type":"integer"}}}}}},"429":{"description":"Rate limit exceeded; retry after the Retry-After seconds.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string"},"path":{"type":"string"},"retry_after":{"type":"integer"}}}}}},"503":{"description":"Training storage or required migration unavailable.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string"},"path":{"type":"string"},"retry_after":{"type":"integer"}}}}}}}}},"/api/training/programs/{token}":{"get":{"operationId":"readTrainingProgram","summary":"Read an immutable program through any enabled training-family host","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{24}$"}}],"responses":{"200":{"description":"Immutable program, token, share_url, api_url, source and creation time. Store the returned share_url; do not invent a token.","content":{"application/json":{"schema":{"type":"object","required":["id","token","title","program","source","agent","created_at","share_url","api_url"],"properties":{"id":{"type":"integer","minimum":1},"token":{"type":"string","pattern":"^[A-Za-z0-9_-]{24}$"},"title":{"type":"string","minLength":1,"maxLength":160},"program":{"$schema":"https://json-schema.org/draft/2020-12/schema","title":"Training ProgramV1","type":"object","additionalProperties":false,"required":["v","u","m","c","weeks"],"properties":{"v":{"const":1},"u":{"enum":["lb","kg"]},"m":{"type":"object","maxProperties":100,"propertyNames":{"minLength":1,"maxLength":160},"additionalProperties":{"anyOf":[{"type":"string","maxLength":48},{"type":"number","minimum":-1000000,"maximum":1000000}],"description":"Strings are preserved exactly, including decimals, ranges and AMRAP. Finite numbers become their decimal string representation on read."}},"c":{"type":"array","minItems":1,"maxItems":52,"items":{"type":"object","required":["n"],"additionalProperties":false,"properties":{"n":{"type":"string","maxLength":120}}}},"weeks":{"type":"array","minItems":1,"maxItems":52,"items":{"type":"object","required":["c","days"],"additionalProperties":false,"properties":{"c":{"type":"integer","minimum":0,"maximum":51,"description":"Must reference an existing entry in c."},"days":{"type":"array","minItems":1,"maxItems":7,"items":{"type":"object","required":["label","rows"],"additionalProperties":false,"properties":{"label":{"type":"string","maxLength":120},"rows":{"type":"array","minItems":0,"maxItems":40,"items":{"type":"object","additionalProperties":false,"required":["ex","mode","sets","reps","load","pct","rpe","rest"],"properties":{"ex":{"type":"string","maxLength":160},"mode":{"type":"string","maxLength":48},"sets":{"anyOf":[{"type":"string","maxLength":48},{"type":"number","minimum":-1000000,"maximum":1000000}],"description":"Strings are preserved exactly, including decimals, ranges and AMRAP. Finite numbers become their decimal string representation on read."},"reps":{"anyOf":[{"type":"string","maxLength":48},{"type":"number","minimum":-1000000,"maximum":1000000}],"description":"Strings are preserved exactly, including decimals, ranges and AMRAP. Finite numbers become their decimal string representation on read."},"load":{"anyOf":[{"type":"string","maxLength":48},{"type":"number","minimum":-1000000,"maximum":1000000}],"description":"Strings are preserved exactly, including decimals, ranges and AMRAP. Finite numbers become their decimal string representation on read."},"pct":{"anyOf":[{"type":"string","maxLength":48},{"type":"number","minimum":-1000000,"maximum":1000000}],"description":"Strings are preserved exactly, including decimals, ranges and AMRAP. Finite numbers become their decimal string representation on read."},"rpe":{"anyOf":[{"type":"string","maxLength":48},{"type":"number","minimum":-1000000,"maximum":1000000}],"description":"Strings are preserved exactly, including decimals, ranges and AMRAP. Finite numbers become their decimal string representation on read."},"rest":{"anyOf":[{"type":"string","maxLength":48},{"type":"number","minimum":-1000000,"maximum":1000000}],"description":"Strings are preserved exactly, including decimals, ranges and AMRAP. Finite numbers become their decimal string representation on read."}}}}}}}}}}},"description":"Decoded legacy ProgramV1. Maximum 2000 total exercise rows and 262144 UTF-8 request bytes. Empty rows and single-week authored programs are valid. Generated catalog programs have separate quality requirements."},"source":{"enum":["agent","builder","generated"]},"agent":{"anyOf":[{"enum":["chatgpt","claude","perplexity","cursor","grok","other"]},{"type":"null"}]},"created_at":{"type":"string","format":"date-time"},"deduplicated":{"type":"boolean"},"share_url":{"type":"string","format":"uri","description":"Open this exact returned URL in the browser. Its path is /workout/{token} on the selected training host."},"api_url":{"type":"string","format":"uri","description":"Read the program through this exact returned URL."}}}}}},"404":{"description":"Unknown token or non-training host.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string"},"path":{"type":"string"},"retry_after":{"type":"integer"}}}}}}}}},"/api/training/schema":{"get":{"operationId":"trainingProgramSchema","responses":{"200":{"description":"ProgramV1 JSON Schema","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/training/openapi.json":{"get":{"operationId":"trainingOpenApi","responses":{"200":{"description":"This OpenAPI 3.1 contract."}}}}}}