diff --git a/api-reference/openapi/templates.json b/api-reference/openapi/templates.json new file mode 100644 index 0000000..880e91c --- /dev/null +++ b/api-reference/openapi/templates.json @@ -0,0 +1,720 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Recoup API - Templates", + "description": "API documentation for managing reusable templates on the Recoup platform. Templates capture a prompt, description, and tags that can be shared with other accounts or kept private.", + "license": { + "name": "MIT" + }, + "version": "1.0.0" + }, + "servers": [ + { + "url": "https://api.recoupable.com" + } + ], + "security": [ + { + "apiKeyAuth": [] + }, + { + "bearerAuth": [] + } + ], + "paths": { + "/api/agents/templates": { + "get": { + "summary": "List templates", + "description": "Retrieve every template visible to the authenticated account. The response combines templates the account owns, public templates created by other accounts, and private templates that have been shared with the authenticated account's email.", + "security": [ + { + "apiKeyAuth": [] + }, + { + "bearerAuth": [] + } + ], + "responses": { + "200": { + "description": "Templates retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListTemplatesResponse" + } + } + } + }, + "401": { + "description": "Unauthorized - missing or invalid credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + }, + "post": { + "summary": "Create a template", + "description": "Create a new template owned by the authenticated account. When `is_private` is true, the optional `share_emails` array grants explicit read access to the listed accounts; for public templates the field is ignored.", + "security": [ + { + "apiKeyAuth": [] + }, + { + "bearerAuth": [] + } + ], + "requestBody": { + "description": "Template fields", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateTemplateRequest" + } + } + } + }, + "responses": { + "201": { + "description": "Template created successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TemplateResponse" + } + } + } + }, + "400": { + "description": "Bad request - validation failed or required fields missing", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized - missing or invalid credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/api/agents/templates/{id}": { + "patch": { + "summary": "Update a template", + "description": "Update fields on an existing template owned by the authenticated account. All body fields are optional and only the supplied fields are modified. Providing `share_emails` replaces the existing share list for the template.", + "security": [ + { + "apiKeyAuth": [] + }, + { + "bearerAuth": [] + } + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The unique identifier (UUID) of the template to update", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "requestBody": { + "description": "Fields to update on the template", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateTemplateRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Template updated successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TemplateResponse" + } + } + } + }, + "400": { + "description": "Bad request - validation failed", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized - missing or invalid credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden - the authenticated account does not own this template", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Template not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + }, + "delete": { + "summary": "Delete a template", + "description": "Permanently delete an template. Only the owner of the template may perform this action. Associated share records and favorite entries are removed as part of the deletion.", + "security": [ + { + "apiKeyAuth": [] + }, + { + "bearerAuth": [] + } + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The unique identifier (UUID) of the template to delete", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Template deleted successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "401": { + "description": "Unauthorized - missing or invalid credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden - the authenticated account does not own this template", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Template not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/api/agents/templates/{id}/favorite": { + "put": { + "summary": "Toggle favorite on a template", + "description": "Mark or unmark an template as a favorite for the authenticated account. The endpoint is idempotent - calling it repeatedly with the same `is_favourite` value has no additional effect. The caller must be able to see the template (own it, the template is public, or it has been shared with them).", + "security": [ + { + "apiKeyAuth": [] + }, + { + "bearerAuth": [] + } + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The unique identifier (UUID) of the template to favorite or unfavorite", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "requestBody": { + "description": "Desired favorite state", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ToggleFavoriteRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Favorite state updated successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request - validation failed", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized - missing or invalid credentials", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden - the template is private and has not been shared with the authenticated account", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Template not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + } + }, + "components": { + "securitySchemes": { + "bearerAuth": { + "type": "http", + "scheme": "bearer" + }, + "apiKeyAuth": { + "type": "apiKey", + "in": "header", + "name": "x-api-key", + "description": "Your Recoup API key. [Learn more](/quickstart#api-keys)." + } + }, + "schemas": { + "TemplateCreator": { + "type": ["object", "null"], + "description": "The account that created the template. May be null when the creator account is unavailable.", + "required": [ + "id", + "name", + "image", + "is_admin" + ], + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier of the creator account" + }, + "name": { + "type": ["string", "null"], + "description": "Display name of the creator account" + }, + "image": { + "type": ["string", "null"], + "description": "Profile image URL of the creator account" + }, + "is_admin": { + "type": "boolean", + "description": "Whether the creator is a Recoup admin (their account email is on the platform admin allow-list)" + } + } + }, + "Template": { + "type": "object", + "required": [ + "id", + "title", + "description", + "prompt", + "tags", + "creator", + "is_private", + "is_favourite", + "favorites_count", + "shared_emails", + "created_at", + "updated_at" + ], + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier of the template" + }, + "title": { + "type": "string", + "description": "Short human-readable title for the template (3-50 characters)" + }, + "description": { + "type": "string", + "description": "Description of what the template does (10-200 characters)" + }, + "prompt": { + "type": "string", + "description": "The agent prompt body (20-10000 characters)" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Free-form tags used to categorize the template. Empty array when there are no tags." + }, + "creator": { + "$ref": "#/components/schemas/TemplateCreator" + }, + "is_private": { + "type": "boolean", + "description": "Whether the template is restricted to the creator and explicitly shared accounts" + }, + "is_favourite": { + "type": "boolean", + "description": "Whether the authenticated account has favorited this template" + }, + "favorites_count": { + "type": "integer", + "description": "Total number of accounts that have favorited this template" + }, + "shared_emails": { + "type": "array", + "items": { + "type": "string", + "format": "email" + }, + "description": "Emails the template has been shared with. Only populated for private templates the authenticated account owns; empty for public templates and for private templates shared with the caller." + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "ISO 8601 timestamp of when the template was created" + }, + "updated_at": { + "type": ["string", "null"], + "format": "date-time", + "description": "ISO 8601 timestamp of when the template was last updated" + } + } + }, + "CreateTemplateRequest": { + "type": "object", + "required": [ + "title", + "description", + "prompt", + "tags", + "is_private" + ], + "properties": { + "title": { + "type": "string", + "minLength": 3, + "maxLength": 50, + "description": "Short human-readable title for the template" + }, + "description": { + "type": "string", + "minLength": 10, + "maxLength": 200, + "description": "Description of what the template does" + }, + "prompt": { + "type": "string", + "minLength": 20, + "maxLength": 10000, + "description": "The agent prompt body" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Free-form tags used to categorize the template. Pass an empty array if there are no tags." + }, + "is_private": { + "type": "boolean", + "description": "When true, the template is restricted to the creator and the accounts listed in `share_emails`" + }, + "share_emails": { + "type": "array", + "items": { + "type": "string", + "format": "email" + }, + "description": "Emails to grant access to. Only applied when `is_private` is true. Defaults to an empty array when omitted." + } + } + }, + "UpdateTemplateRequest": { + "type": "object", + "description": "All fields are optional. Only supplied fields are updated.", + "properties": { + "title": { + "type": "string", + "minLength": 3, + "maxLength": 50, + "description": "Short human-readable title for the template" + }, + "description": { + "type": "string", + "minLength": 10, + "maxLength": 200, + "description": "Description of what the template does" + }, + "prompt": { + "type": "string", + "minLength": 20, + "maxLength": 10000, + "description": "The agent prompt body" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Free-form tags used to categorize the template. Pass an empty array to clear tags." + }, + "is_private": { + "type": "boolean", + "description": "When true, the template is restricted to the creator and the accounts listed in `share_emails`" + }, + "share_emails": { + "type": "array", + "items": { + "type": "string", + "format": "email" + }, + "description": "Replaces the existing share list for the template. Only applied when the template is (or becomes) private." + } + } + }, + "ToggleFavoriteRequest": { + "type": "object", + "required": [ + "is_favourite" + ], + "properties": { + "is_favourite": { + "type": "boolean", + "description": "Desired favorite state for the authenticated account" + } + } + }, + "ListTemplatesResponse": { + "type": "object", + "required": [ + "status", + "templates" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "Status of the request" + }, + "templates": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Template" + }, + "description": "Templates accessible to the authenticated account (own, public, and shared)" + } + } + }, + "TemplateResponse": { + "type": "object", + "required": [ + "status", + "template" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "Status of the request" + }, + "template": { + "$ref": "#/components/schemas/Template" + } + } + }, + "SuccessResponse": { + "type": "object", + "required": [ + "status" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "success" + ], + "description": "Status of the request" + } + } + }, + "ErrorResponse": { + "type": "object", + "required": [ + "status", + "error" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "error" + ], + "description": "Status of the request" + }, + "error": { + "type": "string", + "description": "Human-readable error message" + }, + "missing_fields": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Names of required fields that were missing from the request, when applicable" + } + } + } + } + } +} diff --git a/api-reference/templates/create.mdx b/api-reference/templates/create.mdx new file mode 100644 index 0000000..f140c58 --- /dev/null +++ b/api-reference/templates/create.mdx @@ -0,0 +1,4 @@ +--- +title: 'Create Template' +openapi: '/api-reference/openapi/templates.json POST /api/agents/templates' +--- diff --git a/api-reference/templates/delete.mdx b/api-reference/templates/delete.mdx new file mode 100644 index 0000000..f03a39a --- /dev/null +++ b/api-reference/templates/delete.mdx @@ -0,0 +1,4 @@ +--- +title: 'Delete Template' +openapi: '/api-reference/openapi/templates.json DELETE /api/agents/templates/{id}' +--- diff --git a/api-reference/templates/favorite.mdx b/api-reference/templates/favorite.mdx new file mode 100644 index 0000000..20be00e --- /dev/null +++ b/api-reference/templates/favorite.mdx @@ -0,0 +1,4 @@ +--- +title: 'Favorite Template' +openapi: '/api-reference/openapi/templates.json PUT /api/agents/templates/{id}/favorite' +--- diff --git a/api-reference/templates/list.mdx b/api-reference/templates/list.mdx new file mode 100644 index 0000000..bea110c --- /dev/null +++ b/api-reference/templates/list.mdx @@ -0,0 +1,4 @@ +--- +title: 'List Templates' +openapi: '/api-reference/openapi/templates.json GET /api/agents/templates' +--- diff --git a/api-reference/templates/update.mdx b/api-reference/templates/update.mdx new file mode 100644 index 0000000..257050e --- /dev/null +++ b/api-reference/templates/update.mdx @@ -0,0 +1,4 @@ +--- +title: 'Update Template' +openapi: '/api-reference/openapi/templates.json PATCH /api/agents/templates/{id}' +--- diff --git a/docs.json b/docs.json index 458ada9..e430c00 100644 --- a/docs.json +++ b/docs.json @@ -242,6 +242,16 @@ "content-agent" ] }, + { + "group": "Templates", + "pages": [ + "api-reference/templates/list", + "api-reference/templates/create", + "api-reference/templates/update", + "api-reference/templates/delete", + "api-reference/templates/favorite" + ] + }, { "group": "Tasks", "pages": [