Twilio Integration Guide
This guide covers how to integrate Shuttle payments into your Twilio workflows using the <Pay> verb, handle responses, and leverage advanced features through our API.
Using the <Pay> Verb
<Pay> VerbThe Twilio <Pay> verb enables DTMF payment collection during phone calls. Here's how to implement it with Shuttle.
Required Parameters
| Field | Description |
|---|---|
paymentConnector | (required) The unique name of your Twilio Pay Connector |
action | (required) URL for next TwiML instructions after payment |
chargeAmount | (required for payments) Amount to charge (decimal format) |
Optional Parameters
| Field | Description | Default |
|---|---|---|
statusCallback | URL for progress updates | - |
currency | ISO currency code (lowercase) | usd |
paymentMethod | Payment type | credit-card |
postalCode | AVS postal code collection | true (US/CA only) |
description | Payment description | - |
Shuttle-Specific Parameters
Pass these as <Parameter> elements within the <Pay> verb:
| Parameter | Description |
|---|---|
action | AUTH for pre-authorization, PAYMENT to capture funds |
save_card | Tokenize card during payment |
alt_key | Your payment reference ID |
account_crm_key | Customer identifier |
account_first_name | Customer first name |
account_last_name | Customer last name |
account_email | Customer email |
account_phone | Customer phone |
payment_method_code | Unique payment method ID |
scheduled_date | Schedule payment for later (YYYY-MM-DDTHH:MI:SS) |
frequency | MONTHLY, FORTNIGHTLY, or WEEKLY for recurring |
occurrences | Number of recurring payments |
start_date | First installment date |
metadata_{key} | Custom metadata fields |
Implementation Examples
Card Tokenization
To save a card for future use without charging:
<Pay
paymentConnector="shuttle-pay-connector"
action="https://yourapp.com/next_step">
</Pay>Standard Card Payment
<Pay
paymentConnector="shuttle-pay-connector"
action="https://yourapp.com/next_step"
chargeAmount="29.99"
currency="usd"
postalCode="false">
<Parameter name="save_card" value="true"/>
<Parameter name="alt_key" value="INV-12345"/>
<Prompt for="payment-processing">
<Say>Please wait while we process your payment</Say>
</Prompt>
</Pay>Pre-Authorization
For auth-only transactions (capture later):
<Pay
paymentConnector="shuttle-pay-connector"
action="https://yourapp.com/next_step"
chargeAmount="99.99">
<Parameter name="action" value="AUTH"/>
</Pay>ACH Payment
<Pay
paymentConnector="shuttle-pay-connector"
action="https://yourapp.com/next_step"
chargeAmount="49.99"
paymentMethod="ach-debit"
bankAccountType="consumer-checking">
<Parameter name="AVSName" value="John Smith"/>
<Prompt for="payment-processing">
<Say>Processing your bank transfer</Say>
</Prompt>
</Pay>Recurring Payment
<Pay
paymentConnector="shuttle-pay-connector"
action="https://yourapp.com/next_step"
chargeAmount="19.99">
<Parameter name="frequency" value="MONTHLY"/>
<Parameter name="occurrences" value="12"/>
<Parameter name="start_date" value="2024-01-01T00:00:00"/>
</Pay>With Full Traceability
<Pay
paymentConnector="shuttle-pay-connector"
action="https://yourapp.com/payment_complete"
chargeAmount="149.99"
description="Premium Plan - Monthly">
<Parameter name="alt_key" value="SUB-2024-001"/>
<Parameter name="account_crm_key" value="cus_123456"/>
<Parameter name="account_first_name" value="Jane"/>
<Parameter name="account_last_name" value="Doe"/>
<Parameter name="account_email" value="[email protected]"/>
<Parameter name="metadata_plan" value="premium"/>
<Parameter name="metadata_billing_cycle" value="monthly"/>
</Pay>Handling Payment Responses
The <Pay> verb sends a POST request to your action URL with payment results.
Response Fields
| Field | Description |
|---|---|
Result | Twilio status (check PayConnector_payment_status instead) |
PayErrorCode | Twilio error code if applicable |
PaymentError | Error message or decline reason |
PaymentConfirmationCode | Shuttle payment ID |
PaymentToken | Shuttle payment method ID (for tokenization) |
PayConnector_payment_status | Primary status field - Always check this |
PayConnector_gateway_status | Gateway response (APPROVED, DECLINED, etc.) |
PayConnector_gateway_message | Detailed gateway message |
PayConnector_reference | Your reference (alt_key) |
PayConnector_gateway_reference | Gateway transaction ID |
PayConnector_account | Shuttle account ID |
PayConnector_contract | Recurring contract ID |
PayConnector_payment_method | Saved payment method ID |
PayConnector_transaction | Shuttle transaction ID |
PayConnector_gateway | Gateway identifier |
PaymentCardNumber | Masked card number |
PaymentCardType | Card brand (visa, mastercard, etc.) |
ExpirationDate | Card expiry (MMYY format) |
SecurityCode | Masked CVV |
PaymentCardPostalCode | AVS postal code |
PaymentMethod | Payment type (ach-debit for ACH) |
BankAccountType | Account type (consumer-checking, etc.) |
BankRoutingNumber | Bank routing number |
BankAccountNumber | Masked account number |
Payment Status Values
| Status | Action |
|---|---|
SUCCESS, UNATTRIBUTED | Payment successful - provision service |
PENDING, UNRESOLVED | Payment processing - await webhook |
DECLINED, REQAUTH | Payment failed - retry |
Decline Types
The PayConnector_gateway_status field provides specific decline reasons:
| Type | Customer Action |
|---|---|
DECLINED | Check details and retry |
DECLINED_CALL_BANK | Contact bank (e.g., insufficient funds) |
DECLINED_BLOCKED | Try different card |
DECLINED_ERROR | Technical issue - contact support |
DECLINED_RETRY | Temporary issue - retry |
Example Response Handling
Success Response (Card Payment)
{
"Result": "success",
"PaymentError": "",
"PaymentConfirmationCode": "pay_31660_10007",
"PaymentToken": "",
"PayConnector_account": "acc_20648_10002",
"PayConnector_contract": "co_20648_10002",
"PayConnector_gateway_reference": "pay_56242536421653621",
"PayConnector_gateway_status": "APPROVED",
"PayConnector_payment_method": "pm_20648_10002",
"PayConnector_payment_status": "SUCCESS",
"PayConnector_reference": "REF-00010002",
"PayConnector_transaction": "tr_20648_10002",
"PaymentCardNumber": "xxxxxxxxxxxx4242",
"PaymentCardType": "visa",
"ExpirationDate": "1223",
"SecurityCode": "xxx",
"PaymentCardPostalCode": ""
}Success Response (ACH Payment)
{
"Result": "success",
"PaymentError": "",
"PaymentConfirmationCode": "pay_31660_10007",
"PaymentToken": "",
"PayConnector_account": "acc_20648_10002",
"PayConnector_contract": "co_20648_10002",
"PayConnector_gateway_reference": "pay_56242536421653621",
"PayConnector_gateway_status": "APPROVED",
"PayConnector_payment_method": "pm_20648_10002",
"PayConnector_payment_status": "SUCCESS",
"PayConnector_reference": "REF-00010002",
"PayConnector_transaction": "tr_20648_10002",
"PaymentMethod": "ach-debit",
"BankAccountType": "consumer-checking",
"BankRoutingNumber": "110000000",
"BankAccountNumber": "xxxxxxxxxx89"
}Decline Response
{
"Result": "payment-connector-error",
"PayErrorCode": "64008",
"PaymentError": "Payment Gateway rejected charge creation.",
"PaymentConfirmationCode": "",
"PaymentToken": "",
"PayConnector_account": "acc_20648_10004",
"PayConnector_contract": "co_20648_10004",
"PayConnector_gateway": "gw_31660_10002",
"PayConnector_gateway_status": "DECLINED",
"PayConnector_gateway_message": "Invalid CVC",
"PayConnector_payment_method": "pm_20648_10004",
"PayConnector_payment_status": "DECLINED",
"PayConnector_reference": "BOLT-00010004",
"PayConnector_transaction": "tr_20648_10004",
"PaymentCardNumber": "xxxxxxxxxxxx4242",
"PaymentCardType": "visa",
"ExpirationDate": "1223",
"SecurityCode": "xxx",
"PaymentCardPostalCode": ""
}Error Response
{
"Result": "too-many-failed-attempts",
"PaymentError": "",
"PaymentCardNumber": "",
"PaymentCardPostalCode": "",
"PaymentCardType": "",
"PaymentConfirmationCode": "",
"PaymentToken": ""
}Error Response - Invalid Credentials
Warning: Twilio returns invalid credentials as "success" with no corresponding data. Always check
PayConnector_payment_status:
{
"Result": "success",
"PaymentError": "",
"PaymentConfirmationCode": "",
"PaymentToken": "",
"PaymentCardNumber": "xxxxxxxxxxxx4242",
"PaymentCardType": "visa",
"ExpirationDate": "1223",
"SecurityCode": "xxx",
"PaymentCardPostalCode": ""
}Important: Always check
PayConnector_payment_statusas Twilio may returnResult: "success"even for failed payments.
Webhooks
Configure webhooks to ensure reliable payment tracking, especially for:
- Disconnected calls during payment
- Gateway timeouts
- Held transactions requiring review
- Scheduled/recurring payment updates
Key Webhook Events
| Event | Description |
|---|---|
PAYMENT.SUCCESS | Payment completed successfully |
PAYMENT.DECLINE | Payment declined (important for recurring) |
CAPTURE.SUCCESS | Capture completed (for async gateways) |
CAPTURE.DECLINE | Capture failed |
REFUND.SUCCESS | Refund processed |
Configure webhooks in your Shuttle instance settings. Each webhook contains reference IDs - use the API to retrieve full details.
API Integration
Access advanced features through the Shuttle API.
Authentication
URL: https://api.shuttleglobal.com/c/api/instances/{instance_key}
Header: Authorization: Basic {your_api_key}
Find your authentication details in the merchant portal under your application => Settings.
Common Operations
Retrieve Payment Details
GET /payments/{payment_id}
Process Refund
POST /payments/{payment_id}/refund
{
"amount": "19.99"
}
Capture Pre-Authorization
POST /payments/{payment_id}/capture
{
"amount": "99.99"
}
Void Authorization
POST /payments/{payment_id}/void
Charge Saved Payment Method
POST /payments
{
"payment_method_id": "pm_20648_10002",
"amount": "49.99",
"currency": "USD"
}
Manage Recurring Payments
# Update schedule
PUT /contracts/{contract_id}
{
"amount": "29.99"
}
# Cancel recurring
POST /contracts/{contract_id}/cancel
Create Payment Link
POST /checkouts
{
"amount": "99.99",
"currency": "USD",
"description": "Invoice #12345"
}
Best Practices
- Always use
alt_key- Pass your internal reference for easy reconciliation - Include customer data - Use
account_*parameters for better tracking - Handle all statuses - Don't assume success; check
PayConnector_payment_status - Configure webhooks - Essential for reliable payment tracking
- Test thoroughly - Use our demo app to verify your implementation
- Use metadata - Pass business context through
metadata_*parameters
Troubleshooting
Common Issues
-
"Invalid credentials" with Result: success
- Always verify
PayConnector_payment_statusexists - Check your instance key and secret key
- Always verify
-
Postal code errors
- Set
postalCode="false"for non-US/CA customers - Pass known postal codes directly:
postalCode="12345"
- Set
-
ACH requirements
- Always include
AVSNameparameter for ACH payments - Ensure customer name matches bank account
- Always include
-
Slow gateways
- Configure
<Prompt for="payment-processing">messages - Implement webhook handlers for async results
- Configure
Additional Resources
Updated 18 days ago