Skip to navigation

Integrating Signals with Cost Tracking

Overview

This guide shows you how to integrate cost tracking with Signals in your AI product workflow. By linking these two together, you can:

  • Automatically attribute AI provider costs (OpenAI, Anthropic, etc.) to specific business events
  • Track the true cost of achieving business outcomes (e.g., booking a meeting, sending an email, processing an image or a document)
  • Generate accurate invoices that reflect both usage-based pricing and actual AI costs

Prerequisites

Before you begin, make sure you have:

  • Created an API key in the Paid dashboard
  • Installed the Paid SDK for your language
  • Configured at least one Product with Signals
  • Set up your customer and order records

Note: This feature is currently available in Python and Node.js SDKs.

How It Works

In a typical AI product workflow, your event processing logic might look like this:

1. Receive event (e.g., "prospect replied to email")
2. Process event → make AI calls to generate response
3. Send response
4. Send signal to Paid

To link AI costs with signals, you need to:

  1. Process your AI calls as usual with your AI provider
  2. Send signals to Paid using the Paid SDK

This allows Paid to track your business outcomes and attribute costs accordingly.

Automatic Cost Tracking

The Paid SDK can automatically instrument your AI provider calls so that costs are tracked without any manual bookkeeping. Call initialize_tracing and autoinstrument once at startup, then wrap your business logic in a trace. Supported providers include OpenAI, Anthropic, Gemini, Bedrock, LangChain, OpenAI Agents, and Instructor.

from paid.tracing import paid_autoinstrument, paid_tracing, initialize_tracing
from openai import OpenAI
initialize_tracing()
paid_autoinstrument(libraries=["openai"])
openai_client = OpenAI(api_key="<OPENAI_API_KEY>")
@paid_tracing("your_external_customer_id", external_product_id="your_external_product_id")
def chat_with_gpt():
response = openai_client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": "Hello!"}]
)
return response
chat_with_gpt()

Basic Integration Pattern

Here’s the recommended pattern for integrating cost tracking with signals using the SDK:

from paid import Paid
from openai import OpenAI
# Initialize clients
paid_client = Paid(token="YOUR_PAID_API_KEY")
openai_client = OpenAI(api_key="<OPENAI_API_KEY>")
def process_event(event, customer_id: str, product_id: str):
"""
Process an event and send signal via SDK
"""
# Step 1: Make AI calls
response = openai_client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": "You are an AI SDR assistant"},
{"role": "user", "content": event.content}
]
)
# Step 2: Your business logic
send_response(response.choices[0].message.content)
# Step 3: Send signal via SDK
paid_client.signals.create_signals(
signals=[{
"event_name": "email_sent",
"customer": {"external_customer_id": customer_id},
"attribution": {"external_product_id": product_id},
"data": {"response_length": len(response.choices[0].message.content)}
}]
)
# Call your event processor
process_event(incoming_event, "customer_123", "agent_123")

Real-World Example: AI SDR Product

Let’s walk through a complete example of an AI SDR product that processes email replies and sends signals via the SDK.

from paid import Paid
from openai import OpenAI
# Initialize clients
paid_client = Paid(token="YOUR_PAID_API_KEY")
openai_client = OpenAI(api_key="<OPENAI_API_KEY>")
def handle_email_reply(email, customer_id: str):
"""
Handle incoming email reply from prospect
"""
# AI call #1: Analyze sentiment
sentiment_response = openai_client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": "Analyze email sentiment"},
{"role": "user", "content": email.body}
]
)
sentiment = sentiment_response.choices[0].message.content
# AI call #2: Generate response
reply_response = openai_client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": f"Generate reply. Sentiment: {sentiment}"},
{"role": "user", "content": email.body}
]
)
reply_text = reply_response.choices[0].message.content
# Business logic: Send the email
send_email(
to=email.sender,
subject=f"Re: {email.subject}",
body=reply_text
)
# Send signal via SDK
paid_client.signals.create_signals(
signals=[{
"event_name": "email_reply_processed",
"customer": {"external_customer_id": customer_id},
"attribution": {"external_product_id": "ai_sdr_product"},
"data": {
"sentiment": sentiment,
"reply_length": len(reply_text)
},
"idempotency_key": f"email_reply_{email.id}"
}]
)
# Process incoming email
handle_email_reply(incoming_email, "acme_account_123")

Event Loop Integration

Most AI products run in an event loop, processing events continuously. Here’s how to integrate signal tracking in that pattern:

from paid import Paid
from openai import OpenAI
# Initialize clients once
paid_client = Paid(token="YOUR_PAID_API_KEY")
openai_client = OpenAI(api_key="<OPENAI_API_KEY>")
def send_signal(event_name: str, customer_id: str, product_id: str, data: dict = None):
"""Helper function to send signals"""
signal = {
"event_name": event_name,
"customer": {"external_customer_id": customer_id},
"attribution": {"external_product_id": product_id}
}
if data:
signal["data"] = data
paid_client.signals.create_signals(signals=[signal])
def process_event(event, customer_id: str, product_id: str):
"""Process a single agent event"""
# Make AI calls as needed
if event.type == "email_received":
response = openai_client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": event.content}]
)
handle_email_response(response)
# Send signal
send_signal("email_processed", customer_id, product_id)
elif event.type == "call_completed":
# Different AI calls for call processing
summary = openai_client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": f"Summarize: {event.transcript}"}]
)
send_signal("call_summarized", customer_id, product_id)
# Event loop
while True:
event = get_next_event() # Your event queue
if event:
process_event(event, "customer_123", "agent_123")

Best Practices

1. One Signal Per Business Outcome

Each business outcome should have one signal:

from paid import Paid
paid_client = Paid(token="YOUR_PAID_API_KEY")
def send_signal(event_name, customer_id, product_id, data=None):
signal = {
"event_name": event_name,
"customer": {"external_customer_id": customer_id},
"attribution": {"external_product_id": product_id},
"data": data or {}
}
paid_client.signals.create_signals(signals=[signal])
# ✅ Good: One signal per outcome
def book_meeting(prospect, customer_id):
# Multiple AI calls OK
analyze_calendar(prospect)
generate_invite(prospect)
send_confirmation(prospect)
# Single signal for the outcome
send_signal("meeting_booked", customer_id, "agent_123")
# ❌ Bad: Multiple signals for same workflow
def process_workflow(prospect, customer_id):
analyze_calendar(prospect)
send_signal("calendar_analyzed", customer_id, "agent_123") # Too granular
generate_invite(prospect)
send_signal("invite_generated", customer_id, "agent_123") # Too granular

2. Use Idempotency Keys

Always include idempotency keys to prevent duplicate signals:

from paid import Paid
paid_client = Paid(token="YOUR_PAID_API_KEY")
signal = {
"event_name": "email_sent",
"customer": {"external_customer_id": "customer_123"},
"attribution": {"external_product_id": "agent_123"},
"idempotency_key": f"email_{email_id}_{timestamp}" # Unique per event
}
paid_client.signals.create_signals(signals=[signal])

Troubleshooting

Signals Not Appearing in Dashboard

If signals aren’t showing up:

  1. Check API key: Verify your API key is valid and has the correct permissions
  2. Check customer exists: The customer ID must exist in your Paid organization
  3. Check product exists: If using attribution, the product must exist
  4. Check response: Verify the API response shows ingested: 1

Duplicate Signals

If you’re seeing duplicate signals:

  • Add idempotencyKey to your signals
  • Use a unique identifier for each business event (e.g., {event_type}_{entity_id}_{timestamp})

Next Steps

Need Help?

Additional Resources