openapi: 3.2.0 info: title: Axonflow Templates API version: 11.1.0 contact: name: AxonFlow Support url: https://getaxonflow.com/support license: name: Business Source License 1.1 url: https://github.com/getaxonflow/axonflow/blob/main/LICENSE description: 'Operations tagged Templates across 2 of this provider''s published API definitions: axonflow-policy-api.yaml, axonflow-policy-openapi.yml. Each path carries the servers of the definition it was published in.' servers: - url: https://agent.getaxonflow.com description: Production (Agent single entry point, ADR-024) - url: http://localhost:8080 description: Local development (Agent single entry point) - url: http://localhost:8081 description: Orchestrator direct (internal only) tags: - name: Templates description: Policy templates for quick policy creation paths: /api/v1/templates: get: deprecated: true tags: - Templates summary: List policy templates description: 'Retrieve available policy templates for quick policy creation. Templates provide pre-configured policies for common use cases like HIPAA compliance, GDPR data protection, and rate limiting.' operationId: listTemplates parameters: - $ref: '#/components/parameters/TenantID' - name: category in: query description: Filter by template category schema: type: string enum: - general - security - compliance - content_safety - rate_limiting - access_control - data_protection - custom - name: search in: query description: Search in name and description schema: type: string - name: tags in: query description: Comma-separated tags to filter by schema: type: string - name: active in: query description: Filter by active status schema: type: boolean - name: builtin in: query description: Filter by builtin status schema: type: boolean - name: page in: query description: Page number (1-indexed) schema: type: integer minimum: 1 default: 1 - name: page_size in: query description: Number of items per page schema: type: integer minimum: 1 default: 20 maximum: 100 responses: '200': description: List of templates content: application/json: schema: $ref: '#/components/schemas/TemplatesListResponse' '401': $ref: '#/components/responses/Unauthorized' '500': $ref: '#/components/responses/InternalError' servers: - url: https://agent.getaxonflow.com description: Production (Agent single entry point, ADR-024) - url: http://localhost:8080 description: Local development (Agent single entry point) - url: http://localhost:8081 description: Orchestrator direct (internal only) /api/v1/templates/{id}: parameters: - $ref: '#/components/parameters/TemplateID' - $ref: '#/components/parameters/TenantID' get: deprecated: true tags: - Templates summary: Get a template description: Retrieve a single policy template by ID operationId: getTemplate responses: '200': description: Template details content: application/json: schema: $ref: '#/components/schemas/TemplateResponse' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalError' servers: - url: https://agent.getaxonflow.com description: Production (Agent single entry point, ADR-024) - url: http://localhost:8080 description: Local development (Agent single entry point) - url: http://localhost:8081 description: Orchestrator direct (internal only) /api/v1/templates/{id}/apply: parameters: - $ref: '#/components/parameters/TemplateID' - $ref: '#/components/parameters/TenantID' post: deprecated: true tags: - Templates summary: Apply a template description: 'Create a new policy from a template by providing variable values. Templates may have required and optional variables that customize the generated policy. **v11:** the generated policy is written to `dynamic_policies`, which `migrations/core/172` makes read-only to the application roles, so on a deployment whose database connection cannot write it this route answers `409 LEGACY_POLICY_WRITE_FROZEN` before the request body is read, whatever it contains, as the policy write routes do. An owner-role deployment still applies.' operationId: applyTemplate parameters: - $ref: '#/components/parameters/UserID' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ApplyTemplateRequest' example: policy_name: Production Rate Limit description: Rate limiting for production API variables: threshold: 1000 window_seconds: 60 enabled: true priority: 75 responses: '201': description: Policy created from template content: application/json: schema: $ref: '#/components/schemas/ApplyTemplateResponse' '400': $ref: '#/components/responses/ValidationError' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/LegacyPolicyWriteFrozen' '500': $ref: '#/components/responses/InternalError' servers: - url: https://agent.getaxonflow.com description: Production (Agent single entry point, ADR-024) - url: http://localhost:8080 description: Local development (Agent single entry point) - url: http://localhost:8081 description: Orchestrator direct (internal only) /api/v1/templates/categories: get: deprecated: true tags: - Templates summary: List template categories description: Retrieve all available template categories operationId: listTemplateCategories parameters: - $ref: '#/components/parameters/TenantID' responses: '200': description: List of categories content: application/json: schema: type: object properties: categories: type: array items: type: string example: - general - security - compliance - content_safety - rate_limiting - access_control - data_protection - custom '401': $ref: '#/components/responses/Unauthorized' '500': $ref: '#/components/responses/InternalError' servers: - url: https://agent.getaxonflow.com description: Production (Agent single entry point, ADR-024) - url: http://localhost:8080 description: Local development (Agent single entry point) - url: http://localhost:8081 description: Orchestrator direct (internal only) /api/v1/templates/stats: get: deprecated: true tags: - Templates summary: Get template usage statistics description: Retrieve usage statistics for templates in your tenant operationId: getTemplateStats parameters: - $ref: '#/components/parameters/TenantID' responses: '200': description: Template statistics content: application/json: schema: $ref: '#/components/schemas/TemplateStatsResponse' example: stats: - template_id: hipaa_phi_protection template_name: HIPAA PHI Protection usage_count: 15 last_used_at: '2025-01-15T14:30:00Z' - template_id: gdpr_data_protection template_name: GDPR Data Protection usage_count: 8 last_used_at: '2025-01-14T09:15:00Z' '401': $ref: '#/components/responses/Unauthorized' '500': $ref: '#/components/responses/InternalError' servers: - url: https://agent.getaxonflow.com description: Production (Agent single entry point, ADR-024) - url: http://localhost:8080 description: Local development (Agent single entry point) - url: http://localhost:8081 description: Orchestrator direct (internal only) components: schemas: PolicyResource: type: object properties: id: type: string description: Unique policy identifier example: pol_abc123def456 name: type: string description: Human-readable policy name minLength: 3 maxLength: 100 example: Block PII Access description: type: string description: Detailed policy description maxLength: 500 example: Prevent unauthorized access to personally identifiable information type: $ref: '#/components/schemas/PolicyType' category: type: string description: Policy category (dynamic-risk, dynamic-compliance, media-safety, etc.) example: dynamic-risk tier: type: string enum: - system - organization - tenant description: Policy tier in the hierarchy (system policies are immutable) conditions: type: array items: $ref: '#/components/schemas/PolicyCondition' minItems: 1 description: Conditions that must all match (AND logic) actions: type: array items: $ref: '#/components/schemas/PolicyAction' minItems: 1 description: Actions to execute when policy matches priority: type: integer minimum: 0 maximum: 1000 default: 0 description: Higher priority policies are evaluated first enabled: type: boolean default: true description: Whether the policy is active version: type: integer minimum: 1 description: Policy version number, incremented on each update tenant_id: type: string description: Owning tenant ID organization_id: type: string description: 'The organisation that owns this policy. Since #3490 the organisation is what SELECTS a policy row, at every tier -- this is not an organization-tier-only field, and the previous wording described the retired organization_id COLUMN rather than this resource field. ' tags: type: array items: type: string description: Tags for categorization created_at: type: string format: date-time description: Creation timestamp updated_at: type: string format: date-time description: Last update timestamp created_by: type: string description: User who created the policy updated_by: type: string description: User who last updated the policy deleted_at: type: string format: date-time description: Soft-delete timestamp (present only on deleted policies) ApplyTemplateResponse: type: object properties: success: type: boolean policy: $ref: '#/components/schemas/PolicyResource' usage_id: type: string description: Unique ID for this template usage (for analytics) message: type: string description: Success message TemplateStatsResponse: type: object properties: stats: type: array items: type: object properties: template_id: type: string template_name: type: string usage_count: type: integer last_used_at: type: string format: date-time PaginationMeta: type: object description: Pagination metadata properties: page: type: integer description: Current page number example: 1 page_size: type: integer description: Items per page example: 20 total_items: type: integer description: Total number of items example: 45 total_pages: type: integer description: Total number of pages example: 3 PolicyAction: type: object required: - type properties: type: $ref: '#/components/schemas/ActionType' config: type: object additionalProperties: true description: Action-specific configuration example: message: Request blocked by policy channel: security-alerts TemplateVariable: type: object required: - name - type properties: name: type: string description: Variable name used in template example: threshold type: type: string enum: - string - number - boolean - array description: Variable data type required: type: boolean default: false description: Whether this variable must be provided when applying the template default: description: Default value if not provided oneOf: - type: string - type: number - type: boolean - type: array items: type: string description: type: string description: Human-readable description example: Maximum requests allowed per window validation: type: string description: Regex pattern for validating the variable value TemplateResource: type: object properties: id: type: string description: Unique template identifier example: hipaa_phi_protection name: type: string description: Template name (machine-readable) example: hipaa_phi_protection display_name: type: string description: Human-readable display name example: HIPAA PHI Protection description: type: string description: Template description example: Protects PHI data in accordance with HIPAA requirements category: type: string description: Template category example: compliance subcategory: type: string description: Template subcategory example: healthcare template: type: object description: Policy template with variable placeholders properties: type: $ref: '#/components/schemas/PolicyType' conditions: type: array items: $ref: '#/components/schemas/PolicyCondition' actions: type: array items: $ref: '#/components/schemas/PolicyAction' variables: type: array items: $ref: '#/components/schemas/TemplateVariable' description: Variables that can be customized is_builtin: type: boolean description: Whether this is a built-in template is_active: type: boolean description: Whether this template is active version: type: string description: Template version example: '1.0' tags: type: array items: type: string description: Tags for categorization example: - hipaa - healthcare - phi created_at: type: string format: date-time updated_at: type: string format: date-time ApplyTemplateRequest: type: object required: - policy_name - variables properties: policy_name: type: string minLength: 3 maxLength: 100 description: Name for the new policy description: type: string maxLength: 500 description: Optional policy description variables: type: object additionalProperties: true description: Variable values for the template enabled: type: boolean default: false description: Whether to enable the policy immediately priority: type: integer minimum: 0 maximum: 1000 description: Policy priority (overrides template default) PolicyType: type: string enum: - content - user - risk - cost - context_aware - media - rate-limit - budget - time-access - role-access - mcp - connector description: 'Policy type determines evaluation context: - `content`: Evaluates request/response content - `user`: Evaluates user attributes - `risk`: Evaluates risk scores - `cost`: Evaluates cost estimates - `context_aware`: Context-aware controls (tenant isolation, debug restriction, sensitive-data control) - `media`: Media governance policies (multimodal image governance) - `rate-limit`, `budget`, `time-access`: MCP rate/budget controls - `role-access`, `mcp`, `connector`: MCP access controls ' PolicyCondition: type: object required: - field - operator - value properties: field: type: string description: 'Field to evaluate. `media.*` fields apply to media governance policies (multimodal image governance); `step.*` fields are retry-aware workflow step fields for WCP policies. ' enum: - query - response - user.email - user.role - user.department - user.tenant_id - risk_score - request_type - connector - cost_estimate - media.has_faces - media.face_count - media.has_biometric_data - media.nsfw_score - media.violence_score - media.content_safe - media.document_type - media.is_sensitive_document - media.has_pii - media.pii_types - media.has_extracted_text - media.extracted_text_length - step.gate_count - step.completion_count - step.prior_completion_status - step.prior_output_available - step.last_decision - step.first_attempt_age_seconds - step.idempotency_key operator: $ref: '#/components/schemas/ConditionOperator' value: oneOf: - type: string - type: number - type: boolean - type: array items: type: string description: Value to compare against TemplatesListResponse: type: object properties: templates: type: array items: $ref: '#/components/schemas/TemplateResource' pagination: $ref: '#/components/schemas/PaginationMeta' TemplateResponse: type: object properties: template: $ref: '#/components/schemas/TemplateResource' APIError: type: object properties: error: type: object properties: code: type: string description: Error code message: type: string description: Human-readable error message details: type: array items: type: object properties: field: type: string message: type: string description: Field-level validation errors ActionType: type: string enum: - block - require_approval - redact - warn - alert - log - route - modify_risk description: 'Action to take when policy matches: - `block`: Block the request with message - `require_approval`: Hold the request for human approval (HITL) - `redact`: Redact sensitive content from response - `warn`: Allow the request but attach a warning - `alert`: Send alert to configured channel - `log`: Log to audit trail - `route`: Route to specific provider - `modify_risk`: Adjust risk score ' ConditionOperator: type: string enum: - equals - not_equals - contains - not_contains - contains_any - regex - greater_than - less_than - in - not_in description: Comparison operator for conditions parameters: UserID: name: X-User-ID in: header required: false description: User identifier for audit logging schema: type: string example: user@company.com TenantID: name: X-Tenant-ID in: header required: true description: 'Tenant identifier for multi-tenancy isolation. When calling through the Agent (recommended), this header is stamped automatically from the authenticated client — you do not set it yourself. Required only on direct Orchestrator calls (internal deployments). ' schema: type: string example: tenant_abc123 TemplateID: name: id in: path required: true description: Template unique identifier schema: type: string example: hipaa_phi_protection responses: LegacyPolicyWriteFrozen: description: 'The legacy policy tables are read-only. `migrations/core/172` revoked INSERT, UPDATE, DELETE and TRUNCATE on `static_policies` and `dynamic_policies` from the application roles, and this endpoint writes them, so the write is refused permanently rather than transiently. It is not an entitlement fact: no licence, edition or upgrade changes it. Author policies through the typed authoring route (`/api/v1/typed-policies`, in `orchestrator-api.yaml`) instead. Reads on this endpoint are unaffected. A deployment whose connection may still write the tables (the database owner; a property of the connection, not of `AXONFLOW_DB_USE_APP_ROLE` alone) is not bound by the revoke and does not receive this response. Where the connection cannot write them, the create, update and bulk-import routes answer this before reading the request body, whatever it contains. ' content: application/json: schema: $ref: '#/components/schemas/APIError' example: error: code: LEGACY_POLICY_WRITE_FROZEN message: 'The legacy policy tables are read-only in v11: migrations/core/172 revoked write access from the application role, and this endpoint writes them. Author policies through the typed authoring route at /api/v1/typed-policies instead. Reads on this endpoint are unaffected.' ValidationError: description: Request validation failed content: application/json: schema: $ref: '#/components/schemas/APIError' example: error: code: VALIDATION_ERROR message: Request validation failed details: - field: name message: Name must be between 3 and 100 characters - field: conditions[0].operator message: 'Invalid operator: like. Must be one of: equals, contains, regex' InternalError: description: Internal server error content: application/json: schema: $ref: '#/components/schemas/APIError' example: error: code: INTERNAL_ERROR message: An unexpected error occurred Unauthorized: description: Missing or invalid tenant ID content: application/json: schema: $ref: '#/components/schemas/APIError' example: error: code: UNAUTHORIZED message: Missing tenant ID NotFound: description: Policy not found content: application/json: schema: $ref: '#/components/schemas/APIError' example: error: code: NOT_FOUND message: Policy not found x-refined-from: - axonflow-policy-api.yaml - axonflow-policy-openapi.yml