Developer Guide: Build, Price, and Bill with Paid

At‑a‑Glance

StepInterfaceWhat you’ll doOutcome
1: Sign upWeb AppGo to app.paid.ai, and register with your work e‑mail. During sign‑up you’ll set the organisation nameA dedicated, secure workspace for your company—isolated from other tenants and ready for configuration.
2: Create an API keyWeb AppGenerate and copy your secret token.Credentials to call the Paid.ai API.
3: Create an AgentWeb AppConfigure signals & pricing in Agents ▸ New Agent.An agent_id used in every request.
4: Integrate Accounts / Contacts/ OrdersAPIFor every new or updated record in your platform, immediately POST a JSON payload to:
/accountsfor companies or buying groups)
/contacts(for billing contact or other people working at the account)
/orders(for subscriptions)

This near‑real‑time push keeps Paid.ai perfectly mirrored—no batching or nightly jobs needed.
A continuously live, up‑to‑the‑second copy of your account, contact, and order data inside Paid.ai.
5: Stream agent signalsAPIFor every runtime event, send a signal payload to PaidPaid.ai ingests each signal in real time, applies your pricing and costing, and shows them against your customer and order.

Step 1: Sign up

Go to app.paid.ai, and register with your work e‑mail. During sign‑up you’ll set the organisation name and details

Step 2: Creating an API Key

API keys are your credentials to authenticate with the Paid.ai API.

  1. Sign in to your Paid.ai dashboard at app.paid.ai
  2. Navigate to your organization settings
  3. Go to the API Keys section
  4. Click “Create New API Key”
  5. Give your key a descriptive name
  6. Copy the generated secret key immediately - you won’t be able to see it again!

Security Best Practices

  • Never commit API keys to your repository
  • Store keys in environment variables or a secure secret manager
  • Rotate keys regularly
  • Use different keys for different environments (development, staging, production)

Step 3: Agent Creation

Create Your First Agent

For the purpose of this example, we are going to use AI SDR agent as a reference, and create data related to that.

  1. Go to ‘Agents’.
  2. Click ‘Add Agent’: Give your Agent a name that you’d recognize (e.g., “AI SDR Agent”). This name will appear on invoices.
  3. Describe the Agent’s Purpose: Provide a short description of what this Agent does (e.g., “Automates SDR activities”).
  4. Add your Agent Code: Use an agent code for reference. Eg. AG-001
  5. Click ‘Add Signals’

Tip: If you have multiple Agents (sales chatbot, service chatbot, etc.), create each one here so they can be tracked and billed separately.

Configure Signals

Signals represent the individual activities or events you want to track and monetize.

  1. Click ‘Add Signals’ and fill the details
    • Name: Name of your signal (e.g., Send an email or Book a Meeting ).
    • Value (optional): The approximate human-equivalent cost or effort (e.g., $150 to book a meeting).
    • Type: Choose ‘Activity’ or ‘Outcome’. For example, Send an email might be an Activity, while Book a Meeting is an Outcome.
  2. Click ‘Pricing’

Tip: Keep Signals granular enough to capture precise usage but not so granular that they become cumbersome to track.

Set Up Pricing Rules

After defining your Signals, you can configure various billing options in Paid. In the Pricing section, you’ll see multiple toggles to combine different fee structures:

  • Setup Fee (Fixed, One-Time)

    A one-time charge for onboarding or initial configuration.

  • Platform Fee (Fixed, Recurring)

    A recurring flat fee for ongoing platform access or maintenance.

  • Seat-Based (Variable, Recurring)

    A per-user or “seat” cost that recurs regularly (e.g., monthly).

  • Activity-Based (Usage, Variable, Recurring)

    A usage-based fee tied to activity Signals (e.g., each email sent, each message processed).

  • Outcome-Based (Usage, Variable, Recurring)

    A usage-based fee tied to outcome Signals (e.g., each booked meeting or qualified lead).

Enable the relevant toggles, configure the pricing when prompted, and click ‘Save’.

Copy the “agent-id” displayed on the browser when you view this agent. We would need this in the following steps

Step 4: Integrate Accounts / Contacts / Orders

