Skip to main content
PUT
/
v1
/
request
/
{requestId}
/
property
Add Properties to Request
curl --request PUT \
  --url https://api.helicone.ai/v1/request/{requestId}/property \
  --header 'Content-Type: application/json' \
  --data '
{
  "key": "<string>",
  "value": "<string>"
}
'
{
  "data": null,
  "error": {}
}

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/helicone/helicone/llms.txt

Use this file to discover all available pages before exploring further.

Add custom properties to a request after it has been logged. This is useful when you need to enrich request metadata based on business logic, user actions, or post-processing results that aren’t available at the time of the original request.
Properties added via this endpoint are merged with existing properties. To add properties at request time, use the Helicone-Property-* headers. See Custom Properties for more details.

Path Parameters

requestId
string
required
The unique identifier of the request to add properties to. This can be found in the Helicone-Id response header when making requests through Helicone.Example: req_abc123def456

Request Body

key
string
required
The property key/name. Should be descriptive of the metadata being stored.Examples: "ConversationOutcome", "UserSatisfaction", "ProcessingStatus"
value
string
required
The property value. Must be a string.Examples: "resolved", "high", "completed"

Response

data
null
Returns null on success.
error
string | null
Error message if the request failed.

Examples

Add Single Property

Add a property to mark conversation outcome:
cURL
curl --request PUT \
  --url https://api.helicone.ai/v1/request/req_abc123def456/property \
  --header 'Authorization: Bearer <HELICONE_API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '{
  "key": "ConversationOutcome",
  "value": "resolved"
}'
TypeScript
const requestId = 'req_abc123def456';

