Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.trymaven.com/llms.txt

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

Custom Voice Platform Integration

Add PCI-compliant voice payments to any voice agent platform — Outbox AI, Bland, or any custom Twilio-based system. This guide covers the universal integration pattern that works with any platform capable of HTTP tool calls and call transfers.

How It Works

1

Agent triggers payment collection

During a call, your voice agent calls the Maven API to create a payment session with the amount and caller’s phone number.
2

Maven returns a transfer number

Maven creates a session and returns a phone number (and SIP URI) to transfer the caller to.
3

Agent transfers the caller

Your agent transfers the live call to Maven’s secure payment line.
The transfer must preserve the original caller’s phone number. Maven matches sessions by caller ID. If your platform replaces the caller ID with its own trunk number during transfer, the session will silently fail to connect. See Caller ID Preservation below.
4

Payment collected

Maven collects the card details over voice, processes the payment, and sends a webhook with the result. The caller is optionally transferred back to your agent via the callback number.

Prerequisites

  1. A Maven account with an API key (mvn_test_ for test mode, mvn_live_ for production)
  2. An app with a payment gateway connected (Stripe, Authorize.net, Braintree, Shift4, or Fiserv)
  3. A voice agent platform that supports HTTP tool calls and call transfers

Step 1 — Create a Payment Session

When your agent decides to collect a payment, call the Maven API:
curl -X POST https://api.trymaven.com/v1/sessions \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "project": "your-app-slug",
    "caller": "+14155551234",
    "amount": 150.00,
    "gateway": "stripe",
    "mode": "charge",
    "description": "Invoice #1234",
    "callback": "+18005550000"
  }'
Response (HTTP 201):
{
  "session_id": "a1b2c3d4-...",
  "status": "created",
  "phone_number": "+18338..."  ,
  "sip_uri": "sip:a1b2c3d4@sip.trymaven.com",
  "created_at": "2026-04-26T12:00:00Z"
}
FieldDescription
projectYour app slug from the Maven Dashboard
callerThe customer’s phone number in E.164 format. Must match the caller ID on the transferred call.
amountPayment amount in dollars (e.g. 150.00)
gatewaystripe, authorizenet, braintree, shift4, or fiserv
modecharge (process immediately) or tokenize (save card only)
descriptionOptional — what the payment is for
callbackOptional — phone number or SIP URI to transfer the caller back to after payment

HTTP 201 Compatibility

Some platforms (e.g. Outbox AI) only accept HTTP 200 as a success response. If your platform wraps non-200 responses as errors, add ?response_status=200 to force a 200 response:
POST https://api.trymaven.com/v1/sessions?response_status=200
The response body is identical — only the status code changes.

Step 2 — Transfer the Call

After creating the session, transfer the caller to the phone_number (PSTN) or sip_uri (SIP) returned in the response. Use a cold transfer — Maven handles the entire payment conversation.

PSTN Transfer

Transfer to the phone_number field. This works on any platform that supports standard call transfers.

SIP Transfer

Transfer to the sip_uri field. SIP transfers are more reliable for caller ID preservation because you can pass identifying headers:
  • X-Session-Id — The session UUID (highest priority match, skips caller ID lookup entirely)
  • X-Caller — The original caller’s phone number (useful if the platform can’t preserve caller ID natively)
If your platform supports SIP headers, pass X-Session-Id on the transfer. This is the most reliable matching method — it doesn’t depend on caller ID at all.

Step 3 — Get the Result

Maven sends a webhook to your app’s webhook URL when the session completes. You can also poll the session status:
# By session ID
curl https://api.trymaven.com/v1/sessions/SESSION_ID \
  -H "Authorization: Bearer YOUR_API_KEY"

# By caller phone number (returns most recent session)
curl "https://api.trymaven.com/v1/sessions?caller=%2B14155551234" \
  -H "Authorization: Bearer YOUR_API_KEY"

Caller ID Preservation

This is the most common integration pitfall. Maven matches inbound calls to pending sessions by the caller’s phone number. If the caller ID doesn’t match, the session won’t connect.

How matching works