Your platform already lets new customers sign up, choose a plan, and start using your agents. Paid needs to see the same objects—Accounts, Contacts, and Orders—so it can price usage, generate invoices, and collect payments.

This section walks through a complete, end‑to‑end example. Copy, paste, and adapt these calls to wire Paid into your onboarding flow in minutes.

Scenario

John Doe, VP of Sales at Acme Ltd, signs up for your AI SDR – Pro plan on 1 June 2025.

In your database you will create:

  1. AccountAcme Ltd
  2. ContactJohn Doe
  3. Order → their paid subscription to AI SDR Agent (Pro)

We will mirror those three objects inside Paid with the API.

Prerequisites

1pip install paid-python

1: Create the Account

1from paid import Paid, TaxExemptStatus, CreationSource, Address
2
3# Initialize the client
4client = Paid(token="<YOUR_API_KEY>")
5
6# Create the account
7customer = client.customers.create(
8 name="Acme Ltd",
9 phone="+1-555-0123",
10 employee_count=100,
11 annual_revenue=1000000,
12 tax_exempt_status="none",
13 creation_source="api",
14 website="https://acme.com",
15 external_id="acme_account_123", # this would normally be this account's ID in your DB
16 billing_address=Address(
17 line_1="123 Business Ave",
18 line_2="Suite 100",
19 city="San Francisco",
20 state="CA",
21 zip_code="94105",
22 country="USA"
23 )
24)

Returns

Returns the Account object upon successful creation. Save the returned id—we’ll need it in the next two calls.

1{
2 id: 'uuid',
3 organizationId: 'uuid',
4 name: 'Acme Ltd',
5 phone: '+1-555-0123',
6 website: 'https://acme.com',
7 employeeCount: 100,
8 annualRevenue: 1000000,
9 taxExemptStatus: 'none',
10 creationSource: 'api',
11 externalId: 'acme_123',
12 creationState: 'active',
13 billingAddress: {
14 city: 'San Francisco',
15 line1: '123 Business Ave',
16 line2: 'Suite 100',
17 state: 'CA',
18 country: 'USA',
19 zipCode: '94105'
20 }
21}

2: Create the Contact

1from paid import Paid, Salutation
2
3# Initialize the client
4client = Paid(token="<YOUR_API_KEY>")
5
6# Create the contact (using either an internal or an external account id)
7contact = client.contacts.create(
8 customer_external_id="acme_account_123", # use either customer_id or customer_external_id for contact creation
9 salutation="Mr.",
10 first_name="John",
11 last_name="Doe",
12 email="john.doe@acme.com",
13 phone="+1-555-0123",
14 billing_street="123 Main St",
15 billing_city="San Francisco",
16 billing_state_province="CA",
17 billing_country="USA",
18 billing_postal_code="94105",
19 external_id="acme_contact_123"
20)

Returns

Returns the Contact object upon successful creation. It’s recommended to store the returned contact ID in your own system for future reference and operations. The contact is now linked to the account inside Paid.

1{
2 id: 'uuid',
3 organizationId: 'uuid',
4 salutation: 'Mr.',
5 firstName: 'John',
6 lastName: 'Doe',
7 accountName: 'Acme Ltd',
8 email: 'john.doe@acme.com',
9 phone: '+1-555-0123',
10 billingStreet: '123 Main St',
11 billingCity: 'San Francisco',
12 billingStateProvince: 'CA',
13 billingCountry: 'USA',
14 billingZipPostalCode: '94105',
15 externalId: 'acme_contact_123',
16 accountId: 'uuid'
17}

3: Create an Order

1from paid import Paid
2
3# Initialize the client
4client = Paid(token="<YOUR_API_KEY>")
5
6# Create the order (using either an internal or an external customer id and billing contact id)
7order = client.orders.create(
8 customer_id=customer.id, # use either customer_id or customer_external_id for order creation
9 billing_contact_id=contact.id, # use the contact ID from the previous step
10 name="AI SDR – Pro plan",
11 description="Annual subscription for AI SDR – Pro plan",
12 start_date="2025-06-01",
13 end_date="2026-05-31",
14 currency="USD"
15)

Returns

Returns the Order object upon successful creation. It’s recommended to store the returned order ID in your own system for future reference and operations.