const response = await fetch(
  `https://api.helicone.ai/v1/request/${requestId}/property`,
  {
    method: 'PUT',
    headers: {
      'Authorization': `Bearer ${process.env.HELICONE_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      key: 'ConversationOutcome',
      value: 'resolved'
    })
  }
);

const result = await response.json();
console.log('Property added successfully');
Python
import os
import requests

request_id = "req_abc123def456"

response = requests.put(
    f"https://api.helicone.ai/v1/request/{request_id}/property",
    headers={
        "Authorization": f"Bearer {os.environ['HELICONE_API_KEY']}",
        "Content-Type": "application/json"
    },
    json={
        "key": "ConversationOutcome",
        "value": "resolved"
    }
)

result = response.json()
print("Property added successfully")

Add Multiple Properties

Add multiple properties to a request (requires multiple API calls):
TypeScript
const addMultipleProperties = async (
  requestId: string,
  properties: Record<string, string>
) => {
  const promises = Object.entries(properties).map(([key, value]) =>
    fetch(
      `https://api.helicone.ai/v1/request/${requestId}/property`,
      {
        method: 'PUT',
        headers: {
          'Authorization': `Bearer ${process.env.HELICONE_API_KEY}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({ key, value })
      }
    )
  );
  
  await Promise.all(promises);
  console.log('All properties added successfully');
};

// Usage
await addMultipleProperties('req_abc123def456', {
  'ConversationOutcome': 'resolved',
  'ResolutionTime': '5m',
  'CustomerSatisfaction': 'high',
  'AgentId': 'agent_789'
});
Python
import os
import requests
from concurrent.futures import ThreadPoolExecutor

def add_property(request_id: str, key: str, value: str):
    response = requests.put(
        f"https://api.helicone.ai/v1/request/{request_id}/property",
        headers={
            "Authorization": f"Bearer {os.environ['HELICONE_API_KEY']}",
            "Content-Type": "application/json"
        },
        json={"key": key, "value": value}
    )
    return response.json()

def add_multiple_properties(request_id: str, properties: dict):
    with ThreadPoolExecutor(max_workers=5) as executor:
        futures = [
            executor.submit(add_property, request_id, key, value)
            for key, value in properties.items()
        ]
        results = [future.result() for future in futures]
    print("All properties added successfully")
    return results

# Usage
add_multiple_properties("req_abc123def456", {
    "ConversationOutcome": "resolved",
    "ResolutionTime": "5m",
    "CustomerSatisfaction": "high",
    "AgentId": "agent_789"
})

Use Cases

Post-Processing Enrichment

Add properties after processing the LLM response:
import OpenAI from 'openai';

const client = new OpenAI({
  baseURL: 'https://gateway.helicone.ai/v1',
  defaultHeaders: {
    'Helicone-Auth': `Bearer ${process.env.HELICONE_API_KEY}`
  }
});

// Make the request
const { data, response } = await client.chat.completions
  .create({
    model: 'gpt-4',
    messages: [{ role: 'user', content: 'Explain quantum computing' }]
  })
  .withResponse();

const requestId = response.headers.get('helicone-id');
const responseText = data.choices[0].message.content;

// Analyze the response and add properties
const wordCount = responseText.split(' ').length;
const hasCodeExample = responseText.includes('```');
const sentiment = analyzesentiment(responseText); // Your sentiment analysis

// Add enrichment properties
await Promise.all([
  fetch(`https://api.helicone.ai/v1/request/${requestId}/property`, {
    method: 'PUT',
    headers: {
      'Authorization': `Bearer ${process.env.HELICONE_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ key: 'WordCount', value: wordCount.toString() })
  }),
  fetch(`https://api.helicone.ai/v1/request/${requestId}/property`, {
    method: 'PUT',
    headers: {
      'Authorization': `Bearer ${process.env.HELICONE_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ key: 'HasCodeExample', value: hasCodeExample.toString() })
  }),
  fetch(`https://api.helicone.ai/v1/request/${requestId}/property`, {
    method: 'PUT',
    headers: {
      'Authorization': `Bearer ${process.env.HELICONE_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ key: 'Sentiment', value: sentiment })
  })
]);

Workflow Status Tracking

Track multi-step workflow progress:
const processWorkflow = async (userQuery: string) => {
  // Step 1: Initial LLM call
  const { data: step1Data, response: step1Response } = await client.chat.completions
    .create({
      model: 'gpt-4',
      messages: [{ role: 'user', content: userQuery }]
    })
    .withResponse();
  
  const requestId = step1Response.headers.get('helicone-id');
  
  // Mark as processing
  await fetch(`https://api.helicone.ai/v1/request/${requestId}/property`, {
    method: 'PUT',
    headers: {
      'Authorization': `Bearer ${process.env.HELICONE_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ key: 'WorkflowStatus', value: 'processing' })
  });
  
  // Step 2: Additional processing
  const processingResult = await processData(step1Data);
  
  // Update status
  await fetch(`https://api.helicone.ai/v1/request/${requestId}/property`, {
    method: 'PUT',
    headers: {
      'Authorization': `Bearer ${process.env.HELICONE_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ key: 'WorkflowStatus', value: 'completed' })
  });
  
  // Add final outcome
  await fetch(`https://api.helicone.ai/v1/request/${requestId}/property`, {
    method: 'PUT',
    headers: {
      'Authorization': `Bearer ${process.env.HELICONE_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ key: 'FinalOutcome', value: processingResult.status })
  });
};

Customer Support Tagging

Tag support conversations with resolution details:
const handleSupportConversation = async (ticketId: string, userMessage: string) => {
  // Make request with initial properties
  const { data, response } = await client.chat.completions
    .create(
      {
        model: 'gpt-4',
        messages: [
          { role: 'system', content: 'You are a helpful support agent.' },
          { role: 'user', content: userMessage }
        ]
      },
      {
        headers: {
          'Helicone-Property-TicketId': ticketId,
          'Helicone-Property-Channel': 'chat'
        }
      }
    )
    .withResponse();
  
  const requestId = response.headers.get('helicone-id');
  
  // User interaction happens...
  // Later, after ticket is resolved:
  
  await Promise.all([
    fetch(`https://api.helicone.ai/v1/request/${requestId}/property`, {
      method: 'PUT',
      headers: {
        'Authorization': `Bearer ${process.env.HELICONE_API_KEY}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ key: 'TicketStatus', value: 'resolved' })
    }),
    fetch(`https://api.helicone.ai/v1/request/${requestId}/property`, {
      method: 'PUT',
      headers: {
        'Authorization': `Bearer ${process.env.HELICONE_API_KEY}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ key: 'ResolutionTime', value: '15m' })
    }),
    fetch(`https://api.helicone.ai/v1/request/${requestId}/property`, {
      method: 'PUT',
      headers: {
        'Authorization': `Bearer ${process.env.HELICONE_API_KEY}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ key: 'RequiredEscalation', value: 'false' })
    })
  ]);
};

A/B Test Results

Add experiment results after evaluation:
const runExperiment = async (variant: 'A' | 'B') => {
  const { data, response } = await client.chat.completions
    .create(
      {
        model: 'gpt-4',
        messages: [{ role: 'user', content: 'Explain climate change' }]
      },
      {
        headers: {
          'Helicone-Property-Variant': variant,
          'Helicone-Property-Experiment': 'prompt-test-1'
        }
      }
    )
    .withResponse();
  
  const requestId = response.headers.get('helicone-id');
  const responseText = data.choices[0].message.content;
  
  // Evaluate response quality
  const qualityScore = await evaluateQuality(responseText);
  const userEngagement = await trackUserEngagement(responseText);
  
  // Add evaluation results as properties
  await Promise.all([
    fetch(`https://api.helicone.ai/v1/request/${requestId}/property`, {
      method: 'PUT',
      headers: {
        'Authorization': `Bearer ${process.env.HELICONE_API_KEY}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ key: 'QualityScore', value: qualityScore.toString() })
    }),
    fetch(`https://api.helicone.ai/v1/request/${requestId}/property`, {
      method: 'PUT',
      headers: {
        'Authorization': `Bearer ${process.env.HELICONE_API_KEY}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ key: 'UserEngagement', value: userEngagement })
    }),
    fetch(`https://api.helicone.ai/v1/request/${requestId}/property`, {
      method: 'PUT',
      headers: {
        'Authorization': `Bearer ${process.env.HELICONE_API_KEY}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ key: 'EvaluationComplete', value: 'true' })
    })
  ]);
};

Querying by Properties

Once properties are added, you can query requests by those properties:
// Query all resolved support tickets
const response = await fetch(
  'https://api.helicone.ai/v1/request/query',
  {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.HELICONE_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      filter: {
        request_response_rmt: {
          properties: {
            'TicketStatus': {
              equals: 'resolved'
            }
          }
        }
      },
      limit: 100
    })
  }
);

Best Practices

  • Consistent Naming: Use consistent property key names across your application for easier filtering and analysis
  • String Values: All property values must be strings. Convert numbers and booleans to strings when needed
  • Meaningful Keys: Use descriptive property keys that clearly indicate the metadata being stored
  • Combine with Headers: Use Helicone-Property-* headers for properties known at request time, and this API for post-request enrichment
  • Batch Operations: When adding multiple properties, use Promise.all() to make parallel requests for better performance

Get Request by ID

Retrieve request with all properties

Query Requests

Query requests filtered by properties

Add Feedback

Add user feedback to requests

Add Scores

Add evaluation scores to requests

See Also