Skip to Content
PlatformEndpointsMapping Examples

Mapping Examples

Practical examples showing how to configure request and response mappings for different API patterns. Each example includes the request body template, response mapping, and a description of how Rhesis translates between platform-managed variables and your API.

Simple Query-Response API

The most basic pattern: a single input field and a top-level output field.

API contract: Your API expects \{"prompt": "..."\} and returns \{"text": "..."\}.

Request body template:

simple-request.json
{
  "prompt": "{{ input }}"
}

Response mapping:

simple-response.json
{
  "output": "$.text"
}

Rhesis maps its input variable to your API’s prompt field, and extracts your API’s text field into the platform’s output variable.

OpenAI-Compatible API

For APIs that follow the OpenAI chat completions format.

Request body template:

openai-request.json
{
  "model": "gpt-4",
  "messages": [
    {
      "role": "user",
      "content": "{{ input }}"
    }
  ],
  "temperature": 0.7,
  "max_tokens": 1024
}

Response mapping:

openai-response.json
{
  "output": "$.choices[0].message.content",
  "metadata": "$.usage"
}

The response text is nested inside choices[0].message.content. The metadata field captures token usage statistics for reference.

Multi-turn conversations: This example sends a single user message. Since OpenAI-compatible APIs are stateless, you can use "messages": "{{ messages }}" instead to let Rhesis manage the full conversation history automatically. The response mapping stays the same. See the Stateless Endpoint example below or Multi-Turn Conversations for details.

Anthropic Claude API

For APIs following Anthropic’s message format.

Request body template:

anthropic-request.json
{
  "model": "claude-3-sonnet-20240229",
  "max_tokens": 1024,
  "system": "You are a helpful assistant.",
  "messages": [
    {
      "role": "user",
      "content": "{{ input }}"
    }
  ]
}

Response mapping:

anthropic-response.json
{
  "output": "$.content[0].text",
  "metadata": "$.usage"
}

Anthropic returns the response in content[0].text rather than choices[0].message.content.

Multi-turn conversations: Like OpenAI, the Anthropic API is stateless. Replace the hardcoded messages array with "messages": "{{ messages }}" to let Rhesis manage conversation history across multiple turns. See Multi-Turn Conversations for details.

Google Gemini API

For the Google Gemini (Vertex AI) chat format.

Request body template:

gemini-request.json
{
  "contents": [
    {
      "role": "user",
      "parts": [
        {
          "text": "{{ input }}"
        }
      ]
    }
  ],
  "generationConfig": {
    "temperature": 0.7,
    "maxOutputTokens": 1024
  }
}

Response mapping:

gemini-response.json
{
  "output": "$.candidates[0].content.parts[0].text",
  "metadata": "$.usageMetadata"
}

Gemini uses a deeply nested structure with candidates, content, and parts.

Multi-turn conversations: The Gemini API is also stateless. For multi-turn testing, replace the hardcoded contents array with "contents": "{{ messages }}" to let Rhesis manage the conversation history. See Multi-Turn Conversations for details.

RAG Endpoint with Context

For retrieval-augmented generation APIs that return source documents alongside the answer.

API contract: Your API expects a query and returns an answer with sources.

Request body template:

rag-request.json
{
  "query": "{{ input }}",
  "num_sources": 5,
  "include_metadata": true
}

Response mapping:

rag-response.json
{
  "output": "$.answer",
  "context": "$.sources",
  "metadata": "$.metadata"
}

The context variable captures the retrieved sources, which Rhesis can use for context-dependent metrics like faithfulness and relevance.

Fallback Response Paths

When your API might return the response in different locations depending on the request type, use Jinja2 templates with jsonpath() for fallback logic.

Response mapping:

fallback-response.json
{
  "output": "{{ jsonpath('$.result.text') or jsonpath('$.message') or jsonpath('$.output') }}",
  "metadata": "$.debug_info"
}

Rhesis tries each JSONPath expression in order and uses the first non-empty result. This is useful for APIs that have different response shapes for different endpoints or error conditions.

Stateful Conversation Endpoint

For APIs that manage their own session state and return a conversation identifier.

Request body template:

stateful-request.json
{
"message": "{{ input }}",
"conversation_id": {{ conversation_id | tojson }}
}

Response mapping:

stateful-response.json
{
  "output": "$.response",
  "conversation_id": "$.conversation_id",
  "context": "$.sources"
}

On the first turn, conversation_id renders as null. The API returns a new conversation ID, which Rhesis automatically includes in subsequent requests. See Multi-Turn Conversations for details.

Stateless Conversation Endpoint

For APIs that expect the full message history with every request (e.g., direct LLM provider APIs).

Request body template:

stateless-request.json
{
  "model": "gpt-4",
  "messages": "{{ messages }}",
  "temperature": 0.7,
  "system_prompt": "You are a knowledgeable insurance advisor."
}

Response mapping:

stateless-response.json
{
  "output": "$.choices[0].message.content"
}

Rhesis detects the messages variable and manages conversation history internally. The system_prompt is prepended to the messages array and removed from the request body before sending. See Multi-Turn Conversations for details.

Custom Business Fields

For APIs that require domain-specific fields beyond the standard platform variables. Custom fields are passed through from the test input.

Request body template:

custom-fields-request.json
{
  "question": "{{ input }}",
  "policy_number": "{{ policy_number }}",
  "customer_tier": "{{ tier | default('standard') }}",
  "language": "{{ language | default('en') }}"
}

Response mapping:

custom-fields-response.json
{
  "output": "$.answer",
  "context": "$.relevant_clauses",
  "metadata": "$.claim_info"
}

Custom fields like policy_number and tier must be included in the test input or API request body when invoking the endpoint. Use the default filter to provide fallback values for optional fields.

API with Authentication in the Body

Some APIs require authentication tokens or API keys in the request body rather than in headers.

Request body template:

auth-body-request.json
{
  "api_key": "{{ auth_token }}",
  "input": {
    "text": "{{ input }}",
    "options": {
      "temperature": 0.5,
      "format": "text"
    }
  }
}

Response mapping:

auth-body-response.json
{
  "output": "$.result.generated_text",
  "metadata": "$.result.statistics"
}

The auth_token variable is automatically populated from the authentication token configured in your endpoint settings. See Platform-Managed Variables for details.

Deeply Nested Response

For APIs with complex, deeply nested response structures.

Response mapping:

nested-response.json
{
  "output": "$.data.completion.choices[0].message.content",
  "context": "$.data.retrieval.documents[*].text",
  "metadata": "{{ {'model': jsonpath('$.data.model_info.name'), 'latency_ms': jsonpath('$.data.timing.total_ms')} }}"
}

The metadata field uses a Jinja2 template to construct a custom object from multiple response paths. This is useful when you want to aggregate data from different parts of the response.

WebSocket Endpoint

WebSocket endpoints use the same mapping syntax. The request template defines the message format sent over the WebSocket connection.

Request body template:

websocket-request.json
{
"type": "chat_message",
"payload": {
  "text": "{{ input }}",
  "session_id": {{ conversation_id | tojson }}
}
}

Response mapping:

websocket-response.json
{
  "output": "$.payload.response",
  "conversation_id": "$.payload.session_id",
  "metadata": "$.payload.metadata"
}

The mapping works the same regardless of transport protocol (REST or WebSocket).


Next Steps