# Asenion Custom Provider API — Standard contract for systems under test # Clients implementing this API can be tested by runtest without custom adapter code. # Design: docs/CUSTOM_PROVIDER_API_SPEC.md openapi: 3.0.3 info: title: Asenion Custom Provider API version: 1.0.0 description: | Standard HTTP API for AI systems under test. Implement this contract so Asenion runtest can send prompts and evaluate responses (compliance, red-team, security) without a custom adapter. contact: name: Asenion servers: - url: https://api.example.com description: Your API base URL (replace with actual base URL) paths: /chat: post: summary: Send a prompt and get the assistant reply (single-turn or multi-turn) operationId: chat description: | Primary endpoint. Send a user message (and optional system prompt or full conversation). Returns the assistant's reply. Required for runtest; supports optional multi-turn and session_id. requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ChatRequest' responses: '200': description: Assistant reply content: application/json: schema: $ref: '#/components/schemas/ChatResponse' '400': description: Bad request (e.g. missing message) content: application/json: schema: $ref: '#/components/schemas/Error' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error' '500': description: Server error content: application/json: schema: $ref: '#/components/schemas/Error' security: - BearerAuth: [] - ApiKeyAuth: [] # Optional: session lifecycle — new, restart, end. /sessions: post: summary: Create a new session (optional) operationId: createSession description: | Create a new session. Return session_id for use in /chat and in restart/end. Runtest sends this id as session_id in subsequent /chat requests. requestBody: required: false content: application/json: schema: type: object properties: system: type: string description: Optional system prompt for the session responses: '200': description: Session created content: application/json: schema: type: object required: - session_id properties: session_id: type: string description: Session or thread identifier for use in /chat, restart, end '401': description: Unauthorized '500': description: Server error security: - BearerAuth: [] - ApiKeyAuth: [] /sessions/{session_id}/restart: post: summary: Restart a session (optional) operationId: restartSession description: | Clear conversation state for this session and start fresh. Same session_id remains valid. Optional: return a new session_id if your implementation issues a new id on restart. parameters: - name: session_id in: path required: true schema: type: string description: Session/thread id from create or chat response requestBody: required: false content: application/json: schema: type: object properties: system: type: string description: Optional system prompt for the restarted session responses: '200': description: Session restarted content: application/json: schema: type: object properties: session_id: type: string description: Same as request, or new id if implementation issues a new one '404': description: Session not found or already ended content: application/json: schema: $ref: '#/components/schemas/Error' '401': description: Unauthorized '500': description: Server error security: - BearerAuth: [] - ApiKeyAuth: [] /sessions/{session_id}: delete: summary: End a session (optional) operationId: endSession description: | Invalidate the session. After this, the session_id must not be used for /chat or /restart. Runtest may call this when a test run or conversation is finished. parameters: - name: session_id in: path required: true schema: type: string description: Session/thread id to end responses: '200': description: Session ended content: application/json: schema: type: object properties: ok: type: boolean description: True if the session was ended '204': description: Session ended (no body) '404': description: Session not found or already ended content: application/json: schema: $ref: '#/components/schemas/Error' '401': description: Unauthorized '500': description: Server error security: - BearerAuth: [] - ApiKeyAuth: [] components: securitySchemes: BearerAuth: type: http scheme: bearer bearerFormat: JWT description: Optional. Bearer token in Authorization header. ApiKeyAuth: type: apiKey in: header name: X-API-Key description: Optional. API key in X-API-Key header. schemas: ChatRequest: type: object required: - message properties: message: type: string description: The user prompt to send (required for single-turn). system: type: string description: Optional system prompt or context for the model. messages: type: array description: Optional. Full conversation for multi-turn; client returns next assistant reply. items: $ref: '#/components/schemas/Message' session_id: type: string description: Optional. Session/thread id from previous response for stateful conversations. # Allow either message (single) or messages (multi-turn); message is required if messages omitted example: message: "What is the capital of France?" system: "You are a helpful assistant." Message: type: object required: - role - content properties: role: type: string enum: [system, user, assistant] content: type: string ChatResponse: type: object required: - content properties: content: type: string description: The assistant's reply (required). session_id: type: string description: Optional. Session/thread id for subsequent requests in the same conversation. usage: type: object description: Optional. Token or cost metadata. properties: prompt_tokens: type: integer completion_tokens: type: integer total_tokens: type: integer example: content: "The capital of France is Paris." Error: type: object properties: error: type: string description: Short error code or type message: type: string description: Human-readable error message