1{
2 "id": "uuid",
3 "organizationId": "uuid",
4 "name": "Annual subscription for AI SDR – Pro plan",
5 "startDate": "2024-01-01T00:00:00.000Z",
6 "endDate": "2024-12-31T00:00:00.000Z",
7 "orderAmount": 0,
8 "estimatedTax": 0,
9 "billedAmountNoTax": 0,
10 "billedTax": 0,
11 "pendingBillingAmount": 0,
12 "totalBilledAmount": 0,
13 "totalAmount": 0,
14 "creationState": "draft",
15 "usageSummary": [],
16 "account": {
17 "id": "uuid",
18 "organizationId": "uuid",
19 "name": "Acme Ltd",
20 "email": "contact@acme.com",
21 "phone": "",
22 "website": "https://acme.com",
23 "employeeCount": 100,
24 "annualRevenue": 1000000,
25 "taxExemptStatus": "exempt",
26 "creationSource": "api",
27 "externalId": "customer-123",
28 "creationState": "active",
29 "billingAddress": {
30 "city": "New York",
31 "line1": "123 Main St",
32 "line2": "Suite 100",
33 "state": "NY",
34 "country": "USA",
35 "zipCode": "10001"
36 }
37 },
38 "accountId": "uuid",
39 "orderLines": [...]
40}

Step 4: Stream Agent Signals (AI SDR Edition)

Paid measures how each AI SDR is used through signals—immutable events you emit in real time. Every signal links back to the Order you created (for example, Acme Ltd’s Annual subscription for AI SDR – Pro plan), so Paid can measure all your agent activities against it, and can also price the event and invoice it if you charge your customers on outcome.

We’ll switch to an AI SDR example and stream signals for common SDR activities: sending outbound emails, making calls, logging replies, and booking meetings.

When should I send a signal?

ActivitySend?Signal Name
AI SDR sends a prospecting emailemail_sent
Prospect replies (AI ingests reply)email_reply
AI SDR places an outbound callcall_completed
Call goes to voicemail (no conversation)
Meeting booked & pushed to CRMmeeting_booked
Internal nightly refresh job

Only instrument activities and outcomes that mean something to your customers.

1from paid import Paid, Signal
2
3# Initialize the client
4client = Paid(token="<YOUR_API_KEY>")
5
6agent_id = "agent_123"
7customer_id = "customer_123"
8signal_name = "signal_name"
9additional_data = {
10 "model": "gpt4",
11 "subjectLength": 56,
12 "bodyLength": 452
13}
14
15
16# Create signals for bulk usage recording
17signal = Signal(
18 event_name=signal_name,
19 agent_id=agent_id,
20 customer_id=customer_id,
21 data=additional_data
22)
23
24# Record bulk usage
25result = client.usage.record_bulk(signals=[signal])

Sending Signals Within Traces

A more reliable and streamlined way to send signals is from within traces. This automatically links the signal to the active trace, meaning you no longer need to specify customer_id and agent_id manually. It also benefits from OpenTelemetry for reliable delivery.

This should be used in combination with tracing funcitonality. Tracing should be initialized first. Then, the signal should be sent from within the callback provided to trace(). The example is below.

1from paid import Paid
2
3# Initialize the client
4client = Paid(token="<YOUR_API_KEY>")
5
6# Initialize tracing
7client.initialize_tracing()
8
9def send_email():
10 # Emit signal within a trace
11 client.signal(
12 event_name="email_sent",
13 data={ } # Optional data (ex. Manual Cost Tracking)
14 )
15 # Simulate the rest of your logic
16 print("Email sent!")
17
18# Wrap it in a trace
19_ = client.trace(
20 external_customer_id="customer_123",
21 external_agent_id="agent_123", # external_agent_id is generally optional but is required for sending signals.
22 fn=lambda: send_email()
23)

Error Handling

The API uses conventional HTTP response codes to indicate the success or failure of requests:

  • 2xx range indicates success
  • 4xx range indicates an error that failed given the information provided
  • 5xx range indicates an error with Paid’s servers

Error Response Format

1{
2 "error": {
3 "message": "Error message",
4 "code": "ERROR_CODE",
5 "details": "Additional error details"
6 }
7}

Need Help?

Additional Resources