Make Your First Payment
This guide walks you through creating and executing your first payment using TreasuryPath. You'll learn how to generate a quote, create a payment using that quote, and track the payment status.
What You'll Learn
- How to get payment profile IDs from your bank accounts
- How to create a payment quote
- How to create a payment using the quote
- How to track payment status via webhooks
- Understanding payment lifecycle and statuses
Prerequisites
Before making payments:
- ✅ Company and entity created (see Setup Your Organization)
- ✅ Multi-currency feature enabled and ACTIVE (see Enable Multi-Currency)
- ✅ Funding account linked with active payment profile (see Connect Funding Accounts)
- ✅ Recipient created with bank account and active payment profile (see Add Your First Recipient)
- ✅ A valid JWT token (see Authentication)
- ✅ Company ID from your organization setup
Understanding Payments
Payments are financial transfers between two payment profiles - typically from your funding account (source) to a recipient's bank account (destination).
Key Concepts
- Payment Quotes: Provide pricing, fees, and timing information before creating a payment
- Quote Validity: Quotes expire 15 minutes after creation
- Payment Profiles: Each bank account has payment profiles that define usage type (debit, credit, balance)
- Idempotency: Prevents duplicate payments using unique idempotency keys
- Payment Reasons: Required codes that categorize the payment purpose for compliance
How It Works
Step 1: Get Payment Profile IDs
Before creating a payment, retrieve the payment profile IDs from your bank accounts.
List Bank Accounts
curl -X GET "https://api.treasurypath.com/api/v1/companies/{company_id}/bank_accounts" \
-H "Authorization: Bearer {your_jwt_token}"
Replace:
- {company_id} - Your company ID
- {your_jwt_token} - Your JWT authentication token
Example Response
{
"data": [
{
"id": "Z2lkOi8vd2FsbGV0LWFwcC9CYW5rQWNjb3VudC82NQ",
"currency": "USD",
"owner_type": "Entity",
"payment_profiles": [
{
"id": "Z2lkOi8vd2FsbGV0LWFwcC9QYXltZW50UHJvZmlsZS81",
"status": "active",
"currency": "USD",
"payment_method": "ach",
"usage_type": "debit"
}
]
},
{
"id": "Z2lkOi8vd2FsbGV0LWFwcC9CYW5rQWNjb3VudC82Ng",
"currency": "USD",
"owner_type": "Counterparty",
"payment_profiles": [
{
"id": "Z2lkOi8vd2FsbGV0LWFwcC9QYXltZW50UHJvZmlsZS83",
"status": "active",
"currency": "USD",
"payment_method": "ach",
"usage_type": "credit"
}
]
}
]
}
Identify Payment Profiles
From the response, identify:
- Source Profile (
from_profile_id): Payment profile withusage_type: "debit"from your funding account - Destination Profile (
to_profile_id): Payment profile withusage_type: "credit"from the recipient's account
Active Profiles Required
Both payment profiles must have status: "active" to create a quote and payment.
Save Profile IDs
Copy and save:
- The id from the debit payment profile for from_profile_id
- The id from the credit payment profile for to_profile_id
Step 2: Create a Payment Quote
Generate a quote to get pricing, fees, exchange rates, and expected completion date for your payment.
curl -X POST "https://api.treasurypath.com/api/v1/companies/{company_id}/quotes" \
-H "Authorization: Bearer {your_jwt_token}" \
-H "Content-Type: application/json" \
-d '{
"quote": {
"from_profile_id": "Z2lkOi8vd2FsbGV0LWFwcC9QYXltZW50UHJvZmlsZS81",
"to_profile_id": "Z2lkOi8vd2FsbGV0LWFwcC9QYXltZW50UHJvZmlsZS83",
"instructed_amount": {
"amount": 1000.00,
"currency": "USD"
}
}
}'
Replace:
- {company_id} - Your company ID
- {your_jwt_token} - Your JWT authentication token
- from_profile_id - Payment profile ID with usage_type: "debit" from Step 1
- to_profile_id - Payment profile ID with usage_type: "credit" from Step 1
- amount - Payment amount
- currency - Payment currency (e.g., "USD", "EUR", "GBP")
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
from_profile_id |
string | Yes | Source payment profile ID (usage_type: "debit") |
to_profile_id |
string | Yes | Destination payment profile ID (usage_type: "credit") |
instructed_amount.amount |
number | Yes | Payment amount |
instructed_amount.currency |
string | Yes | ISO 4217 currency code |
Success Response
{
"data": {
"id": "Z2lkOi8vd2FsbGV0LWFwcC9QYXltZW50UXVvdGUvMQ",
"created_at": "2025-01-17T10:30:00.000Z",
"updated_at": "2025-01-17T10:30:00.000Z",
"instructed_amount": "1000.0",
"instructed_amount_currency": "USD",
"source_amount": "1000.0",
"source_amount_currency": "USD",
"target_amount": "1000.0",
"target_amount_currency": "USD",
"exchange_rate": "1.0",
"expires_at": "2025-01-17T10:45:00.000Z",
"fee": "0.0",
"fee_currency": "USD",
"expected_completion_date": "2025-01-18",
"from_profile": {
"id": "Z2lkOi8vd2FsbGV0LWFwcC9QYXltZW50UHJvZmlsZS81",
"status": "active",
"currency": "USD",
"payment_method": "ach",
"usage_type": "debit"
},
"to_profile": {
"id": "Z2lkOi8vd2FsbGV0LWFwcC9QYXltZW50UHJvZmlsZS83",
"status": "active",
"currency": "USD",
"payment_method": "ach",
"usage_type": "credit"
}
}
}
Important Quote Fields
id: Quote identifier - save this for creating the paymentexpires_at: Quote expiration time (15 minutes from creation)fee: Fee amount that will be chargedsource_amount: Total amount debited from source (includes fees)target_amount: Amount credited to destinationexchange_rate: Exchange rate (1.0 for same-currency transfers)expected_completion_date: When the payment is expected to complete
Quote Expiration
Quotes expire 15 minutes after creation. The expires_at field shows the exact expiration time. After expiration, generate a new quote to create a payment.
Save the Quote ID
Copy and save the id field from the data object - you'll need this payment_quote_id for creating the payment in the next step.
Step 3: Create the Payment
Using the quote ID from Step 2, create a payment instruction to execute the transfer.
curl -X POST "https://api.treasurypath.com/api/v1/companies/{company_id}/payments" \
-H "Authorization: Bearer {your_jwt_token}" \
-H "Content-Type: application/json" \
-d '{
"payment_instruction": {
"payment_quote_id": "Z2lkOi8vd2FsbGV0LWFwcC9QYXltZW50UXVvdGUvMQ",
"reason": "business_expenses",
"idempotency_key": "unique-payment-12345-abcdef",
"credit_note": "Invoice #1234 payment",
"debit_note": "Payment for services"
}
}'
Replace:
- {company_id} - Your company ID
- {your_jwt_token} - Your JWT authentication token
- payment_quote_id - Quote ID from Step 2
- reason - Payment reason code (see Payment Reason Codes)
- idempotency_key - Unique identifier to prevent duplicate payments
- credit_note - Optional note visible to the recipient
- debit_note - Optional note for internal reference
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
payment_quote_id |
string | Yes | Quote ID from Step 2 |
reason |
string | Yes | Payment reason code (e.g., "business_expenses") |
idempotency_key |
string | Yes | Unique key to prevent duplicate payments |
credit_note |
string | No | Note visible to the recipient |
debit_note |
string | No | Internal note for the sender |
Success Response
{
"data": {
"id": "Z2lkOi8vd2FsbGV0LWFwcC9QYXltZW50SW5zdHJ1Y3Rpb24vMQ",
"created_at": "2025-01-17T10:30:00.286Z",
"updated_at": "2025-01-17T10:30:00.286Z",
"instructed_amount": "1000.0",
"instructed_amount_currency": "USD",
"quote_id": "Z2lkOi8vd2FsbGV0LWFwcC9QYXltZW50UXVvdGUvMQ",
"reason": "business_expenses",
"status": "pending",
"idempotency_key": "unique-payment-12345-abcdef",
"from_profile": {
"id": "Z2lkOi8vd2FsbGV0LWFwcC9QYXltZW50UHJvZmlsZS81",
"status": "active",
"currency": "USD",
"payment_method": "ach",
"usage_type": "debit"
},
"to_profile": {
"id": "Z2lkOi8vd2FsbGV0LWFwcC9QYXltZW50UHJvZmlsZS83",
"status": "active",
"currency": "USD",
"payment_method": "ach",
"usage_type": "credit"
}
}
}
Payment Created
The payment has been successfully created with status: "pending". Save the payment id to track its status.
Understanding Payment Reason Codes
Payment reason codes are required for regulatory compliance. Common codes include:
| Code | Description | Use Case |
|---|---|---|
business_expenses |
General business expenses | Operational costs, supplies, equipment |
professional_business_services |
Professional services | Legal, accounting, consulting fees |
goods_purchased |
Goods purchased | Inventory, raw materials, products |
bill_payment |
Bill payment | Utilities, rent, subscriptions |
wages_salary |
Wages or salary | Employee compensation, payroll |
transfer_to_own_account |
Internal transfer | Moving funds between your accounts |
For the complete list, see Payment Reason Codes.
Understanding Idempotency Keys
Idempotency keys prevent accidental duplicate payments:
- Unique per payment: Each distinct payment requires a unique key
- Format: Use UUIDs or unique identifiers (e.g.,
"order-12345-20250117-001") - Behavior: Submitting the same key multiple times returns the existing payment
- Scope: Keys are scoped to your company
Generating Idempotency Keys
Use a UUID library or combine unique identifiers like order ID + timestamp. Examples:
- "uuid-a7b3c1d9-e2f4-4a5b-8c9d-0e1f2a3b4c5d"
- "invoice-INV-2025-001-20250117"
- "payroll-2025-01-15-employee-12345"
Step 4: Monitor Payment Status
Track the payment status through webhooks or API polling.
Payment Lifecycle
Payments progress through these statuses:
| Status | Description |
|---|---|
pending |
Payment created but not yet submitted to the payment network |
processing |
Payment is being processed by the payment network |
completed |
Payment successfully completed (terminal status) |
failed |
Payment failed and will not be processed (terminal status) |
Receive Webhook Notifications (Recommended)
Set up webhooks to receive real-time payment status updates.
Payment Completed Event
Event Type: PaymentEvents::CompletedEvent
Triggered when a payment successfully completes.
{
"event": "PaymentEvents::CompletedEvent",
"timestamp": "2025-01-17T14:30:00.000Z",
"company_id": "Z2lkOi8vYXBwL0NvbXBhbnkvMTIz",
"resource_id": "Z2lkOi8vd2FsbGV0LWFwcC9QYXltZW50SW5zdHJ1Y3Rpb24vNDU2",
"actor_id": null
}
Payment Failed Event
Event Type: PaymentEvents::FailedEvent
Triggered when a payment fails to process.
{
"event": "PaymentEvents::FailedEvent",
"timestamp": "2025-01-17T14:30:00.000Z",
"company_id": "Z2lkOi8vYXBwL0NvbXBhbnkvMTIz",
"resource_id": "Z2lkOi8vd2FsbGV0LWFwcC9QYXltZW50SW5zdHJ1Y3Rpb24vNDU2",
"actor_id": null
}
Setting Up Webhooks
Configure webhook endpoints to receive these notifications. See the Webhooks Guide for setup instructions.
Alternative: Check Payment Status via API
If webhooks aren't configured, poll the payment details endpoint:
curl -X GET "https://api.treasurypath.com/api/v1/companies/{company_id}/payments/{payment_id}" \
-H "Authorization: Bearer {your_jwt_token}"
Common Errors
Quote Expired
Solution: Quotes expire 15 minutes after creation. Generate a new quote and create the payment using the new quote ID.
Invalid Payment Profile
{
"errors": [
{
"field": "from_profile_id",
"message": "Payment profile is not in active status"
}
]
}
Solution: Ensure both payment profiles have status: "active". Inactive, draft, or failed profiles cannot be used for quotes or payments.
Missing Idempotency Key
Solution: Include a unique idempotency_key in your payment request.
Invalid Reason Code
Solution: Use a valid payment reason code from the Payment Reason Codes reference.
Insufficient Funds
If a payment fails due to insufficient funds, you'll receive a PaymentEvents::FailedEvent webhook. Fetch the payment details to see the specific failure reason.
Solution: Ensure the funding account has sufficient balance before creating payments.
Best Practices
Quote Management
- ✅ Generate quotes immediately before creating payments
- ✅ Check the
expires_atfield and act within 15 minutes - ✅ Generate new quotes if exchange rates or fees need updating
- ✅ Save quote IDs for payment creation and record-keeping
Payment Creation
- ✅ Always use unique idempotency keys for each distinct payment
- ✅ Choose accurate payment reason codes for compliance
- ✅ Include descriptive notes (credit_note, debit_note) for clarity
- ✅ Verify payment profile IDs before creating quotes
Status Monitoring
- ✅ Use webhooks for real-time status updates (recommended)
- ✅ Store payment IDs for tracking and reconciliation
- ✅ Handle both completed and failed payment events
- ✅ Monitor failed payments and notify relevant parties
Security and Compliance
- ✅ Never reuse idempotency keys across different payments
- ✅ Verify webhook signatures to ensure authenticity
- ✅ Use HTTPS for all API communications
- ✅ Follow regulatory requirements for payment categorization
Error Handling
- ✅ Implement retry logic for expired quotes
- ✅ Handle payment failures gracefully
- ✅ Provide clear error messages to users
- ✅ Log all payment attempts for audit trails
What's Next?
Once you've made your first payment, you can:
- Set Up Webhooks - Configure real-time payment notifications
- List Payments - View all payments for your company
- Cross-Currency Payments - Create payments between different currencies
- Manage Multiple Payment Methods - Use different payment methods (ACH, Wire, SWIFT)
API Reference
For complete API documentation, see:
- Payments API Reference - Full endpoint documentation
- Quotes API Reference - Quote creation and details
- Payment Data Model - Detailed payment properties
- Quote Data Model - Detailed quote properties
- Payment Reason Codes - Complete reason code list
Need Help?
- Check the FAQ for common questions
- Contact support at support@treasurypath.com