Report Usage Ticks

Report usage ticks periodically to track consumption. Each tick records the duration since the last tick and automatically deducts the cost from the customer's balance.


Endpoint

POST
/v1/metered-billing/sessions/{session_id}/tick

Authorization: Bearer <ORVION_API_KEY> or X-API-Key: <ORVION_API_KEY>

Content-Type: application/json


Request Body

FieldTypeRequiredDescriptionExample
secondsnumber
Required
Number of seconds consumed since last tick10
tick_idstring | null
Optional
Unique identifier for this tick (for idempotency). If not provided, one will be generatedtick_20250115_100000

Response

FieldTypeRequiredDescriptionExample
recordedboolean
Optional
Whether the tick was successfully recordedtrue
already_recordedboolean
Optional
Whether this tick was already recorded (idempotency check)false
cap_reachedboolean
Optional
Whether the usage cap was reachedfalse
insufficient_balanceboolean
Optional
Whether the customer has insufficient balancefalse
session_statusstring
Optional
Current session status after the tickactive

Example: cURL

cURL
curl -X POST "https://api.orvion.sh/v1/metered-billing/sessions/sess_abc123/tick" \
-H "Authorization: Bearer $ORVION_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"seconds": 10,
"tick_id": "tick_20250115_100000"
}'

Example: Python SDK

Python
from orvion import OrvionClient
# Initialize client
orvion = OrvionClient(api_key="your_api_key")
# Get existing session
session = await orvion.usage.get_session("sess_abc123")
# Report usage tick (10 seconds)
result = await session.tick(seconds=10, tick_id="tick_20250115_100000")
if result.recorded:
print(f"Tick recorded: {result.session_status}")
print(f"Cap reached: {result.cap_reached}")
print(f"Insufficient balance: {result.insufficient_balance}")
else:
print(f"Tick already recorded: {result.already_recorded}")
# Or use automatic ticker for periodic reporting
from orvion.usage import Ticker
ticker = Ticker(session, interval_seconds=10)
await ticker.start()
# Ticker automatically reports every 10 seconds
# Stop when done
await ticker.stop()

Example: Node.js SDK

JavaScript
import { OrvionClient } from '@orvion/sdk';
// Initialize client
const orvion = new OrvionClient({ apiKey: 'your_api_key' });
// Get existing session
const session = await orvion.usage.getSession('sess_abc123');
// Report usage tick (10 seconds)
const result = await session.tick({
seconds: 10,
tickId: 'tick_20250115_100000'
});
if (result.recorded) {
console.log(`Tick recorded: ${result.sessionStatus}`);
console.log(`Cap reached: ${result.capReached}`);
console.log(`Insufficient balance: ${result.insufficientBalance}`);
} else {
console.log(`Tick already recorded: ${result.alreadyRecorded}`);
}
// Or use automatic ticker for periodic reporting
import { Ticker } from '@orvion/sdk/usage';
const ticker = new Ticker(session, { intervalSeconds: 10 });
await ticker.start();
// Ticker automatically reports every 10 seconds
// Stop when done
await ticker.stop();

Response Example

{
  "recorded": true,
  "already_recorded": false,
  "cap_reached": false,
  "insufficient_balance": false,
  "session_status": "active"
}

Periodic Reporting Pattern

For continuous usage tracking, report ticks periodically:

Python Example

import asyncio
from orvion import OrvionClient

async def track_usage(session_id: str):
    orvion = OrvionClient(api_key="your_api_key")
    session = await orvion.usage.get_session(session_id)
    
    tick_interval = 10  # Report every 10 seconds
    last_tick_time = asyncio.get_event_loop().time()
    
    while True:
        await asyncio.sleep(tick_interval)
        
        current_time = asyncio.get_event_loop().time()
        elapsed_seconds = int(current_time - last_tick_time)
        
        result = await session.tick(
            seconds=elapsed_seconds,
            tick_id=f"tick_{int(current_time)}"
        )
        
        if result.insufficient_balance:
            print("Insufficient balance! Stopping tracking.")
            break
        
        if result.cap_reached:
            print("Usage cap reached! Stopping tracking.")
            break
        
        last_tick_time = current_time

Node.js Example

import { OrvionClient } from '@orvion/sdk';

async function trackUsage(sessionId) {
  const orvion = new OrvionClient({ apiKey: 'your_api_key' });
  const session = await orvion.usage.getSession(sessionId);
  
  const tickInterval = 10; // Report every 10 seconds
  let lastTickTime = Date.now() / 1000;
  
  const interval = setInterval(async () => {
    const currentTime = Date.now() / 1000;
    const elapsedSeconds = Math.floor(currentTime - lastTickTime);
    
    const result = await session.tick({
      seconds: elapsedSeconds,
      tickId: `tick_${Date.now()}`
    });
    
    if (result.insufficientBalance) {
      console.log('Insufficient balance! Stopping tracking.');
      clearInterval(interval);
      return;
    }
    
    if (result.capReached) {
      console.log('Usage cap reached! Stopping tracking.');
      clearInterval(interval);
      return;
    }
    
    lastTickTime = currentTime;
  }, tickInterval * 1000);
}

Important Notes

Idempotency

Use tick_id to ensure ticks are not double-counted. If you retry a request with the same tick_id, the response will have already_recorded: true and the tick won't be charged again.

Insufficient Balance

If insufficient_balance is true:

  • The tick is not recorded
  • The session remains active but no further ticks will be accepted
  • Top up the balance and retry, or stop the session

Usage Cap

If cap_reached is true:

  • The tick is not recorded
  • The session status changes to stopped
  • No further ticks will be accepted
  • You can still settle the session

Session Status

After a tick, session_status can be:

  • active - Session is running normally
  • stopped - Cap reached or manually stopped
  • settled - Session has been settled

Error Responses

400 Bad Request

{
  "detail": "Invalid seconds value"
}

404 Not Found

{
  "detail": "Session not found"
}

409 Conflict

{
  "detail": "Session is not active"
}

Next Steps