Passing MetadataPer-Request Headers

Per-Request Headers

Override or add headers for specific API calls when you need request-specific context.

Basic Usage

JavaScript/TypeScript

import { Tokenlay } from 'tokenlay'
 
const tokenlay = new Tokenlay({
  apiKey: 'your-api-key',
  defaultHeaders: {
    'User-ID': 'user-123',
    'Organization': 'acme-corp'
  }
})
 
// Override headers for specific requests
const result = await tokenlay.process(data, {
  headers: {
    'User-ID': 'different-user-456',  // Override default
    'Request-ID': generateRequestId(), // Add new header
    'Priority': 'high'                 // Request-specific context
  }
})

Python

from tokenlay import Tokenlay
 
tokenlay = Tokenlay(
    api_key="your-api-key",
    default_headers={
        "User-ID": "user-123",
        "Organization": "acme-corp"
    }
)
 
# Add request-specific headers
result = await tokenlay.process(
    data, 
    headers={
        "User-ID": "different-user-456",
        "Request-ID": generate_request_id(),
        "Priority": "high"
    }
)

Go

package main
 
import (
    "github.com/tokenlay/go-sdk"
)
 
func processWithContext(client *tokenlay.Client, data interface{}, userID string) {
    result, err := client.Process(data, tokenlay.RequestOptions{
        Headers: map[string]string{
            "User-ID":    userID,
            "Request-ID": generateRequestID(),
            "Priority":   "high",
        },
    })
}

Common Use Cases

User Impersonation

// Admin acting on behalf of another user
const result = await tokenlay.process(data, {
  headers: {
    'User-ID': targetUserId,
    'Acting-User-ID': adminUserId,
    'Impersonation-Reason': 'customer-support'
  }
})

Request Prioritization

// High priority processing for premium users
const result = await tokenlay.process(data, {
  headers: {
    'Priority': 'high',
    'SLA-Tier': 'premium',
    'Max-Wait-Time': '5000'
  }
})

A/B Testing

// Include experiment context
const result = await tokenlay.process(data, {
  headers: {
    'Experiment-ID': 'new-algorithm-v2',
    'Experiment-Variant': 'treatment',
    'Experiment-Session': sessionId
  }
})

Batch Processing

// Process multiple items with different contexts
const results = await Promise.all(
  items.map(item => 
    tokenlay.process(item.data, {
      headers: {
        'Batch-ID': batchId,
        'Item-ID': item.id,
        'Item-Priority': item.priority,
        'Processing-Mode': 'batch'
      }
    })
  )
)

Advanced Patterns

Conditional Headers

function processWithDynamicHeaders(data, options = {}) {
  const headers = {
    'Request-ID': generateRequestId(),
    'Timestamp': new Date().toISOString()
  }
  
  // Add optional headers based on conditions
  if (options.userId) {
    headers['User-ID'] = options.userId
  }
  
  if (options.priority) {
    headers['Priority'] = options.priority
  }
  
  if (options.trace) {
    headers['Trace-ID'] = options.traceId
    headers['Span-ID'] = options.spanId
  }
  
  return tokenlay.process(data, { headers })
}

Request Context Builder

class RequestContextBuilder {
  constructor() {
    this.headers = {}
  }
  
  withUser(userId, role = null) {
    this.headers['User-ID'] = userId
    if (role) this.headers['User-Role'] = role
    return this
  }
  
  withOrganization(orgId) {
    this.headers['Organization-ID'] = orgId
    return this
  }
  
  withTracing(traceId, spanId) {
    this.headers['Trace-ID'] = traceId
    this.headers['Span-ID'] = spanId
    return this
  }
  
  withPriority(level) {
    this.headers['Priority'] = level
    return this
  }
  
  build() {
    return { headers: { ...this.headers } }
  }
}
 
// Usage
const context = new RequestContextBuilder()
  .withUser('user-123', 'admin')
  .withOrganization('org-456')
  .withPriority('high')
  .build()
 
const result = await tokenlay.process(data, context)

Header Merging Strategies

// Merge with default headers (default behavior)
const result1 = await tokenlay.process(data, {
  headers: {
    'Custom-Header': 'value'
    // Default headers are automatically included
  }
})
 
// Replace all headers (override defaults)
const result2 = await tokenlay.process(data, {
  headers: {
    'User-ID': 'user-456',
    'Custom-Header': 'value'
  },
  replaceHeaders: true  // Only these headers will be sent
})
 
// Explicitly remove certain default headers
const result3 = await tokenlay.process(data, {
  headers: {
    'Custom-Header': 'value'
  },
  excludeHeaders: ['Organization', 'Environment']
})

Error Handling

async function processWithErrorHandling(data, customHeaders = {}) {
  try {
    const result = await tokenlay.process(data, {
      headers: {
        'Request-ID': generateRequestId(),
        'Retry-Count': '0',
        ...customHeaders
      }
    })
    
    return result
  } catch (error) {
    if (error.code === 'RATE_LIMIT') {
      // Retry with lower priority
      return tokenlay.process(data, {
        headers: {
          ...customHeaders,
          'Priority': 'low',
          'Retry-Count': '1'
        }
      })
    }
    
    throw error
  }
}

Testing Patterns

Mock Headers for Testing

// Test with specific user context
describe('User processing', () => {
  it('should process data for premium user', async () => {
    const result = await tokenlay.process(testData, {
      headers: {
        'User-ID': 'test-user-premium',
        'User-Tier': 'premium',
        'Test-Mode': 'true'
      }
    })
    
    expect(result.priority).toBe('high')
  })
})

Header Validation

function validateHeaders(headers) {
  const required = ['User-ID', 'Request-ID']
  const missing = required.filter(header => !headers[header])
  
  if (missing.length > 0) {
    throw new Error(`Missing required headers: ${missing.join(', ')}`)
  }
  
  // Validate header formats
  if (headers['User-ID'] && !headers['User-ID'].startsWith('user-')) {
    throw new Error('Invalid User-ID format')
  }
  
  return true
}
 
// Usage
const headers = {
  'User-ID': 'user-123',
  'Request-ID': generateRequestId()
}
 
validateHeaders(headers)
const result = await tokenlay.process(data, { headers })

Best Practices

Performance

  • Reuse header objects when possible to reduce object creation
  • Cache computed header values for frequently used contexts
  • Avoid excessive header overhead for high-frequency requests

Security

  • Validate all header values before sending
  • Use secure token formats for sensitive headers
  • Log header usage for security auditing

Debugging

  • Include request IDs for tracing individual requests
  • Add timestamps for request timing analysis
  • Use consistent header naming conventions