When Maven receives a transferred call, it checks these fields in priority order:
  1. X-Session-Id SIP header (direct UUID match — most reliable)
  2. X-Caller SIP header (phone number override)
  3. SIP To URI (if it contains the session ID or phone number)
  4. From field (the caller ID on the inbound leg)

Common pitfalls

Platform behaviorResultFix
Platform replaces caller ID with its own trunk numberSession doesn’t matchUse SIP transfer with X-Session-Id header
Platform uses agent’s number as caller IDSession doesn’t matchConfigure transfer to use customer’s number as displayed caller ID
Platform strips SIP headersFalls back to From field matchingEnsure PSTN caller ID is preserved

Diagnosing caller ID issues

If sessions are created but calls don’t connect, verify the session exists for the expected caller:
curl "https://api.trymaven.com/v1/sessions?caller=%2B14155551234" \
  -H "Authorization: Bearer YOUR_API_KEY"
If this returns the session, the issue is that the transferred call’s From doesn’t match +14155551234. Check your platform’s transfer settings.

Tool Configuration

Most voice agent platforms let you define HTTP tools. Here’s how to configure them:

collect_payment tool

SettingValue
MethodPOST
URLhttps://api.trymaven.com/v1/sessions?response_status=200
HeadersAuthorization: Bearer YOUR_API_KEY, Content-Type: application/json
Parameters:
{
  "type": "object",
  "properties": {
    "amount": {
      "type": "number",
      "description": "Payment amount in dollars (e.g. 150.00)"
    },
    "caller": {
      "type": "string",
      "description": "Customer phone number in E.164 format (e.g. +14155551234)"
    },
    "description": {
      "type": "string",
      "description": "What the payment is for"
    },
    "callback": {
      "type": "string",
      "description": "Phone number to transfer the caller back to after payment"
    }
  },
  "required": ["amount", "caller"]
}
The project, gateway, and mode fields should be hardcoded in the URL or request body rather than exposed to the LLM. Use the URL format:
POST https://api.trymaven.com/v1/sessions?response_status=200
with a fixed body that includes "project": "your-app-slug", "gateway": "stripe", "mode": "charge".

get_session tool

SettingValue
MethodGET
URLhttps://api.trymaven.com/v1/sessions?caller={phone_number}
HeadersAuthorization: Bearer YOUR_API_KEY
Use this after the caller returns from the payment line to check the result.

cancel_session tool

SettingValue
MethodPOST
URLhttps://api.trymaven.com/v1/sessions/{session_id}/cancel
HeadersAuthorization: Bearer YOUR_API_KEY

Example Agent Prompt

Add something like this to your voice agent’s system prompt:
When a caller needs to make a payment:

1. Confirm the amount with the caller
2. Call collect_payment with:
   - amount: the payment amount
   - caller: the customer's phone number
   - description: a short description of the payment
   - callback: your agent's phone number (so the caller returns after payment)
3. Tell the caller: "I'm transferring you to our secure payment line now."
4. IMMEDIATELY transfer the call to the phone_number returned by collect_payment.
   Do NOT wait for the caller to confirm — transfer right away.

After the caller returns from the payment line:
1. Call get_session with the caller's phone number
2. If status is "payment-success" — confirm the payment and thank them
3. If status is "payment-failed" or "expired" — let them know and offer to try again

Never ask for card details yourself — the secure payment line handles that.
If your agent has trouble chaining the create and transfer steps, add explicit instructions like “You MUST call transfer immediately after collect_payment succeeds — do not wait or ask for confirmation.”

Troubleshooting

ProblemCauseSolution
Tool call returns error with 201 in the messagePlatform doesn’t accept HTTP 201Add ?response_status=200 to the URL
Session created but call doesn’t connectCaller ID mismatchSee Caller ID Preservation
Agent creates session but doesn’t transferLLM not chaining tool callsAdd explicit transfer instructions to agent prompt
Transfer connects but “no session found”Session expired (5 min TTL)Create the session immediately before transferring, not at the start of the call

Next

Webhooks

Get notified when sessions complete.

API Reference

Explore the full API.

Voice Settings

Configure TTS voice and language.

Testing

Test payments with test cards.