# API Request Authentication
Source: https://docs.juicyway.com/authentication
Authenticate your API calls to Payment related endpoints.
Before proceeding with authentication, make sure you've completed the [Quickstart](/quickstart) guide and set up your [Webhooks](/webhooks).
## Authentication Headers
Authenticate your API calls by including your gateway key in the `Authorization` header of every request you make to the payment endpoints.
Generally, we provide both test and live keys. `test` keys are meant to be used from your **sandbox** when integrating Juice API. The `live` keys, however, are to be kept **secret**.
**`Both test and live keys have the format: myusdguyheiuwX746bagbedjyqg, but sandbox keys will not be the same as the production keys.`**
Authorization headers should be in the following format: `Authorization: API_KEY`
**Sample Authorization Header**
```bash theme={null}
Authorization: test_r3m3mb3r2pu70nasm1l3
```
API requests made without authentication will fail with the status code `401: Unauthorized`. See our [Errors](/errors) page for details on handling authentication errors. All API requests must be made over HTTPS.
## API Key Management
### Key Types
* **Test Keys**: Used in the sandbox environment for integration testing
* **Live Keys**: Used in production for processing real transactions
* **Restricted Keys**: Limited-scope keys for specific operations
### Key Security Best Practices
Never commit your API keys to git repositories or expose them in client-side code. Your live production key must be kept secure at all times.
1. **Environment Variables**: Store API keys as environment variables rather than hardcoding them
```bash theme={null}
# .env file
JUICE_API_KEY=live_myusdguyheiuwX746bagbedjyqg
```
2. **Secure Configuration**: Use secure configuration management services in production
```javascript theme={null}
// Node.js example using environment variables
const apiKey = process.env.JUICE_API_KEY;
```
3. **Key Rotation**: Implement a regular key rotation schedule
* Rotate keys every 90 days
* Generate new keys before deactivating old ones
* Update all systems using the keys during maintenance windows
Keep old keys active for a short overlap period (maximum 24 hours) during transition to prevent service disruption.
* Read about [Error Handling](/errors) to properly handle authentication errors
* Explore the Payment APIs to start processing transactions
* Set up your production environment with live keys
# Create Customer
Source: https://docs.juicyway.com/customers/create-customer
Create and manage customers within your integration.
## Overview
The Customers API enables you to create and manage customer profiles for your integration. Each customer object includes personal information, contact details, and billing information that can be referenced in future transactions.
## Create a Customer
```json theme={null}
POST /customers
```
Create a new customer profile with the specified information. Each customer must have a unique email address within your integration.
Ensure phone numbers match the billing address country format. For example, Nigerian phone numbers (+234) should have a Nigerian billing address.
### Request Parameters
Customer's first name.
* Maximum length: 100 characters
* Must contain only letters, spaces, hyphens, and apostrophes
Customer's last name.
* Maximum length: 100 characters
* Must contain only letters, spaces, hyphens, and apostrophes
Customer's email address.
* Must be a valid email format
* Must be unique within your integration
Customer's phone number in E.164 format.
* Must include country code
* Must be a valid number for the billing address country
* Example: +2348012345678
Customer's billing address information.
Street address (first line)
* Maximum length: 100 characters
Street address (second line)
* Maximum length: 100 characters
City name
* Maximum length: 50 characters
State or province
* Maximum length: 50 characters
Postal or ZIP code
* Format varies by country
Two-letter country code (ISO 3166-1 alpha-2)
* Example: "US", "NG", "GB"
Must be of `business` or `individual`
### Code Examples
```bash cURL theme={null}
curl -X POST "https://api.spendjuice.com/customers" \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"first_name": "John",
"last_name": "Doe",
"email": "john.doe@example.com",
"phone_number": "+2348012345678",
"type": "business|individual",
"billing_address": {
"line1": "123 Test Lane",
"line2": "Suite 456",
"city": "Lagos",
"state": "Lagos",
"zip_code": "100001",
"country": "NG"
}
}'
```
```javascript Node.js theme={null}
const response = await fetch('https://api.spendjuice.com/customers', {
method: 'POST',
headers: {
'Authorization': ' YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
first_name: 'John',
last_name: 'Doe',
email: 'john.doe@example.com',
phone_number: '+2348012345678',
type: "business|individual",
billing_address: {
line1: '123 Test Lane',
line2: 'Suite 456',
city: 'Lagos',
state: 'Lagos',
zip_code: '100001',
country: 'NG'
}
})
});
const customer = await response.json();
```
```python Python theme={null}
import requests
response = requests.post(
'https://api.spendjuice.com/customers',
headers={
'Authorization': ' YOUR_API_KEY',
'Content-Type': 'application/json'
},
json={
'first_name': 'John',
'last_name': 'Doe',
'email': 'john.doe@example.com',
'phone_number': '+2348012345678',
'type': 'business|individual',
'billing_address': {
'line1': '123 Test Lane',
'line2': 'Suite 456',
'city': 'Lagos',
'state': 'Lagos',
'zip_code': '100001',
'country': 'NG'
}
}
)
customer = response.json()
```
### Response
```json 201 Success theme={null}
{
"data": {
"id": "6f7e1e7f-93d1-4fcc-b7a4-738f869615c8",
"first_name": "John",
"last_name": "Doe",
"email": "john.doe@example.com",
"phone_number": "+2348012345678",
"type": "business|individual",
"billing_address": {
"line1": "123 Test Lane",
"line2": "Suite 456",
"city": "Lagos",
"state": "Lagos",
"zip_code": "100001",
"country": "NG"
}
}
}
```
```json 400 Validation Error theme={null}
{
"error": {
"code": "validation_error",
"message": "Invalid input parameters",
"details": {
"email": ["Invalid email format"],
"phone_number": ["Phone number does not match country format"]
}
}
}
```
```json 409 Duplicate Customer theme={null}
{
"error": {
"code": "duplicate_customer",
"message": "A customer with this email already exists",
"details": {
"email": ["must be unique"]
}
}
}
```
## Rate Limits
| Environment | Requests per minute |
| ----------- | ------------------- |
| Test | 100 |
| Production | 1000 |
Exceeding these limits will return a `429 Too Many Requests` response.
## Idempotency
All POST requests support idempotency to prevent duplicate customer creation. Include an `Idempotency-Key` header with a unique value for each request:
```bash theme={null}
Idempotency-Key: a123b456-c789-d012-e345-f67890123456
```
The same key will return the original response for duplicate requests within 24 hours.
## Best Practices
1. **Validation**
* Validate email formats before sending
* Ensure phone numbers match country codes
* Use proper character encoding for names
2. **Error Handling**
* Implement retry logic with exponential backoff
* Handle validation errors gracefully
* Check for duplicate customers before creation
3. **Security**
* Use HTTPS for all API calls
* Keep API keys secure
* Implement proper access controls
For support with customer creation:
* Check our [Error Handling Guide](/errors)
* Contact [support@juicyway.com](mailto:support@juicyway.com)
# Delete Customer
Source: https://docs.juicyway.com/customers/delete-customer
Permanently remove a customer record from your integration
Customer deletion is a permanent, irreversible action. Make sure to confirm the deletion intent and understand the implications before proceeding.
## Delete a Customer
```http theme={null}
DELETE /customers/{customer_id}
```
Delete a customer and all associated data. This action cannot be undone.
### Parameters
The unique identifier of the customer to delete
### Cascade Deletion Behavior
When you delete a customer, the following associated data will also be permanently removed:
* Customer profile information
* Saved payment methods
* Billing addresses
* Transaction history references
* Subscription associations
Transaction records themselves are preserved for compliance and audit purposes, even after customer deletion.
### Data Retention Policy
After deletion:
* Customer data is immediately removed from active systems
* Backups are retained for 30 days as per our data retention policy
* Transaction records are maintained in compliance with financial regulations
* Anonymized analytics data may be retained
## Request Examples
```bash cURL theme={null}
curl -X DELETE "https://api.spendjuice.com/v1/customers/cus_12345" \
-H "Authorization: YOUR_API_KEY"
```
```javascript Node.js theme={null}
const response = await juice.customers.delete('cus_12345');
```
```python Python theme={null}
response = juice.Customer.delete('cus_12345')
```
```php PHP theme={null}
$response = $juice->customers->delete('cus_12345');
```
## Response
A successful deletion returns an HTTP `204 No Content` response with no response body.
## Error Scenarios
```json theme={null}
{
"error": {
"code": "customer_not_found",
"message": "No customer found with ID: cus_12345",
"type": "not_found_error"
}
}
```
```json theme={null}
{
"error": {
"code": "deletion_restricted",
"message": "Cannot delete customer with active subscriptions",
"type": "authorization_error"
}
}
```
```json theme={null}
{
"error": {
"code": "deletion_conflict",
"message": "Customer has pending transactions",
"type": "conflict_error"
}
}
```
## Recommended Deletion Workflow
Check for any active subscriptions, pending transactions, or other dependencies that might prevent deletion.
Consider exporting customer data before deletion if needed for records.
Implement a confirmation step in your interface to prevent accidental deletions.
Perform the deletion API call with proper error handling.
Confirm the customer record has been removed by attempting to fetch it.
## Best Practices
* Implement confirmation workflows for deletion requests
* Handle cascade deletion effects in your application
* Maintain audit logs of deletion operations
* Consider soft deletion for recoverable data
* Respect data privacy regulations (GDPR, CCPA)
If you need to preserve customer data for compliance or business purposes, consider implementing a soft delete mechanism instead of permanent deletion.
# Fetch Customer
Source: https://docs.juicyway.com/customers/fetch-customer
Retrieve details of a specific customer by their ID
## Overview
Retrieve detailed information about a specific customer using their unique identifier. This endpoint supports field selection, response versioning, and conditional fetching.
## Base URL
```bash theme={null}
GET /customers/{id}
```
## Path Parameters
The unique identifier of the customer. Example: `6f7e1e7f-93d1-4fcc-b7a4-738f869615c8`
## Query Parameters
Comma-separated list of fields to include in the response. Example: `fields=first_name,email,phone_number`
API version for backwards compatibility. Default: Latest version
Additional related resources to include. Example: `include=transactions,payment_methods`
## Request Examples
```bash cURL theme={null}
curl -X GET "https://api.spendjuice.com/customers/6f7e1e7f-93d1-4fcc-b7a4-738f869615c8" \
-H "Authorization: YOUR_API_KEY" \
-H "Accept: application/json"
```
```javascript Node.js theme={null}
const axios = require('axios');
try {
const response = await axios.get(
'https://api.spendjuice.com/customers/6f7e1e7f-93d1-4fcc-b7a4-738f869615c8',
{
headers: {
'Authorization': ' YOUR_API_KEY',
'Accept': 'application/json'
}
}
);
console.log(response.data);
} catch (error) {
console.error('Error fetching customer:', error.response.data);
}
```
```python Python theme={null}
import requests
headers = {
'Authorization': ' YOUR_API_KEY',
'Accept': 'application/json'
}
try:
response = requests.get(
'https://api.spendjuice.com/customers/6f7e1e7f-93d1-4fcc-b7a4-738f869615c8',
headers=headers
)
response.raise_for_status()
print(response.json())
except requests.exceptions.RequestException as e:
print('Error fetching customer:', e)
```
## Response
```json 200 Success theme={null}
{
"data": {
"id": "6f7e1e7f-93d1-4fcc-b7a4-738f869615c8",
"first_name": "Test",
"last_name": "Customer",
"email": "test@custom.com",
"phone_number": "+2348012345678",
"billing_address": {
"line1": "123 Test lane",
"line2": "3456 Mike Drive",
"city": "Anon",
"state": "Acme",
"zip_code": "12345",
"country": "US"
},
"created_at": "2024-03-15T12:00:00Z",
"updated_at": "2024-03-15T12:00:00Z"
}
}
```
```json 404 Not Found theme={null}
{
"error": {
"code": "customer_not_found",
"message": "No customer found with ID: 6f7e1e7f-93d1-4fcc-b7a4-738f869615c8"
}
}
```
## Rate Limiting
This endpoint has a rate limit of 1000 requests per hour per API key. Rate limit information is included in the response headers:
* `X-RateLimit-Limit`: Total requests allowed per hour
* `X-RateLimit-Remaining`: Remaining requests in the current period
* `X-RateLimit-Reset`: Time when the rate limit resets (Unix timestamp)
## Common Use Cases
```bash theme={null}
GET /customers/{id}?fields=first_name,last_name,email
```
Returns only the customer's basic contact information.
```bash theme={null}
GET /customers/{id}?include=transactions,payment_methods
```
Returns customer details along with their transaction history and saved payment methods.
```bash theme={null}
GET /customers/{id}?version=2023-01-01
```
Returns customer data formatted according to the specified API version.
## Error Responses
| Status Code | Description |
| ----------- | -------------------------------------------------- |
| 400 | Invalid request (malformed parameters) |
| 401 | Authentication failed (invalid or missing API key) |
| 403 | Permission denied |
| 404 | Customer not found |
| 429 | Rate limit exceeded |
| 500 | Internal server error |
## Best Practices
1. Always use HTTPS for API requests
2. Implement proper error handling
3. Cache responses when appropriate
4. Monitor rate limits
5. Use field selection to minimize response payload size
For additional assistance:
* Check our [API Reference](/api-reference/overview)
* Contact [Support](mailto:support@juicyway.com)
# List Customers
Source: https://docs.juicyway.com/customers/list-customers
Retrieve and filter a paginated list of customers
Retrieve a list of customers with support for pagination, filtering, and sorting.
## Endpoint
```bash theme={null}
GET /customers
```
## Query Parameters
Number of records to return per page (max: 100)
Cursor for fetching next page of results
Cursor for fetching previous page of results
Filter customers by email address
Filter customers created after this timestamp (ISO 8601)
Filter customers created before this timestamp (ISO 8601)
Sort order for results (created\_at:asc|created\_at:desc)
## Response Format
Array of customer objects. See [Customer Object](#customer-object) for structure.
Cursor for the previous page
Cursor for the next page
Number of records per page
## Examples
### Basic List Request
```bash cURL theme={null}
curl -X GET "https://api.spendjuice.com/customers?limit=2" \
-H "Authorization: YOUR_API_KEY"
```
```javascript Node.js theme={null}
const juice = require('juice-node');
const client = new juice('YOUR_API_KEY');
const customers = await client.customers.list({
limit: 2
});
```
```python Python theme={null}
import juice
juice.api_key = 'YOUR_API_KEY'
customers = juice.Customer.list(
limit=2
)
```
```json Response theme={null}
{
"data": [
{
"id": "6f7e1e7f-93d1-4fcc-b7a4-738f869615c8",
"first_name": "Test",
"last_name": "Customer",
"email": "test@custom.er",
"phone_number": "+2348012345678",
"billing_address": {
"line1": "123 Test lane",
"line2": "356 Mike Drive",
"city": "Anon",
"state": "Acme",
"zip_code": "12345",
"country": "US"
},
"created_at": "2024-03-01T12:00:00Z",
"updated_at": "2024-03-01T12:00:00Z"
},
{
"id": "7a8b9c0d-1e2f-3g4h-5i6j-7k8l9m0n1o2p",
"first_name": "Jane",
"last_name": "Doe",
"email": "jane@example.com",
"phone_number": "+2348012345679",
"billing_address": {
"line1": "456 Sample St",
"line2": null,
"city": "Lagos",
"state": "LA",
"zip_code": "23401",
"country": "NG"
},
"created_at": "2024-03-02T12:00:00Z",
"updated_at": "2024-03-02T12:00:00Z"
}
],
"pagination": {
"before": null,
"after": "7a8b9c0d-1e2f-3g4h-5i6j-7k8l9m0n1o2p",
"limit": 2
}
}
```
### Filtered List Request
```bash cURL theme={null}
curl -X GET "https://api.spendjuice.com/customers?email=test@custom.er&created_after=2024-01-01T00:00:00Z" \
-H "Authorization: YOUR_API_KEY"
```
```javascript Node.js theme={null}
const customers = await client.customers.list({
email: 'test@custom.er',
created_after: '2024-01-01T00:00:00Z'
});
```
```python Python theme={null}
customers = juice.Customer.list(
email='test@custom.er',
created_after='2024-01-01T00:00:00Z'
)
```
## Pagination
The API uses cursor-based pagination to handle large collections of customers. To fetch the next page of results:
1. Get the `after` cursor from the pagination object
2. Pass it as the `after` parameter in your next request
3. Repeat until no more `after` cursor is returned
For optimal performance, we recommend:
* Use reasonable page sizes (15-50 records)
* Cache results when possible
* Implement progressive loading in your UI
## Error Responses
Invalid query parameters or malformed request
Missing or invalid API key
Insufficient permissions to list customers
## Rate Limits
List operations are subject to the following rate limits:
* 100 requests per minute per API key
* 1000 requests per hour per API key
Exceeding these limits will result in a `429 Too Many Requests` response.
## Best Practices
1. **Efficient Filtering**: Use filters to reduce response size and improve performance
2. **Cursor Management**: Store cursors temporarily for pagination
3. **Bulk Operations**: Use higher limit values for bulk data retrieval
4. **Error Handling**: Implement proper retry logic for rate limits
5. **Data Freshness**: Consider implementing cache invalidation strategies
## Customer Object
See the [Customer Object](/snippets/customer-object.mdx) documentation for detailed field descriptions.
# Update Customer
Source: https://docs.juicyway.com/customers/update-customer
Update an existing customer's information
## Overview
The customer update endpoint allows you to modify existing customer information. You can perform both partial and full updates to customer records.
## Base URL
```bash theme={null}
PATCH /customers/{id}
```
## Authentication
All requests must include your API key in the Authorization header:
```bash theme={null}
Authorization: YOUR_API_KEY
```
## Request Parameters
### Path Parameters
The unique identifier of the customer to update
### Body Parameters
Customer's first name
Customer's last name
Customer's email address. Must be a valid email format.
Customer's phone number in E.164 format (e.g., +2348012345678)
Customer's billing address information
Primary address line
Secondary address line (optional)
City name
State or province
Postal or ZIP code
Two-letter country code (ISO 3166-1 alpha-2)
## Examples
```bash cURL theme={null}
curl -X PATCH "https://api.spendjuice.com/customers/6f7e1e7f-93d1-4fcc-b7a4-738f869615c8" \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"phone_number": "+2348012345678",
"billing_address": {
"line1": "123 Test lane",
"city": "Anon"
}
}'
```
```python Python theme={null}
import requests
url = "https://api.spendjuice.com/customers/6f7e1e7f-93d1-4fcc-b7a4-738f869615c8"
headers = {
"Authorization": " YOUR_API_KEY",
"Content-Type": "application/json"
}
data = {
"phone_number": "+2348012345678",
"billing_address": {
"line1": "123 Test lane",
"city": "Anon"
}
}
response = requests.patch(url, headers=headers, json=data)
print(response.json())
```
```javascript Node.js theme={null}
const axios = require('axios');
const customerUpdate = async () => {
try {
const response = await axios.patch(
'https://api.spendjuice.com/customers/6f7e1e7f-93d1-4fcc-b7a4-738f869615c8',
{
phone_number: '+2348012345678',
billing_address: {
line1: '123 Test lane',
city: 'Anon'
}
},
{
headers: {
'Authorization': ' YOUR_API_KEY',
'Content-Type': 'application/json'
}
}
);
return response.data;
} catch (error) {
console.error('Error updating customer:', error.response.data);
}
};
```
## Response
### Success Response (200 OK)
```json theme={null}
{
"data": {
"id": "6f7e1e7f-93d1-4fcc-b7a4-738f869615c8",
"first_name": "Test",
"last_name": "Customer",
"email": "test@custom.er",
"phone_number": "+2348012345678",
"billing_address": {
"line1": "123 Test lane",
"line2": "3456 Mike Drive",
"city": "Anon",
"state": "Acme",
"zip_code": "12345",
"country": "US"
}
}
}
```
### Error Responses
```json theme={null}
{
"error": {
"code": "invalid_request",
"message": "Invalid parameters provided",
"details": {
"phone_number": ["Invalid phone number format"]
}
}
}
```
```json theme={null}
{
"error": {
"code": "not_found",
"message": "Customer not found"
}
}
```
```json theme={null}
{
"error": {
"code": "validation_error",
"message": "The request contains invalid parameters",
"details": {
"email": ["Invalid email format"]
}
}
}
```
## Update Rules
* Only provide fields that need to be updated
* Nested objects (like billing\_address) must be updated as a complete object
* Empty strings ("") will clear the field value
* Null values are ignored
* Phone numbers must be in E.164 format
* Email addresses must be valid format
## Rate Limits
Customer update requests are limited to:
* 10 requests per minute per API key
* 1000 requests per day per API key
## Versioning
The current version of this API is v1. We recommend including a version accept header:
```bash theme={null}
Accept: application/json;version=1
```
## Best Practices
1. **Partial Updates**
* Only send fields that need to be changed
* Use PATCH for partial updates
* Validate data before sending
2. **Error Handling**
* Implement proper error handling
* Validate response status codes
* Log failed update attempts
3. **Idempotency**
* Use idempotency keys for critical updates
* Retry failed requests with the same idempotency key
4. **Validation**
* Validate all input fields client-side
* Handle validation errors appropriately
* Check response data matches expected format
For additional support:
* Check our [API Reference](/api-reference/overview)
* Contact [Support](mailto:support@juicyway.com)
* Join our [Developer Community](https://discord.gg/juice)
# Errors
Source: https://docs.juicyway.com/errors
Learn how to handle errors when integrating with the Juice API
## HTTP Status Codes
Here are the common HTTP status codes you may encounter when using our API:
### 200 - Success
The request was successful, and the intended action was completed.
For charge or verification requests, always check the `data` object to confirm the specific outcome (success or failure).
### 201 - Created
A new resource was successfully created.
### 204 - No Content
The request was successful, but no content is returned in the response.
### 400 - Bad Request
A validation or client-side error occurred, preventing the request from being processed.
### 401 - Unauthorized
The request was not authorized. This commonly occurs due to:
* Invalid secret key in authorization header
* Missing authorization header
* Expired API key
* Using test key in production environment
* Using production key in test environment
### 403 - Forbidden
Access to the requested resource is denied due to insufficient permissions.
### 404 - Not Found
The requested resource could not be found.
This status code does not apply when a payment session is completed.
### 422 - Unprocessable Entity
Some required fields are missing or invalid, preventing the request from being processed.
### 429 - Too Many Requests
You've exceeded the API rate limits.
### 500 - Server Error
The request could not be fulfilled due to an error on Juicyway's server.
Please report any encounters with 500 errors to our support team.
## Error Response Format
All API errors follow a consistent format:
```json theme={null}
{
"error": {
"code": "error_code",
"message": "Human readable error message",
"type": "error_type",
"details": {
// Additional error context if available
}
}
}
```
## Common Error Types
### Validation Errors
When required fields are missing or invalid:
```json theme={null}
{
"error": {
"code": "validation_error",
"message": "The request was invalid",
"type": "invalid_request_error",
"errors": [
{
"field": "amount",
"message": "Amount must be a positive integer"
},
{
"field": "currency",
"message": "Currency must be one of: NGN, USD, CAD"
}
]
}
}
```
### Authentication Errors
When there are issues with API keys or authentication:
```json theme={null}
{
"error": {
"code": "invalid_key",
"message": "Invalid API key provided",
"type": "authentication_error"
}
}
```
### Rate Limiting Errors
When you exceed the API rate limits:
```json theme={null}
{
"error": {
"code": "rate_limit_exceeded",
"message": "Too many requests. Please try again in 30 seconds.",
"type": "rate_limit_error",
"retry_after": 30
}
}
```
### Server Errors
For 500-level server errors:
```json theme={null}
{
"error": {
"code": "internal_server_error",
"message": "An unexpected error occurred",
"type": "server_error",
"request_id": "req_123xyz"
}
}
```
## Error Handling Best Practices
### Timeout Handling
All API requests automatically timeout after 30 seconds. For long-running operations like payments that may take longer to process, we recommend:
1. Implementing proper retry logic with exponential backoff
2. Using webhooks to receive the final status asynchronously
3. Checking the transaction status via the GET endpoints if webhook delivery fails
### Rate Limit Handling
To handle rate limits effectively:
1. Implement exponential backoff with jitter for retries
2. Check the `retry_after` header to know when to retry
3. Cache frequently requested data
4. Batch requests where possible
### Server Error Handling
Best practices for handling server errors:
1. Log the `request_id` for debugging
2. Implement retry logic with exponential backoff
3. Contact support if errors persist
4. Set up monitoring for error rates
## Code Examples
Here's how to properly handle API errors in different languages:
```javascript theme={null}
try {
const response = await juiceApi.createPayment({
amount: 1000,
currency: 'NGN'
});
} catch (error) {
if (error.type === 'validation_error') {
// Handle validation errors
error.errors.forEach(err => {
console.log(`${err.field}: ${err.message}`);
});
} else if (error.type === 'authentication_error') {
// Handle auth errors
console.log('Please check your API keys');
} else if (error.type === 'rate_limit_error') {
// Implement exponential backoff
const retryAfter = error.retry_after || 30;
await sleep(retryAfter * 1000);
// Retry request
} else {
// Handle other errors
console.error(`Error: ${error.message}`);
// Log error for debugging
console.error(`Request ID: ${error.request_id}`);
}
}
```
```python theme={null}
try:
response = juice_api.create_payment(
amount=1000,
currency='NGN'
)
except ValidationError as e:
# Handle validation errors
for error in e.errors:
print(f"{error['field']}: {error['message']}")
except AuthenticationError as e:
# Handle auth errors
print("Please check your API keys")
except RateLimitError as e:
# Implement exponential backoff
retry_after = getattr(e, 'retry_after', 30)
time.sleep(retry_after)
# Retry request
except ServerError as e:
# Handle server errors
print(f"Error: {e.message}")
# Log error for debugging
print(f"Request ID: {e.request_id}")
except Exception as e:
# Handle unexpected errors
print(f"Unexpected error: {str(e)}")
```
# Add Contact
Source: https://docs.juicyway.com/exchange/market-makers/add-contact
Add a contact to a market maker.
```json theme={null}
PATCH /exchange/market-makers/{id}/add-contact
```
**Parameters:**
* `id` (string, required): The unique ID of the market maker.
* `email` (string, required): Contact email.
* `id` (string, required): Contact ID.
* `name` (string, required): Contact name.
* `type` (string, required): Contact type (`user` or `business`).
**Sample Request**
```bash theme={null}
curl -X PATCH "https://exchange.spendjuice.com/v1/exchange/market-makers/7da75a46-a1bc-11ee-9a32-560f156a658b/add-contact" \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"email": "new@user.com",
"id": "7da8e726-a1bc-11ee-80cf-560f156a658b",
"name": "New User",
"type": "user"
}'
```
**Sample Response**
```json theme={null}
{
"data": {
"beneficiary": {
"account_name": "MICHAEL ENITAN ASAJU",
"account_number": "0821081314",
"account
```
# Create a Market Maker
Source: https://docs.juicyway.com/exchange/market-makers/create-market-makers
The endpoint below creates a new market maker for the exchange.
```json theme={null}
POST /exchange/market-makers
```
#### **Request**
* **Headers**:
`Authorization: YOUR_API_KEY`
* **Body** (required):
* **Media Type**: `application/json`
```json theme={null}
{
"business_id": "7da8e726-a1bc-11ee-80cf-560f156a658b",
"contacts": [
{
"id": "7da8e726-a1bc-11ee-80cf-560f156a658b",
"type": "user"
}
],
"swap_provider": true,
"swap_weight": 50
}
```
### **Fields:**
* `business_id` (string, required): The ID of the business to be assigned as a market maker.
* `contacts `(array of objects, required): A list of associated contact users.
* `id `(string, required): Contact user ID.
* `type `(string, required): The type of contact (e.g., user).
* `swap_provider` (boolean, required): Indicates if the market maker provides swaps.
* `swap_weight` (integer, required): The weight or priority for the swap service (e.g., 0–100).
#### **Responses:**
**201 Created**
1. **Media Type**: `application/json`
2. **Sample Response**:
```json theme={null}
{
"data": {
"archived": false,
"contacts": [
{
"email": "test@user.com",
"id": "7da8e726-a1bc-11ee-80cf-560f156a658b",
"name": "Test User",
"type": "user"
}
],
"email": "anon@nymous.com",
"entity": {
"id": "6ebe0a0f-bb8f-49be-80ea-c6b72c348fea",
"type": "business"
},
"id": "7da75a46-a1bc-11ee-9a32-560f156a658b",
"name": "Anon Nymous",
"swap_provider": false,
"swap_weight": 0
}
}
```
* **400 Bad Request**- Returned if the request contains invalid data.
* **403 Forbidden**- Returned if the user is not authorized to create a market maker.
* **422 Unprocessable Entity**- Returned if required fields are missing or invalid.
# Get Market Maker
Source: https://docs.juicyway.com/exchange/market-makers/get-market-makers
Retrieve details of a specific market maker by ID.
```json theme={null}
GET /exchange/market-makers/{id}
```
**Parameters:**
* `id` (string, required): The unique ID of the market maker.
**Sample Request**
```bash theme={null}
curl -X GET "https://exchange.spendjuice.com/v1/exchange/market-makers/7da75a46-a1bc-11ee-9a32-560f156a658b" \
-H "Authorization: YOUR_API_KEY"
```
**Sample Response**
```json theme={null}
{
"data": {
"archived": false,
"contacts": [
{
"email": "test@user.com",
"id": "7da8e726-a1bc-11ee-80cf-560f156a658b",
"name": "Test User",
"type": "user"
}
],
"email": "anon@nymous.com",
"entity": {
"id": "6ebe0a0f-bb8f-49be-80ea-c6b72c348fea",
"type": "business"
},
"id": "7da75a46-a1bc-11ee-9a32-560f156a658b",
"name": "Anon Nymous",
"swap_provider": true,
"swap_weight": 50
}
}
```
# Market Makers
Source: https://docs.juicyway.com/exchange/market-makers/list-market-makers
Market makers facilitate liquidity on the exchange by providing buy and sell quotes for specific trading pairs. This section outlines how to interact with market maker data via API.
The endpoint below lists all available market makers.
```
GET /exchange/market-makers
```
#### **Parameters**
* **`before`** *(string, optional)*: Cursor for retrieving records before a specific entry.
* **`after`** *(string, optional)*: Cursor for retrieving records after a specific entry.
* **`limit`** *(integer, optional)*: Maximum number of records to return. Default: 15.
#### **Responses**
1. **200 OK**
* **Media Type**: `application/json`
* **Sample Response**:
```json theme={null}
{
"data": [
{
"archived": false,
"contacts": [
{
"email": "test@user.com",
"id": "7da8e726-a1bc-11ee-80cf-560f156a658b",
"name": "Test User",
"type": "user"
}
],
"email": "anon@nymous.com",
"entity": {
"id": "6ebe0a0f-bb8f-49be-80ea-c6b72c348fea",
"type": "business"
},
"id": "7da75a46-a1bc-11ee-9a32-560f156a658b",
"name": "Anon Nymous",
"swap_provider": false,
"swap_weight": 0
}
],
"pagination": {
"after": "b101f718-d133-450c-a572-c281c7341803",
"before": null,
"limit": 15
}
}
```
# Remove Contact
Source: https://docs.juicyway.com/exchange/market-makers/remove-contact
Remove a contact from a market maker.
```json theme={null}
PATCH /exchange/market-makers/{id}/remove-contact
```
**Parameters:**
* `id` (string, required): The unique ID of the market maker.
* `contact_id` (string, required): The ID of the contact to remove.
**Sample Request**
```json theme={null}
curl -X PATCH "https://exchange.spendjuice.com/v1/exchange/market-makers/7da75a46-a1bc-11ee-9a32-560f156a658b/remove-contact" \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"contact_id": "7da8e726-a1bc-11ee-80cf-560f156a658b"
}'
```
**Sample Response**
```json theme={null}
{
"data": {
"archived": true,
"contacts": [],
"email": "anon@nymous.com",
"entity": {
"id": "6ebe0a0f-bb8f-49be-80ea-c6b72c348fea",
"type": "business"
},
"id": "7da75a46-a1bc-11ee-9a32-560f156a658b",
"name": "Anon Nymous",
"swap_provider": false,
"swap_weight": 0
}
}
```
# Update Market Maker
Source: https://docs.juicyway.com/exchange/market-makers/update-market-maker
Update an existing market maker.
```json theme={null}
PATCH /exchange/market-makers/{id}
```
**Parameters:**
* `id` (string, required): The unique ID of the market maker to update.
* `archived` (boolean, optional): Whether the market maker is archived.
* `swap_provider` (boolean, optional): Whether the market maker is a swap provider.
* `swap_weight` (integer, optional): Swap weight.
**Sample Request**
```bash theme={null}
curl -X PATCH "https://exchange.spendjuice.com/v1/exchange/market-makers/7da75a46-a1bc-11ee-9a32-560f156a658b" \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"archived": true,
"swap_provider": false,
"swap_weight": 0
}'
```
**Sample Response**
```json theme={null}
{
"data": {
"archived": true,
"contacts": [
{
"email": "test@user.com",
"id": "7da8e726-a1bc-11ee-80cf-560f156a658b",
"name": "Test User",
"type": "user"
}
],
"email": "anon@nymous.com",
"entity": {
"id": "6ebe0a0f-bb8f-49be-80ea-c6b72c348fea",
"type": "business"
},
"id": "7da75a46-a1bc-11ee-9a32-560f156a658b",
"name": "Anon Nymous",
"swap_provider": false,
"swap_weight": 0
}
}
```
# Cancel Order
Source: https://docs.juicyway.com/exchange/orders/cancel-order
Cancel an existing order.
```json theme={null}
PUT /exchange/orders/{id}/cancel
```
**Parameters:**
* `id` (string, required): The unique ID of the order to cancel.
**Sample Request**
```bash theme={null}
curl -X PUT "https://exchange.spendjuice.com/v1/exchange/orders/7da75a46-a1bc-11ee-9a32-560f156a658b/cancel" \
-H "Authorization: YOUR_API_KEY"
```
**Sample Response**
```json theme={null}
{
"data": {
"accepted_at": "2023-12-23T17:55:42.919523",
"average_fill_price": 80000,
"business_id": "dd625bec-b1a3-466e-867e-c91ae0b6e71e",
"correlation_id": "7da742ea-a1bc-11ee-b907-560f156a658b",
"created_at": "2023-12-23T17:55:42.911",
"expires_at": null,
"id": "7da75a46-a1bc-11ee-9a32-560f156a658b",
"min_qty": null,
"min_quote_qty": null,
"percent_filled": 10000,
"price": 80000,
"price_type": "market",
"qty": 1.0,
"quote_qty": null,
"status": "cancelled",
"symbol": "USD-NGN",
"time_in_force": "gtc",
"trades": [],
"type": "buy",
"updated_at": "2023-12-23T17:55:42.911",
"user_id": "b101f718-d133-450c-a572-c281c7341803"
}
}
```
# Create Orders
Source: https://docs.juicyway.com/exchange/orders/create-order
Create a new order.
```json theme={null}
POST /exchange/orders
```
**Parameters:**
* `qty` (number, required): Order quantity in the base currency.
* `symbol` (string, required): Currency pair symbol (e.g., `USD-NGN`).
* `type` (string, required): Order type (`buy` or `sell`).
* `price` (integer, optional): Order price in minor units.
* `price_type` (string, optional): Price type (`limit` or `market`).
* `time_in_force` (string, optional): Time in force (`gtc`, `gtt`, `ioc`, `fok`).
**Sample Request**
```bash theme={null}
curl -X POST "https://exchange.spendjuice.com/v1/exchange/orders" \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"qty": 1.0,
"symbol": "USD-NGN",
"type": "buy"
}'
```
**Sample Response**
```json theme={null}
{
"data": {
"accepted_at": "2023-12-23T17:55:42.919523",
"average_fill_price": 80000,
"business_id": "dd625bec-b1a3-466e-867e-c91ae0b6e71e",
"correlation_id": "7da742ea-a1bc-11ee-b907-560f156a658b",
"created_at": "2023-12-23T17:55:42.911",
"expires_at": null,
"id": "7da75a46-a1bc-11ee-9a32-560f156a658b",
"min_qty": null,
"min_quote_qty": null,
"percent_filled": 10000,
"price": 80000,
"price_type": "market",
"qty": 1.0,
"quote_qty": null,
"status": "filled",
"symbol": "USD-NGN",
"time_in_force": "gtc",
"trades": [
{
"buy_order_id": "7da75a46-a1bc-11ee-9a32-560f156a658b",
"commission": 0,
"correlation_id": "7da742ea-a1bc-11ee-b907-560f156a658b",
"created_at": "2023-12-23T17:55:42.921",
"id": "7da8e726-a1bc-11ee-80cf-560f156a658b",
"price": 80000,
"sell_order_id": "7d97c0b8-a1bc-11ee-b240-560f156a658b",
"size": 1.0,
"symbol": "USD-NGN"
}
],
"type": "buy",
"updated_at": "2023-12-23T17:55:42.911",
"user_id": "b101f718-d133-450c-a572-c281c7341803"
}
}
```
# Get Order Book
Source: https://docs.juicyway.com/exchange/orders/get-order-book
Retrieve the order book for a specific currency pair.
```json theme={null}
GET /exchange/books/{symbol}
```
**Parameters:**
* `symbol` (string, required): The currency pair symbol (e.g., `USD-NGN`).
**Sample Request**
```bash theme={null}
curl -X GET "https://exchange.spendjuice.com/v1/exchange/books/USD-NGN" \
-H "Authorization: YOUR_API_KEY"
```
**Sample Response**
```json theme={null}
{
"data": {
"asks": [
{
"business_id": "ce8331b2-a396-46c1-9638-5db5e9cf5b2e",
"created_at": "2023-12-23T19:11:23.215",
"id": "0fe2d322-a1c7-11ee-9c0e-560f156a658b",
"percent_filled": 0,
"price": 80000,
"price_type": "limit",
"status": "open",
"time_in_force": "gtc",
"total_qty": "1",
"unfilled_qty": "1.0",
"user_id": null
}
],
"bids": [
{
"business_id": "ce8331b2-a396-46c1-9638-5db5e9cf5b2e",
"created_at": "2023-12-23T19:11:23.097",
"id": "0fd0baf2-a1c7-11ee-ae88-560f156a658b",
"percent_filled": 0,
"price": 75000,
"price_type": "limit",
"status": "open",
"time_in_force": "gtc",
"total_qty": "1",
"unfilled_qty": "1.0",
"user_id": "82dde615-d181-4f3e-8d3f-53ac7962feb7"
}
],
"max_bid": 75000,
"min_ask": 80000,
"symbol": "USD-NGN"
}
}
```
# List Orders
Source: https://docs.juicyway.com/exchange/orders/list-orders
Retrieve a list of orders.
```json theme={null}
GET /exchange/orders
```
**Parameters:**
* `before` (string, optional): Cursor for pagination (before).
* `after` (string, optional): Cursor for pagination (after).
* `limit` (integer, optional): Limit the number of orders returned.
* `type` (string, optional): Filter by order type (`buy` or `sell`).
* `status` (string, optional): Filter by order status (`open`, `cancelled`, `rejected`, `filled`, `expired`, `closed`).
* `price` (integer, optional): Filter by order price.
**Sample Request**
```bash theme={null}
curl -X GET "https://exchange.spendjuice.com/v1/exchange/orders?limit=10&type=buy" \
-H "Authorization: YOUR_API_KEY"
```
**Sample Response**
```json theme={null}
{
"data": [
{
"accepted_at": "2023-12-23T17:55:42.919523",
"average_fill_price": 80000,
"business_id": "dd625bec-b1a3-466e-867e-c91ae0b6e71e",
"correlation_id": "7da742ea-a1bc-11ee-b907-560f156a658b",
"created_at": "2023-12-23T17:55:42.911",
"expires_at": null,
"id": "7da75a46-a1bc-11ee-9a32-560f156a658b",
"min_qty": null,
"min_quote_qty": null,
"percent_filled": 10000,
"price": 80000,
"price_type": "market",
"qty": 1.0,
"quote_qty": null,
"status": "filled",
"symbol": "USD-NGN",
"time_in_force": "gtc",
"trades": [
{
"buy_order_id": "7da75a46-a1bc-11ee-9a32-560f156a658b",
"commission": 0,
"correlation_id": "7da742ea-a1bc-11ee-b907-560f156a658b",
"created_at": "2023-12-23T17:55:42.921",
"id": "7da8e726-a1bc-11ee-80cf-560f156a658b",
"price": 80000,
"sell_order_id": "7d97c0b8-a1bc-11ee-b240-560f156a658b",
"size": 1.0,
"symbol": "USD-NGN"
}
],
"type": "buy",
"updated_at": "2023-12-23T17:55:42.911",
"user_id": "b101f718-d133-450c-a572-c281c7341803"
}
],
"pagination": {
"after": "b101f718-d133-450c-a572-c281c7341803",
"before": null,
"limit": 10
}
}
```
# Convert
Source: https://docs.juicyway.com/exchange/rates/convert
Converts a specified amount from one currency to another.
Ensure the `amount` is provided in minor units, and the `from` and `to` fields are valid ISO currency codes. Handle cases where the input parameters are missing or invalid to return a `400 - Bad Request` response.
```
POST /exchange/convert
```
### Sample Request
```json theme={null}
{
"amount": 75000,
"from": "USD",
"to": "NGN"
}
```
### Responses
#### 200 - Conversion Result
Sample Response
```json theme={null}
{
"data": {
"converted_amount": 100
}
}
```
#### 400 - Bad Request
Indicates a problem with the request (e.g., missing or invalid parameters).
# Create Rates
Source: https://docs.juicyway.com/exchange/rates/create-rates
This endpoint creates a new exchange rate.
```json theme={null}
POST /exchange/rates
```
#### **Request**
* **Headers**:
`Content-Type: application/json`
* **Body** (required):
```json theme={null}
{
"buy": 100,
"pair": "USD-NGN",
"sell": 75000,
"ttl": 60
}
```
* buy (integer): Buy amount in base currency.
* pair (string): Currency pair (e.g., "USD-NGN").
* sell (integer): Sell amount in quote currency.
* ttl (integer): Time-to-live for the rate, in seconds.
#### **Sample Response**
1. **201 Created**
* **Media Type**: `application/json`
```json theme={null}
{
"data": {
"buy": 1200,
"created_at": "2025-01-21T11:56:45Z",
"entity": {
"id": "397752fb-92e6-404a-b6e4-d9d72f1379f9",
"type": "business"
},
"id": "83b16397-d524-4619-b30f-e5e77b1b8d17",
"pair": "USD-NGN",
"sell": 1100,
"ttl": 60,
"updated_at": "2025-01-21T11:56:46Z"
}
}
```
1. **422 Unprocessable Entity**
* **Media Type**: `application/json`
* Indicates validation errors or invalid request parameters.
# Delete Rates
Source: https://docs.juicyway.com/exchange/rates/delete-rates
This endpoint deletes a specified exchange rate by its ID.
```json theme={null}
DELETE /exchange/rates/{id}
```
#### **Request**
* **Headers**:
`Authorization: YOUR_API_KEY`
* **Path Parameter**:
* **`id`** *(string, required)*: The unique identifier of the rate to delete.
**Example**: `3f27a046-314d-457f-b39b-1ec30561353d`
#### **Responses**
1. **204 No Content**
* Indicates that the rate was successfully deleted.
* No response body.
2. **404 Not Found**
* **Media Type**: `application/json`
* Returned if the specified `id` does not exist or is invalid.
# Fetch Rate
Source: https://docs.juicyway.com/exchange/rates/fetch-rate
Retrieves details of a specific exchange rate by its ID.
```json theme={null}
GET /exchange/quote/{id}}
```
#### **Request**\\
**Headers**: `Authorization: YOUR_API_KEY`\
\
**Path Parameter**:
* **`id`** *(string, required)*: The unique identifier of the rate to retrieve. **Example**: `3f27a046-314d-457f-b39b-1ec30561353d`
#### **Responses**
1. **200 OK**
* **Media Type**: `application/json`
```json theme={null}
{
"data": {
"id": "2f939fe5-fb7b-4234-8b73-761a848d13af",
"locked": true,
"rate": 1500,
"symbol": "USD-NGN",
"time_to_convert": 10,
"time_to_lock": 30,
"type": "buy"
}
}
```
2. **404 Not Found**
* **Media Type**: `application/json`
* Returned if the specified `id` does not exist or is invalid.
\
**Path Parameter**:
* `id` *(string, required)*: The unique identifier of the rate to retrieve. **Example**: `3f27a046-314d-457f-b39b-1ec30561353d`
* `.time_to_convert`
* **Description**: The Time-To-Live (TTL) of the rate in seconds.
* `time_to_lock`
* **Description**: The duration (in seconds) before the rate becomes available for locking while it is being unlocked.
* `locked`
* **Description**:
* A locked quote is available for use in a swap within the `time_to_convert` interval.
* An unlocked rate will become unavailable after the `time_to_lock` interval.
* By default, the quote is locked for authenticated requests.
* To prevent locking, add `lock=false` to the quote endpoint parameters.
* `type`
* **Description**: Specifies the conversion side from the provider's perspective. Possible values are `buy` or `sell`.
## Locking a quote
# Exchange Rates
Source: https://docs.juicyway.com/exchange/rates/list-rates
The endpoint provides a list of currency rates
### Request Details
* **Parameters**: None
* **Accept Header**: `application/json`
```json theme={null}
GET /exchange/rates
```
### Description of Key Fields
* **accepted\_at**: Timestamp when the rate was accepted.
* **correlation\_id**: Unique identifier for correlating requests.
* **entity**: Contains the entity's `id` and `type` (e.g., "business").
* **price**: Exchange rate in minor units.
* **symbol**: The currency pair (e.g., "USD-NGN").
* **status**: Status of the rate (e.g., "filled").
* **trades**: Details of the trades executed for the rate, including `price`, `size`, and associated order IDs.
### Sample Response
* **Status Code**: `200`
* **Description**: Returns a list of rates with detailed information about each rate and related trades.
```json theme={null}
{
"data": [
{
"buy": 1200,
"created_at": "2025-01-21T11:56:45Z",
"entity": {
"id": "397752fb-92e6-404a-b6e4-d9d72f1379f9",
"type": "business"
},
"id": "83b16397-d524-4619-b30f-e5e77b1b8d17",
"pair": "USD-NGN",
"sell": 1100,
"ttl": 60,
"updated_at": "2025-01-21T11:56:46Z"
}
]
}
```
# Supported Rates.
Source: https://docs.juicyway.com/exchange/rates/list-supported-pairs
Retrieves a list of supported currency pairs for exchange.
To retrieve the list of supported currency pairs, send a `GET` request to the `/exchange/pairs` endpoint with the `Accept` header set to `application/json`. A successful response (HTTP status code 200) will return the above JSON structure.
```json theme={null}
GET /exchange/pairs
```
**Sample Response**
```json theme={null}
{
"data": [
"USD-NGN"
]
}
```
# Update an existing Rate
Source: https://docs.juicyway.com/exchange/rates/update-rates
Updates an existing exchange rate by its ID.
```json theme={null}
PATCH /exchange/rates/{id}
```
#### **Request**
* **Headers**:
`Authorization: YOUR_API_KEY`
* **Path Parameter**:
* **`id`** *(string, required)*: The unique identifier of the rate to update.
**Example**: `3f27a046-314d-457f-b39b-1ec30561353d`
* **Body** (required):
* **Media Type**: `application/json`
```json theme={null}
{
"buy": 100,
"sell": 75000,
"ttl": 60
}
```
**Fields:**
* buy (integer): Updated buy amount in base currency.
* sell (integer): Updated sell amount in quote currency.
* ttl (integer): Updated time-to-live for the rate, in seconds.
#### **Responses**
1. **201 Created**
* **Media Type**: `application/json`
* **Sample Response:**
```json theme={null}
{
"data": {
"accepted_at": "2023-12-23T17:55:42.919523",
"correlation_id": "7da742ea-a1bc-11ee-b907-560f156a658b",
"created_at": "2023-12-23T17:55:42.911",
"entity": {
"id": "6ebe0a0f-bb8f-49be-80ea-c6b72c348fea",
"type": "business"
},
"expires_at": null,
"id": "7da75a46-a1bc-11ee-9a32-560f156a658b",
"min_qty": null,
"min_quote_qty": null,
"percent_filled": 10000,
"price": 80000,
"price_type": "market",
"qty": 1,
"quote_qty": null,
"status": "filled",
"symbol": "USD-NGN",
"time_in_force": "gtc",
"trades": [
{
"buy_order_id": "7da75a46-a1bc-11ee-9a32-560f156a658b",
"commission": 0,
"correlation_id": "7da742ea-a1bc-11ee-b907-560f156a658b",
"created_at": "2023-12-23T17:55:42.921",
"id": "7da8e726-a1bc-11ee-80cf-560f156a658b",
"price": 80000,
"sell_order_id": "7d97c0b8-a1bc-11ee-b240-560f156a658b",
"size": 1,
"symbol": "USD-NGN"
}
],
"type": "buy",
"updated_at": "2023-12-23T17:55:42.911"
}
}
```
1. **404 Not Found**
* **Media Type**: `application/json`
* Returned if the specified `id` does not exist.
1. **422 Unprocessable Entity**
* **Media Type**: `application/json`
* Returned if the request body contains invalid or missing parameters.
# Create Standing Orders
Source: https://docs.juicyway.com/exchange/standing-orders/create-standing-order
Create a new standing order.
Endpoint
```json theme={null}
POST /exchange/standing-orders
```
#### **Request Body:**
```json theme={null}
{
"qty": 1,
"symbol": "USD-NGN",
"type": "buy"
}
```
#### **Responses:**
* **`201`** - Standing Order Created
**Sample:**
```json theme={null}
{
"data": {
"archived": false,
"created_at": "2023-12-23T17:55:42.911",
"entity": {
"id": "6ebe0a0f-bb8f-49be-80ea-c6b72c348fea",
"type": "business"
},
"id": "7da75a46-a1bc-11ee-9a32-560f156a658b",
"low_watermark_qty": 1,
"min_qty": null,
"qty": 3,
"strict": false,
"symbol": "USD-NGN",
"type": "buy",
"updated_at": "2023-12-23T17:55:42.911"
}
}
```
* 422 - Unprocessable Entity
# Delete Standing Order
Source: https://docs.juicyway.com/exchange/standing-orders/delete-standing-order
Delete a standing order by its ID.
**Endpoint**
```json theme={null}
DELETE /exchange/standing-orders/{id}
```
#### **Path Parameters:**
* **`id`** (string, required): Standing Order ID.
#### **Query Parameters:**
* **`token`** (string, optional): Token for additional validation.
#### **Responses:**
* **`204`** - No Content
* **`404`** - Not Found
# Retrieve Standing Order
Source: https://docs.juicyway.com/exchange/standing-orders/get-standing-order
Retrieve details of a specific standing order by its ID.
Endpoint
```json theme={null}
GET /exchange/standing-orders/{id}
```
#### **Path Parameters:**
* **`id`** (string, required): Standing Order ID.
#### **Responses:**
* **`200`** - Standing Order Retrieved
**Sample:**
```json theme={null}
{
"data": {
"archived": false,
"created_at": "2023-12-23T17:55:42.911",
"entity": {
"id": "6ebe0a0f-bb8f-49be-80ea-c6b72c348fea",
"type": "business"
},
"id": "7da75a46-a1bc-11ee-9a32-560f156a658b",
"low_watermark_qty": 1,
"min_qty": null,
"qty": 3,
"strict": false,
"symbol": "USD-NGN",
"type": "buy",
"updated_at": "2023-12-23T17:55:42.911"
}
}
```
* 404 - Not Found
# List Standing Orders
Source: https://docs.juicyway.com/exchange/standing-orders/list-standing-orders
Retrieve a list of standing orders with pagination support.
Endpoint
```json theme={null}
GET /exchange/standing-orders
```
# Update Standing Order
Source: https://docs.juicyway.com/exchange/standing-orders/update-standing-order
Update an existing standing order.
Endpoint
```json theme={null}
PUT /exchange/standing-orders/{id}
```
#### **Path Parameters:**
* **`id`** (string, required): Standing Order ID.
#### **Request Body:**
**Content Type:** `application/json`
**Sample:**
```json theme={null}
{
"archived": false,
"qty": 1,
"strict": true
}
```
#### **Responses:**
* **`201`** - Standing Order Updated**Sample:**
```json theme={null}
{
"data": {
"archived": false,
"created_at": "2023-12-23T17:55:42.911",
"entity": {
"id": "6ebe0a0f-bb8f-49be-80ea-c6b72c348fea",
"type": "business"
},
"id": "7da75a46-a1bc-11ee-9a32-560f156a658b",
"low_watermark_qty": 1,
"min_qty": null,
"qty": 3,
"strict": false,
"symbol": "USD-NGN",
"type": "buy",
"updated_at": "2023-12-23T17:55:42.911"
}
}
```
* 422 - Unprocessable Entity
# Create a Swap Configuration
Source: https://docs.juicyway.com/exchange/swap-configurations/create-swap-configuration
Create a Swap Configuration
Endpoint
```json theme={null}
POST /exchange/swap-configurations
```
#### **Request Body:**
**Content Type:** `application/json`
**Sample Request Body:**
```json theme={null}
{
"symbol": "USD-NGN",
"ttl": 10,
"type": "buy"
}
```
#### **Responses:**
* **`201`** - Swap Configuration Created
**Sample:**
```json theme={null}
{
"data": {
"id": "string",
"order_type": "sell",
"symbol": "string",
"ttl": 0
}
}
```
* 422 - Unprocessable Entity
# Delete a Swap Configuration
Source: https://docs.juicyway.com/exchange/swap-configurations/delete-swap-configuration
Delete a swap configuration by its ID.
Endpoint
```json theme={null}
DELETE /exchange/swap-configurations/{id}
```
#### **Path Parameters:**
* **`id`** (string, required): Swap Configuration ID.
#### **Query Parameters:**
* **`token`** (string, optional): Token for additional validation.
#### **Responses:**
* **`204`** - No Content
* **`404`** - Not Found
# Retrieve Swap Configuration
Source: https://docs.juicyway.com/exchange/swap-configurations/get-swap-configuration
Retrieve details of a specific swap configuration by its ID.
**Endpoint**
```json theme={null}
GET /exchange/swap-configurations/{id}
```
#### **Path Parameters:**
* **`id`** (string, required): Swap Configuration ID.
#### **Responses:**
* **`200`** - Swap Configuration Retrieved
**Sample:**
```json theme={null}
{
"data": {
"id": "string",
"order_type": "sell",
"symbol": "string",
"ttl": 0
}
}
```
* 404 - Not Found
# List Swap Configuration
Source: https://docs.juicyway.com/exchange/swap-configurations/list-swap-configurations
Retrieve a list of swap configurations with pagination support.
Endpoint
```json theme={null}
GET /exchange/swap-configurations
```
#### **Query Parameters:**
* **`before`** (string, optional): Cursor for pagination (before).
* **`after`** (string, optional): Cursor for pagination (after).
* **`limit`** (integer, optional): Number of records to return.
* **`symbol`** (string, optional): Filter by symbol.
#### **Responses:**
* **`200`** - Swap List**Sample:**
```json theme={null}
{
"data": [
{
"correlation_id": "7da742ea-a1bc-11ee-b907-560f156a658b",
"created_at": "2021-01-01T00:00:00Z",
"customer": {
"email": "customer@email.com",
"id": "1",
"name": "User 1",
"type": "user"
},
"id": "7da8e726-a1bc-11ee-80cf-560f156a658b",
"provider": {
"email": "provider@email.com",
"id": "1",
"name": "Provider 1",
"type": "provider"
},
"source_amount": {
"amount": 1,
"currency": "USD"
},
"status": "success",
"symbol": "USD-NGN",
"target_amount": {
"amount": 1000,
"currency": "NGN"
},
"updated_at": "2021-01-01T00:00:00Z"
}
],
"pagination": {
"after": "b101f718-d133-450c-a572-c281c7341803",
"before": null,
"limit": 15
}
}
```
# Update Swap Configuration
Source: https://docs.juicyway.com/exchange/swap-configurations/update-swap-configuration
Update an existing swap configuration.
Endpoint
```json theme={null}
PUT /exchange/swap-configurations/{id}
```
#### **Path Parameters:**
* **`id`** (string, required): Swap Configuration ID.
#### **Request Body:**
**Content Type:** `application/json`
**Sample:**
```json theme={null}
{
"symbol": "USD-NGN",
"ttl": 10,
"type": "buy"
}
```
**Responses**
**`201`** - Swap Configuration Updated
**Sample**
```json theme={null}
{
"data": {
"id": "string",
"order_type": "sell",
"symbol": "string",
"ttl": 0
}
}
```
**`422`** - Unprocessable Entity
# Get Swap
Source: https://docs.juicyway.com/exchange/swaps/get-swap
Retrieve details of a specific swap by ID.
```json theme={null}
GET /exchange/swap/{id}
```
**Parameters:**
* `id` (string, required): The unique ID of the swap.
**Sample Request**
```bash theme={null}
curl -X GET "https://exchange.spendjuice.com/v1/exchange/swap/7da8e726-a1bc-11ee-80cf-560f156a658b" \
-H "Authorization: YOUR_API_KEY"
```
**Sample Response**
```json theme={null}
{
"data": {
"correlation_id": "7da742ea-a1bc-11ee-b907-560f156a658b",
"created_at": "2021-01-01T00:00:00Z",
"customer": {
"email": "customer@email.com",
"id": "1",
"name": "User 1",
"type": "user"
},
"id": "7da8e726-a1bc-11ee-80cf-560f156a658b",
"provider": {
"email": "provider@email.com",
"id": "1",
"name": "Provider 1",
"type": "provider"
},
"source_amount": {
"amount": 1.0,
"currency": "USD"
},
"status": "success",
"symbol": "USD-NGN",
"target_amount": {
"amount": 1000.0,
"currency": "NGN"
},
"updated_at": "2021-01-01T00:00:00Z"
}
}
```
# Get Swap Rate
Source: https://docs.juicyway.com/exchange/swaps/get-swap-rate
Retrieve the current swap rate for a currency pair.
```json theme={null}
GET /exchange/quote/{id}}
```
**Parameters:**
* `source_currency` (string, required): Source currency (e.g., `USD`).
* `target_currency` (string, required): Target currency (e.g., `NGN`).
**Sample Request**
```bash theme={null}
curl --location 'https://api.spendjuice.com/exchange/quote?source_currency=NGN&target_currency=USD' \
--header 'Authorization: '
```
**Sample Response**
```json theme={null}
{
"data": {
"id": "2f939fe5-fb7b-4234-8b73-761a848d13af",
"locked": true,
"rate": 1500,
"symbol": "USD-NGN",
"time_to_convert": 10,
"time_to_lock": 30,
"type": "buy"
}
}
```
**Path Parameter**:
* `id` *(string, required)*: The unique identifier of the rate to retrieve. **Example**: `3f27a046-314d-457f-b39b-1ec30561353d`
* `.time_to_convert`
* **Description**: The Time-To-Live (TTL) of the rate in seconds.
* `time_to_lock`
* **Description**: The duration (in seconds) before the rate becomes available for locking while it is being unlocked.
* `locked`
* **Description**:
* A locked quote is available for use in a swap within the `time_to_convert` interval.
* An unlocked rate will become unavailable after the `time_to_lock` interval.
* By default, the quote is locked for authenticated requests.
* To prevent locking, add `lock=false` to the quote endpoint parameters.
* `type`
* **Description**: Specifies the conversion side from the provider's perspective. Possible values are `buy` or `sell`.
## Locking a Rate
Once you have fetched a quote, you can use the request below to lock it in.
```
curl --location --request POST 'https://api.spendjuice.com/exchange/quote//lock' \
--header 'Authorization: '
```
# List Swaps
Source: https://docs.juicyway.com/exchange/swaps/list-swaps
Retrieve a list of swaps.
```json theme={null}
GET /exchange/swap
```
**Parameters:**
* `before` (string, optional): Cursor for pagination (before).
* `after` (string, optional): Cursor for pagination (after).
* `limit` (integer, optional): Limit the number of swaps returned.
* `symbol` (string, optional): Filter by currency pair symbol.
**Sample Request**
```bash theme={null}
curl -X GET "https://exchange.spendjuice.com/v1/exchange/swap?limit=10&symbol=USD-NGN" \
-H "Authorization: YOUR_API_KEY"
```
Sample Response
```json theme={null}
{
"data": [
{
"correlation_id": "7da742ea-a1bc-11ee-b907-560f156a658b",
"created_at": "2021-01-01T00:00:00Z",
"customer": {
"email": "customer@email.com",
"id": "1",
"name": "User 1",
"type": "user"
},
"id": "7da8e726-a1bc-11ee-80cf-560f156a658b",
"provider": {
"email": "provider@email.com",
"id": "1",
"name": "Provider 1",
"type": "provider"
},
"source_amount": {
"amount": 1.0,
"currency": "USD"
},
"status": "success",
"symbol": "USD-NGN",
"target_amount": {
"amount": 1000.0,
"currency": "NGN"
},
"updated_at": "2021-01-01T00:00:00Z"
}
],
"pagination": {
"after": "b101f718-d133-450c-a572-c281c7341803",
"before": null,
"limit": 10
}
}
```
# Make Swap
Source: https://docs.juicyway.com/exchange/swaps/make-swaps
Execute a swap between two currencies.
```json theme={null}
POST /exchange/swap
```
**Parameters:**
* `amount` (integer, required): Amount in minor units.
* `source_currency` (string, required): Source currency (e.g., `USD`).
* `target_currency` (string, required): Target currency (e.g., `NGN`).
**Sample Request**
````bash theme={null}
curl --location 'https://api.spendjuice.com/exchange/swap' \
--header 'Authorization: '
--data '{
"amount": 1000,
"source_currency": "NGN",
"target_currency": "USD",
"quote_id": "4bed6a6a-2431-4a51-9600-d0badd939bf7"
}'
```
````
**Sample Response**
```json theme={null}
{
"data": {
"correlation_id": "7da742ea-a1bc-11ee-b907-560f156a658b",
"created_at": "2021-01-01T00:00:00Z",
"customer": {
"email": "customer@email.com",
"id": "1",
"name": "User 1",
"type": "user"
},
"id": "7da8e726-a1bc-11ee-80cf-560f156a658b",
"provider": {
"email": "provider@email.com",
"id": "1",
"name": "Provider 1",
"type": "provider"
},
"source_amount": {
"amount": 1.0,
"currency": "USD"
},
"status": "success",
"symbol": "USD-NGN",
"target_amount": {
"amount": 1000.0,
"currency": "NGN"
},
"updated_at": "2021-01-01T00:00:00Z"
}
}
```
# Home
Source: https://docs.juicyway.com/home
Welcome to the Juicyway Developer Documentation. Here, you'll learn how to create incredible payment experiences securely using our API.
Juicyway provides a REST API that allows you to seamlessly accept payments from your customers via multiple payment methods such as Debit cards, Bank transfers, Crypto transfers and Interac e-transfers. The API delivers responses in a secure JSON format.
## Getting Started
Get up and running with Juice API in minutes. Learn how to make your first API call and process test payments in our sandbox environment.
Secure your API requests with proper authentication. Learn about API keys and best practices for securing your integration.
Set up real-time notifications for payment events. Receive updates about transactions and system events automatically.
Learn about error codes, messages, and best practices for handling errors in your integration.
## Development Environments
We provide two distinct environments to cater to your development and deployment needs:
```bash Sandbox theme={null}
https://api-sandbox.spendjuice.com
```
```bash Production theme={null}
https://api.spendjuice.com
```
* **Sandbox Environment:** This environment is specifically designed for testing your integration with Juice. It facilitates a risk-free environment where you can experiment without processing real payments .
* **Production Environment:** Once you've thoroughly tested your integration within the Sandbox environment, you can transition to the Production environment for processing live transactions.
Always test your integration thoroughly in the sandbox environment before moving to production.
## Core Features
[**Collect payments**](https://docs.juicyway.com/payments/overview) through multiple channels:
* Credit/Debit Cards
* Bank Transfers
* Crypto Transfers
Access powerful currency exchange features to facilitate multi-currency transactions.
Seamlessly move funds between accounts using our secure APIs
Manage transactions, view analytics, and handle customer support through our intuitive dashboard.
## Next Steps
After reviewing this documentation, you can:
1. Follow our [Quick Start Guide](/quickstart) to begin integration
2. Set up [Authentication](/authentication) for secure API access
3. Configure [Webhooks](/webhooks) for real-time updates
4. Review common [Errors](/errors) and how to handle them
5. Test transactions in the sandbox environment
6. Go live with your integration
Need help? Contact our support team at [support@juicyway.com](mailto:support@juicyway.com)
# Fetch Payment
Source: https://docs.juicyway.com/payment-transactions/fetch-payment
Retrieve details of a specific payment by ID
## Overview
The Fetch Payment endpoint allows you to retrieve detailed information about a specific payment using its unique identifier. This is useful for checking payment status, verifying transaction details, or retrieving customer information associated with the payment.
## Endpoint
```bash theme={null}
GET /payments/{id}
```
## Authentication
All requests must include your API key in the Authorization header:
```bash theme={null}
Authorization: YOUR_API_KEY
```
## Path Parameters
The unique identifier of the payment to retrieve.
* Format: UUID v4
* Example: `2315fca8-9aec-42ee-8bee-a9d10add170e`
## Response Structure
The payment details object
Unique identifier for the payment
Payment amount in minor units (e.g., cents, kobo)
Three-letter currency code (e.g., NGN, USD)
Current status of the payment. One of:
* pending
* processing
* succeeded
* failed
* cancelled
Details about the customer who made the payment
Information about the payment method used
## Examples
```bash cURL theme={null}
curl -X GET "https://api.spendjuice.com/payments/2315fca8-9aec-42ee-8bee-a9d10add170e" \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json"
```
```javascript Node.js theme={null}
const response = await fetch(
'https://api.spendjuice.com/payments/2315fca8-9aec-42ee-8bee-a9d10add170e',
{
headers: {
'Authorization': ' YOUR_API_KEY',
'Content-Type': 'application/json'
}
}
);
const payment = await response.json();
```
```python Python theme={null}
import requests
headers = {
'Authorization': ' YOUR_API_KEY',
'Content-Type': 'application/json'
}
response = requests.get(
'https://api.spendjuice.com/payments/2315fca8-9aec-42ee-8bee-a9d10add170e',
headers=headers
)
payment = response.json()
```
## Response Examples
```json 200 - Successful Response theme={null}
{
"data": {
"amount": 10000,
"cancellation_reason": null,
"correlation_id": "a3f53cea-e05a-11ee-8a6d-8a7019bc5d83",
"currency": "NGN",
"customer": {
"billing_address": {
"city": "Torphy",
"country": "NG",
"line1": "46259 Brekke Adella Rapids",
"line2": "Suite 304",
"state": "River",
"zip_code": "53292"
},
"email": "greg_gleichner@hansen.net",
"first_name": "Murray Inc",
"id": "53380ca0-b29d-4dd4-8732-8fd518f4a394",
"last_name": "",
"phone_number": "+2348023321025"
},
"date": "2024-03-12T10:23:59.750724Z",
"description": "Test",
"id": "a3f53772-e05a-11ee-9444-8a7019bc5d83",
"order": {
"identifier": "Veniam quaerat dolor?",
"items": [
{
"name": "Small Rubber Shoes",
"type": "digital"
}
]
}
"mode": "test",
"payment_method": {
"account_name": "Carrie Romaguera Sr.",
"account_number": "34521736",
"account_type": "savings",
"bank_name": "Conn Group",
"id": "1e140102-3ddc-41d1-aaaf-b101cd195377",
"type": "bank_account"
},
"reference": "Possimus rerum.",
"status": "pending"
}
}
```
```json 404 - Payment Not Found theme={null}
{
"error": {
"code": "payment_not_found",
"message": "No payment found with ID: 2315fca8-9aec-42ee-8bee-a9d10add170e"
}
}
```
```json 401 - Unauthorized theme={null}
{
"error": {
"code": "unauthorized",
"message": "Invalid or missing API key"
}
}
```
## Error Handling
| Status Code | Description | Possible Solution |
| ----------- | -------------------------- | ------------------------------------------- |
| 401 | Invalid or missing API key | Check your API key and authorization header |
| 403 | Permission denied | Verify your API key has correct permissions |
| 404 | Payment not found | Verify the payment ID exists and is valid |
| 429 | Rate limit exceeded | Implement exponential backoff |
| 500 | Internal server error | Contact support |
## Best Practices
1. Implement proper error handling for all status codes
2. Use exponential backoff for retries
3. Log errors with payment IDs for debugging
4. Handle network timeouts appropriately
1. Never log complete payment details
2. Keep API keys secure
3. Use HTTPS for all API calls
4. Validate payment IDs before making requests
1. Cache payment details when appropriate
2. Implement request timeouts
3. Monitor API response times
4. Use connection pooling for multiple requests
## Rate Limits
This endpoint is subject to rate limiting:
* 100 requests per minute per API key
* Rate limit info included in response headers:
* X-RateLimit-Limit
* X-RateLimit-Remaining
* X-RateLimit-Reset
For additional assistance:
* Review our [Error Handling Guide](/errors)
* Contact [support@juicyway.com](mailto:support@juicyway.com)
# List Payments
Source: https://docs.juicyway.com/payment-transactions/list-payments
Retrieve a paginated list of payment transactions with filtering and sorting options.
## Overview
This endpoint retrieves a list of payment transactions with support for pagination, filtering, and sorting. Results are ordered by creation date in descending order by default.
```bash theme={null}
GET /payments
```
## Query Parameters
Filter by payment status.
* Available values: `pending`, `captured`, `settled`, `failed`
* Example: `status=settled`
Cursor for fetching records before a specific position.
* Use for backward pagination
* Example: `before=pay_123xyz`
Cursor for fetching records after a specific position.
* Use for forward pagination
* Example: `after=pay_456abc`
Number of records to return per page (max: 100).
* Example: `limit=25`
Filter payments created after this timestamp (ISO 8601).
* Example: `created_after=2024-01-01T00:00:00Z`
Filter payments created before this timestamp (ISO 8601).
* Example: `created_before=2024-03-31T23:59:59Z`
## Response Format
Array of payment objects. Each payment object contains:
Unique payment identifier
Payment amount in minor units
Three-letter currency code
Payment status (`pending`, `captured`, `settled`, `failed`)
Customer details including name, email, and billing address
Payment method details and type
Payment creation timestamp
Additional payment order
Cursor for the previous page
Cursor for the next page
Number of records per page
## Examples
### Basic List Request
```bash cURL theme={null}
curl -X GET "https://api.spendjuice.com/payments?limit=2" \
-H "Authorization: YOUR_API_KEY"
```
```javascript Node.js theme={null}
const response = await fetch('https://api.spendjuice.com/payments?limit=2', {
headers: {
'Authorization': ' YOUR_API_KEY'
}
});
```
```python Python theme={null}
import requests
response = requests.get(
'https://api.spendjuice.com/payments',
params={'limit': 2},
headers={'Authorization': ' YOUR_API_KEY'}
)
```
### Response Examples
```json 200 Success theme={null}
{
"data": [
{
"auth_type": "3ds",
"expires_at": "2024-03-01T08:43:08.110470Z",
"links": {},
"message": "Successful",
"payment": {
"amount": 50000,
"cancellation_reason": null,
"correlation_id": "2549dcf4-d743-11ee-9d95-c6d49632367b",
"currency": "NGN",
"customer": {
"billing_address": {
"city": "Awolowo Road",
"country": "NG",
"line1": "Opposite Sasa Estate",
"line2": null,
"state": "Kwara",
"zip_code": "23401"
},
"email": "asajuenitan@gmail.com",
"first_name": "Enitan",
"id": "d05e51df-809e-498a-ac3f-7acfc0b5d35d",
"last_name": "Michael",
"phone_number": "+2348036120313"
},
"date": "2024-02-29T20:43:08.344264Z",
"description": "Deposit",
"id": "2549c96c-d743-11ee-aa4d-c6d49632367b",
"order": {
"identifier": "dbf99bd0-262a-46bd-8339-3c741d040dbb",
"items": [
{
"name": "Deposit",
"type": "digital"
}
]
}
"mode": "live",
"payment_method": {
"card_number": "417396******9621",
"expiry_month": 6,
"expiry_year": 2024,
"id": "5e21efda-c526-4057-92f6-1b94ee210b47",
"type": "card"
},
"reference": "85d53ab5-92b8-4151-9f8f-a4f12863a911",
"status": "settled"
},
"status": "settled"
}
],
"pagination": {
"after": "2549c96c-d743-11ee-aa4d-c6d49632367b",
"before": null,
"limit": 2
}
}
```
```json 400 Bad Request theme={null}
{
"error": {
"code": "invalid_request",
"message": "Invalid query parameters",
"details": {
"limit": ["Must be between 1 and 100"]
}
}
}
```
## Pagination
The API uses cursor-based pagination to handle large collections of payments:
1. Initial request: Specify `limit` (default: 15)
2. Subsequent requests: Use the `after` cursor from the previous response
3. Previous page: Use the `before` cursor if available
For optimal performance:
* Use reasonable page sizes (15-50 records)
* Cache results when possible
* Implement progressive loading in your UI
## Filtering Tips
```bash theme={null}
# Get all settled payments
GET /payments?status=settled
# Get failed payments from last 24 hours
GET /payments?status=failed&created_after=2024-03-14T00:00:00Z
```
```bash theme={null}
# Get payments for March 2024
GET /payments?created_after=2024-03-01T00:00:00Z&created_before=2024-03-31T23:59:59Z
```
## Rate Limits
This endpoint has the following rate limits:
* 1000 requests per hour per API key
* Maximum of 100 records per request
* Burst limit: 100 requests per minute
## Best Practices
1. **Efficient Filtering**
* Use filters to reduce response size
* Combine filters for precise results
* Cache frequently accessed data
2. **Pagination Handling**
* Store cursors temporarily for navigation
* Implement infinite scroll for large lists
* Show loading states during fetches
3. **Error Handling**
* Implement proper retry logic
* Handle rate limits gracefully
* Log pagination errors
For additional assistance:
* Review our [Error Handling Guide](/errors)
* Contact [support@juicyway.com](mailto:support@juicyway.com)
# Payment Statistics
Source: https://docs.juicyway.com/payment-transactions/payment-statistics
Retrieve aggregate statistics about your payment transactions
## Overview
The Payment Statistics API provides aggregated metrics about your payment transactions across different statuses. This helps you monitor payment flows and track success/failure rates.
```http theme={null}
GET /payments/stats
```
## Authentication
All requests must include your API key in the Authorization header:
```bash theme={null}
Authorization: YOUR_API_KEY
```
## Response Fields
Payment statistics container object.
Number of payments successfully captured but not yet settled
Number of failed payment attempts
Number of payments currently in progress
Number of payments fully completed and settled
Total number of payment attempts across all statuses
## Examples
### Basic Statistics Request
```bash cURL theme={null}
curl -X GET "https://api.spendjuice.com/payments/stats" \
-H "Authorization: YOUR_API_KEY"
```
```python Python theme={null}
import requests
response = requests.get(
'https://api.spendjuice.com/payments/stats',
headers={'Authorization': ' YOUR_API_KEY'}
)
```
```javascript Node.js theme={null}
const response = await fetch('https://api.spendjuice.com/payments/stats', {
headers: {
'Authorization': ' YOUR_API_KEY'
}
});
```
### Success Response
```json 200 Success theme={null}
{
"data": {
"captured": 2,
"failed": 5,
"pending": 2,
"settled": 8,
"total": 20
}
}
```
```json Empty Stats theme={null}
{
"data": {
"captured": 0,
"failed": 0,
"pending": 0,
"settled": 0,
"total": 0
}
}
```
## Data Aggregation
The statistics endpoint aggregates payment data with the following characteristics:
* Updates in near real-time as payment statuses change
* Includes payments from the last 30 days by default
* Counts each payment exactly once based on its current status
* Excludes test mode payments from production statistics
## Usage Examples
### Monitor Payment Success Rate
```javascript theme={null}
const stats = await getPaymentStats();
const successRate = (stats.data.settled / stats.data.total) * 100;
console.log(`Payment Success Rate: ${successRate}%`);
```
### Track Failed Payments
```javascript theme={null}
const stats = await getPaymentStats();
if (stats.data.failed > 0) {
notifyTeam(`${stats.data.failed} failed payments require attention`);
}
```
## Best Practices
1. **Caching**
* Cache statistics for up to 5 minutes to reduce API load
* Implement stale-while-revalidate caching strategy
* Clear cache when receiving payment webhooks
2. **Error Handling**
* Implement exponential backoff for retries
* Handle network timeouts gracefully
* Log unusual statistical patterns
3. **Monitoring**
* Track success rate trends over time
* Set up alerts for unusual failure rates
* Monitor pending payment resolution times
For questions about payment statistics:
* Review our [Error Handling](/errors) guide
* Contact [support@juicyway.com](mailto:support@juicyway.com)
* Join our [Discord community](https://discord.gg/juice)
# Authorize Payment
Source: https://docs.juicyway.com/payments/authorize-payment
Learn about payment authorization in the Juice API
## Overview
Payment authorization is a critical step in the transaction flow where a customer's payment credentials are validated and checked before capturing the payment. The authorization process helps ensure:
1. The payment method is valid and active
2. Sufficient funds are available
3. The transaction is not suspicious or fraudulent
### Authorization Types
Depending on the payment method and risk level, one or more authorization steps may be required:
* Card number validation
* CVV/CVC check
* Address verification (AVS)
* 3D Secure authentication
* Account ownership verification
* Balance check
* Account status validation
* One-time passwords
* PIN validation
* Security questions
Authorization requirements vary by:
* Payment method
* Transaction amount
* Geographic region
* Customer risk profile
Refer to the specific [payment method guides](/payments/overview) for detailed authorization steps and requirements.
# Cards
Source: https://docs.juicyway.com/payments/authorize-payment/cards
Auth flow for card transactions.
## Authorization
During the payment capture process, additional authentication steps may be required due to the specific card involved. These may include OTP validation, PIN validation, or even 3DS (3D Secure).
```http theme={null}
POST /payment-sessions/{payment_id}/authorize
```
```json theme={null}
// otp authorize
{
"otp": "123456" //5 or 6 digit string
}
// pin authorize
{
"pin": "1234" //4 digit string
}
// card_enroll & 3ds
{
"card_enroll": "" //string
}
// Cvv
{
"cvv": "123" //string
}
```
**Sample Response**
```json theme={null}
{
"data": {
"url": "",
"status": "captured|failed",
"message": "",
"payment": {
"id": ,
"currency": ,
"amount": ,
"description": ,
"payment_method": {
"card_number": "",
"expiry_month": ,
"expiry_year": ,
"id": "",
"type": "card"
},
"status": "pending",
"date": ,
"mode": ,
"customer": {
"first_name": ,
"last_name": ,
"email": ,
"billing_address": {
"line1": ,
"line2": ,
"city": ,
"state": ,
"zip_code": ,
"country": ,
}
},
"reference": ,
"metadata": {}
}
}
}
```
# Payment Capture
Source: https://docs.juicyway.com/payments/capture-payment
Payment capture is the binding stage in the transaction lifecycle where funds are transferred from the customer's account to your merchant account. This process occurs after successful authorization and represents the final step in completing a payment.
## Overview
Before attempting to capture a payment:
* Ensure you have a valid payment session ID
* Verify any required authorizations are complete
* Check that the payment hasn't expired
## Supported Payment Methods
**Features**
* Direct capture after authorization
* 3DS/OTP support where required
* Partial captures supported
* Real-time status updates
**Features**
* Virtual account generation
* Multiple bank support
* Automated reconciliation
* Real-time notifications
**Features**
* Multi-chain support (ETH, TRX)
* USDT/USDC acceptance
* Automated rate conversion
* Cross-border capability
**Features**
* Direct wallet integration
* Instant settlement
* Multiple currencies
## Processing Times
* Standard capture: Near instant
* 3DS Authentication: 1 - 5 minutes
* Refunds: 5 - 7 business days
* NGN transfers: 1.5 - 10 minutes
* USD/International: 1 - 3 business days
* CAD (Interac): 5 - 15 minutes
* TRX Network: 1-3 minutes
* ETH Network: 5-30 minutes
* MATIC Network: 1-5 minutes
* Standard capture: Near instant
* Confirmation time: 1-2 minutes
## Capture Flow
The general payment capture process follows these steps:
Check that the payment session is valid and in an authorized state
Complete any required authentication steps:
* 3D Secure for cards
* OTP validation
* PIN verification
Make the API call to capture the payment with:
* Payment session ID
* Capture amount (for partial captures)
* Any method-specific parameters
Handle the capture response:
* Success: Update your systems
* Pending: Wait for webhook
* Failed: Handle error appropriately
Track the payment status via:
* Webhook notifications (recommended)
* Status check endpoints
## Method-Specific Guides
For detailed implementation instructions, see the following guides:
* [Card Payments](/payments/capture-payment/cards)
* [Bank Transfers](/payments/capture-payment/bank-transfer)
* [Stablecoins](/payments/capture-payment/stablecoins-payment)
* [Binance Pay](/payments/capture-payment/binance-pay)
* [Interac e-Transfer](/payments/capture-payment/interac)
## Best Practices
* Implement exponential backoff for retries
* Handle timeouts gracefully
* Log all capture attempts
* Monitor failed captures
* Set appropriate timeout limits
* Validate all capture requests
* Use HTTPS for API calls
* Follow PCI compliance for card data
* Implement proper access controls
* Rotate API keys regularly
* Track capture success rates
* Monitor processing times
* Set up alerts for failures
* Review capture logs regularly
* Record all capture attempts
* Match captures to authorizations
* Reconcile daily transactions
* Track partial captures
* Monitor settlement status
## Testing
Always test capture flows in our sandbox environment first:
* Use test cards for card payments
* Test different authentication scenarios
* Verify webhook handling
* Check error responses
## Rate Limits
Capture requests are subject to rate limiting:
* 100 requests per minute per API key
* Burst limit: 10 requests per second
* Monitor rate limit headers in responses
For additional support:
* Check our [API Reference](/api-reference/overview)
* Review the [Error Handling Guide](/errors)
* Contact [support@juicyway.com](mailto:support@juicyway.com)
# Bank Transfer
Source: https://docs.juicyway.com/payments/capture-payment/bank-transfer
Capture payments via bank transfer with virtual accounts
## Overview
Bank transfer capture generates a virtual account where the customer can deposit funds. This is an asynchronous process - you'll receive webhook notifications when the transfer is detected and completed.
Virtual accounts are typically valid for 24 hours. Monitor the `expires_at` field in the response to know when the account will expire.
## Capture Flow
Call the capture endpoint to get bank account details
Customer initiates transfer to provided account
System detects incoming transfer
Receive webhook notification of successful payment
## Endpoint
```http theme={null}
POST /payment-sessions/{payment_id}
```
### Path Parameters
The ID of the payment session to capture
### Request Example
```bash cURL theme={null}
curl -X POST "https://api.spendjuice.com/payment-sessions/265710b4-255d-11ee-add2-2ae94e9097ac" \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json"
```
```javascript Node.js theme={null}
const response = await fetch(
'https://api.spendjuice.com/payment-sessions/265710b4-255d-11ee-add2-2ae94e9097ac',
{
method: 'POST',
headers: {
'Authorization': ' YOUR_API_KEY',
'Content-Type': 'application/json'
}
}
);
const result = await response.json();
```
```python Python theme={null}
import requests
response = requests.post(
'https://api.spendjuice.com/payment-sessions/265710b4-255d-11ee-add2-2ae94e9097ac',
headers={
'Authorization': ' YOUR_API_KEY',
'Content-Type': 'application/json'
}
)
```
### Response Example
```json theme={null}
{
"data": {
"auth_type": null,
"expires_at": "2024-03-20T11:56:43.482556Z",
"links": {},
"message": "Waiting for payment resolution",
"payment": {
"amount": 100000,
"cancellation_reason": null,
"correlation_id": "26571e60-255d-11ee-b2a8-2ae94e9097ac",
"currency": "NGN",
"customer": {
"billing_address": {
"city": "Ikeja",
"country": "NG",
"line1": "1, Church Street",
"line2": "235 Hello Drive",
"state": "Lagos State",
"zip_code": "23401"
},
"email": "customer@example.com",
"first_name": "John",
"last_name": "Doe"
},
"date": "2024-03-19T11:20:50.050770Z",
"description": "Product Purchase",
"id": "265710b4-255d-11ee-add2-2ae94e9097ac",
"order": {
"identifier": "ORD12345",
"items": [
{
"name": "Premium Package",
"type": "digital"
}
]
}
"mode": "live",
"payment_method": {
"account_name": "JUICE PAYMENTS",
"account_number": "7650266816",
"account_type": "savings",
"bank_name": "Wema Bank",
"id": "498c981d-b549-47c1-bb26-abc798b7f398",
"type": "bank_account"
},
"reference": "ord_1234567890",
"status": "pending"
},
"status": "pending"
}
}
```
## Processing Times
**Average Processing Times**
* NGN transfers: 5-15 minutes
* CAD transfers: 1-2 business days
Times may vary based on:
* Bank network status
* Time of day
* Transaction volume
## Webhook Events
Monitor these webhook events for transfer status:
Virtual account generated successfully
Transfer detected but not yet confirmed
Transfer confirmed and credited
Transfer failed or expired
## Best Practices
1. **Display Information**
* Show account details clearly
* Include transfer instructions
* Display expiration time
* Show expected processing time
2. **Error Handling**
* Handle expired accounts
* Implement retry logic
* Monitor transfer status
* Log all webhook events
3. **User Experience**
* Provide clear transfer instructions
* Display payment status updates
* Send email/SMS notifications
* Include support contact info
For assistance with bank transfers:
* Check our [Error Handling Guide](/errors)
* Review [Webhook Implementation](/webhooks)
* Contact [Support](mailto:support@juicyway.com)
# Cards
Source: https://docs.juicyway.com/payments/capture-payment/cards
# Card Payment Capture
This guide explains how to capture an authorized card payment. The capture request processes the actual charge against the customer's card after authentication.
## Overview
Before capturing a payment, ensure:
1. You have a valid payment session ID from initialization
2. Any required card data is encrypted following our [encryption guide](/payments/encryption-keys)
3. You can handle authentication flows if needed
## Endpoint
```bash theme={null}
POST /payment-sessions/{payment_id}
```
## Request Parameters
Encrypted card payment details
Encrypted card number (PAN)
Encrypted CVV/CVC
Card expiry month (1-12)
Card expiry year (current or future)
## Example Request
```bash cURL theme={null}
curl -X POST "https://api.spendjuice.com/payment-sessions/{payment_id}" \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"card": {
"card_number": "encrypted_card_number",
"cvv": "encrypted_cvv",
"expiry_month": 1,
"expiry_year": 39
}
}'
```
```javascript Node.js theme={null}
const response = await fetch(
`https://api.spendjuice.com/payment-sessions/${paymentId}`,
{
method: 'POST',
headers: {
'Authorization': ` ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
card: {
card_number: encryptedCardNumber,
cvv: encryptedCvv,
expiry_month: 1,
expiry_year: 39
}
})
}
);
```
## Authentication Flows
Some card payments require additional authentication after capture:
### 3D Secure (3DS)
```json theme={null}
{
"data": {
"status": "authenticating",
"auth_type": "3ds",
"message": "3D Secure authentication required",
"links": {
"redirect_url": "https://3ds.issuer-bank.com/auth"
}
}
}
```
Redirect customer to provided URL to complete 3DS
Monitor webhooks or status endpoint for final result
### One-Time Password (OTP)
```json theme={null}
{
"data": {
"status": "authenticating",
"auth_type": "otp",
"message": "OTP sent to registered phone number"
}
}
```
```bash theme={null}
POST /payment-sessions/{payment_id}/authorize
{
"otp": "123456"
}
```
### PIN Verification
```json theme={null}
{
"data": {
"status": "authenticating",
"auth_type": "pin",
"message": "Enter card PIN"
}
}
```
```bash theme={null}
POST /payment-sessions/{payment_id}/authorize
{
"pin": "1234"
}
```
## Error Handling
Card declined by issuing bank
* Status code: 402
* Common reasons:
* Insufficient funds
* Invalid card
* Suspicious activity
Additional authentication needed
* Status code: 401
* Next steps:
* Handle 3DS redirect
* Collect OTP/PIN
* Retry with authentication
## Best Practices
1. **Authentication Flow**
* Handle all authentication types (3DS, OTP, PIN)
* Provide clear user feedback during auth
* Implement proper timeouts and retries
* Monitor auth completion via webhooks
2. **Error Handling**
* Implement exponential backoff for retries
* Show user-friendly error messages
* Log errors with payment IDs
* Handle timeouts gracefully
3. **Security**
* Never log decrypted card data
* Use HTTPS for all requests
* Clear sensitive data after use
* Monitor for unusual patterns
* See [Error Handling Guide](/errors)
* Review [Authentication](/authentication)
* Contact [Support](mailto:support@juicyway.com)
# Interac e-Transfer Capture
Source: https://docs.juicyway.com/payments/capture-payment/interac
Process Interac e-Transfer payments for Canadian transactions
## Overview
Capture an Interac e-Transfer payment by generating a secure payment link that your customer can use to complete the transfer. This endpoint supports incoming (receiving) payments through Canada's Interac e-Transfer system.
Interac e-Transfer is only available for Canadian dollar (CAD) transactions and requires both the sender and recipient to have Canadian bank accounts.
## Endpoint
```bash theme={null}
POST /payment-sessions/{payment_id}
```
## Capture Flow
First create a payment session with [payment initialization](/payments/initialize-payment/interac-e-transfer)
Capture the payment to generate an Interac e-Transfer link
Customer completes the transfer through their online banking
Funds are automatically deposited if enabled, or require security answer
## Response Object
```json theme={null}
{
"data": {
"auth_type": null,
"expires_at": "2024-04-09T01:11:30.239705Z",
"links": {
"redirect_url": "https://gateway-web.fit.interac.ca/reqPayment/eml/CA1MRz75R4Hy"
},
"message": "Waiting for payment",
"payment": {
"amount": 100000, // Amount in cents
"currency": "CAD",
"status": "pending",
"payment_method": {
"type": "interac"
},
"customer": {
"first_name": "John",
"last_name": "Doe",
"email": "john.doe@example.com",
"phone_number": "+14165555555",
"billing_address": {
"line1": "123 Main St",
"line2": "Unit 4B",
"city": "Toronto",
"state": "ON",
"country": "CA",
"zip_code": "M5V 2T6"
}
},
"description": "Invoice payment",
"reference": "inv_20240322_123",
"order": {
"identifier": "ORD12345",
"items": [
{
"name": "Professional Services",
"type": "service"
}
]
}
}
}
}
```
### Important Response Fields
Interac e-Transfer payment link to share with customer
* Valid for payment session duration
* Unique per transaction
* Must be accessed within expires\_at time
ISO 8601 timestamp when the payment session expires
* Default: 1 hours from creation
* Customer must complete transfer before this time
## Transaction Limits
* Minimum: CAD 100.00 (10000 cents)
* Maximum: CAD 10,000.00 (1000000 cents)
* Daily Limit: CAD 25,000.00 (2500000 cents)
* Monthly Limit: CAD 100,000.00 (10000000 cents)
## Processing Times
* Incoming transfers typically process within 15-30 minutes
* Auto-deposit reduces processing time
* Bank cut-off times may affect processing
* Weekend/holiday transfers may take longer
## Error Handling
```json theme={null}
{
"error": {
"code": "invalid_request",
"message": "Invalid payment session ID"
}
}
```
```json theme={null}
{
"error": {
"code": "session_not_found",
"message": "Payment session not found"
}
}
```
```json theme={null}
{
"error": {
"code": "validation_error",
"message": "Invalid currency for Interac e-Transfer"
}
}
```
## Best Practices
1. **Customer Communication**
* Send the redirect URL immediately to the customer
* Include clear transfer instructions
* Notify when payment is received
2. **Error Handling**
* Implement retry logic for failed captures
* Monitor payment session expiration
* Handle timeout scenarios properly
3. **Security**
* Validate payment sessions before capture
* Check transaction limits
* Monitor for suspicious patterns
4. **Integration**
* Use webhooks for real-time updates
* Store payment IDs for reconciliation
* Implement proper logging
For questions about Interac e-Transfer integration:
* See our [API Reference](/api-reference/overview)
* Contact [Support](mailto:support@juicyway.com)
* Review [Error Handling](/errors)
# Stablecoins payment
Source: https://docs.juicyway.com/payments/capture-payment/stablecoins-payment
# Stablecoin Payment Capture
This guide covers how to capture stablecoin payments after initialization. The capture process confirms the blockchain address and network for the payment.
## Overview
Ensure you've completed [payment
initialization](/payments/initialize-payment/stablecoins-transfer) before
attempting capture.
## Endpoint
```bash theme={null}
POST /payment-sessions/{payment_id}
```
## Supported Tokens and Networks
**USDC Support Matrix**
| Network | Status | Confirmation Time |
| ------- | ------ | ----------------- |
| ETH | ✅ | 5-30 minutes |
| MATIC | ✅ | 1-5 minutes |
| AVAXC | ✅ | 1-5 minutes |
**USDT Support Matrix**
| Network | Status | Confirmation Time |
| ------- | ------ | ----------------- |
| ETH | ✅ | 5-30 minutes |
| TRX | ✅ | 1-3 minutes |
Always verify the network matches the token to avoid lost transactions. For
example, send USDC only on ETH, MATIC, or AVAXC networks.
## Request Parameters
Crypto payment details
Blockchain network code: \* ETH (Ethereum) \* TRX (Tron) \* MATIC (Polygon) \*
AVAXC (Avalanche C-Chain)
Stablecoin type: \* USDC \* USDT
## Example Requests
```json USDT on Tron theme={null}
{
"crypto_address": {
"chain": "TRX",
"currency": "USDT"
}
}
```
```json USDC on Polygon theme={null}
{
"crypto_address": {
"chain": "MATIC",
"currency": "USDC"
}
}
```
## Response Format
Payment status: "captured", "failed"
Additional status information
Unique payment identifier
Generated blockchain address for payment
Selected blockchain network
Selected stablecoin
Will be "crypto\_address"
Current payment status
## Example Response
```json theme={null}
{
"data": {
"status": "captured",
"message": "Payment address generated successfully",
"payment": {
"id": "pay_123abc456def",
"currency": "USDT",
"amount": 100000,
"description": "Crypto payment",
"payment_method": {
"address": "TAd3A1MPNb3xhWrCpmi9x7UdqtwigWcdea",
"chain": "TRX",
"currency": "USDT",
"id": "f1ce6d0f-b30b-4c53-810d-77584f2a36fb",
"type": "crypto_address"
},
"status": "captured",
"date": "2024-03-15T12:00:00Z",
"mode": "live",
"customer": {
"first_name": "John",
"last_name": "Doe",
"email": "john.doe@example.com",
"billing_address": {
"line1": "123 Main St",
"line2": "Apt 4B",
"city": "New York",
"state": "NY",
"zip_code": "10001",
"country": "US"
}
},
"reference": "crypto_pay_123"
}
}
}
```
## Transaction Flow
Capture request generates a unique blockchain address
Listen for webhook events: \* crypto.payment.pending - Transaction detected \*
crypto.payment.confirmed - Required confirmations reached \*
crypto.payment.completed - Funds credited
Ensure received amount matches expected payment
## Best Practices
* Use TRX network for lowest fees \* Consider ETH during low gas periods \*
Use MATIC/AVAXC for faster confirmations
* Validate chain/token compatibility \* Handle network congestion gracefully
* Monitor transaction timeouts
* Display QR code for address \* Show clear network requirements \* Provide
transaction instructions
* Check our [Error Handling Guide](/errors) \* Contact
[support@juicyway.com](mailto:support@juicyway.com) \* Join our [Discord
community](https://discord.gg/juice)
# Encryption Keys
Source: https://docs.juicyway.com/payments/encryption-keys
Secure your card data with strong encryption
# Payment Data Encryption
Never send raw card data directly to your backend or our API. All sensitive payment information must be encrypted client-side before transmission.
Protecting customer payment information is critical. Our API uses strong encryption to safeguard sensitive data. This guide explains how to securely handle encryption for card data in your integration.
## Fetching Encryption Keys
To encrypt sensitive card information, you first need to retrieve your unique encryption keys. Make a GET request to:
```bash theme={null}
GET /keys/encryption-key
```
**Parameters**
Environment Mode. Available Values: `live`, `test`
**Successful Response (200 OK):**
```json theme={null}
{
"data": {
"encryption_key": "67634cc972d2433b8725c8f6fbfdf792"
}
}
```
**Error Response (400 Bad Request):**
Indicates an issue with the request, such as an invalid `mode`.
### Encryption Process
When handling sensitive card data, follow these steps:
1. Fetch the encryption key for your environment (test/live)
2. Format the card data as a JSON string
3. Generate a random initialization vector (IV)
4. Encrypt the data using AES-256-GCM with your encryption key and IV
5. Concatenate the hex-encoded IV, ciphertext, and authentication tag
6. Send the encrypted data to our API
Never send raw card data directly to your backend or our API. Always encrypt it first on the client-side.
### Code Examples
```php theme={null}
function card_encrypt($payload, $key) {
$iv = openssl_random_pseudo_bytes(16);
$cipher_text = openssl_encrypt(
$payload,
"aes-256-gcm",
$key,
OPENSSL_RAW_DATA,
$iv,
$tag
);
return implode(':', [
bin2hex($iv),
bin2hex($cipher_text),
bin2hex($tag)
]);
}
// Example usage
$card_data = json_encode([
'card_number' => '4111111111111111',
'expiry_month' => '12',
'expiry_year' => '2025',
'cvv' => '123'
]);
$encrypted = card_encrypt($card_data, $encryption_key);
```
```javascript theme={null}
const cardEncrypt = async (payload, encKey) => {
const _iv = crypto.getRandomValues(new Uint8Array(12));
const encodedPlaintext = new TextEncoder().encode(payload);
const secretKey = await crypto.subtle.importKey(
"raw",
Buffer.from(encKey, "utf8"),
{
name: "AES-GCM",
length: 256,
},
true,
["encrypt", "decrypt"],
);
const cipherText = await crypto.subtle.encrypt(
{
name: "AES-GCM",
iv: _iv,
},
secretKey,
encodedPlaintext,
);
const [value, auth_tag] = [
cipherText.slice(0, cipherText.byteLength - 16),
cipherText.slice(cipherText.byteLength - 16),
];
const cipher = Buffer.from(value).toString("hex");
const iv = Buffer.from(_iv).toString("hex");
const tag = Buffer.from(auth_tag).toString("hex");
return [iv, cipher, tag].join(":");
};
// Example usage
const cardData = JSON.stringify({
card_number: '4111111111111111',
expiry_month: '12',
expiry_year: '2025',
cvv: '123'
});
const encrypted = await cardEncrypt(cardData, encryptionKey);
```
```python theme={null}
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os
import json
import binascii
def card_encrypt(payload, key):
# Convert hex key to bytes
key_bytes = bytes.fromhex(key)
# Generate random IV
iv = os.urandom(12)
# Create AESGCM instance
aesgcm = AESGCM(key_bytes)
# Encrypt the payload
payload_bytes = payload.encode()
cipher_text = aesgcm.encrypt(iv, payload_bytes, None)
# Split cipher text and auth tag
auth_tag = cipher_text[-16:]
encrypted_data = cipher_text[:-16]
# Format result
return ':'.join([
binascii.hexlify(iv).decode(),
binascii.hexlify(encrypted_data).decode(),
binascii.hexlify(auth_tag).decode()
])
# Example usage
card_data = json.dumps({
'card_number': '4111111111111111',
'expiry_month': '12',
'expiry_year': '2025',
'cvv': '123'
})
encrypted = card_encrypt(card_data, encryption_key)
```
```ruby theme={null}
require 'openssl'
require 'json'
def card_encrypt(payload, key)
# Convert hex key to binary
key_bin = [key].pack('H*')
# Generate random IV
iv = OpenSSL::Random.random_bytes(12)
# Create cipher
cipher = OpenSSL::Cipher.new('aes-256-gcm')
cipher.encrypt
cipher.key = key_bin
cipher.iv = iv
# Encrypt
cipher.auth_data = ""
encrypted = cipher.update(payload) + cipher.final
tag = cipher.auth_tag
# Format result
[
iv.unpack('H*')[0],
encrypted.unpack('H*')[0],
tag.unpack('H*')[0]
].join(':')
end
# Example usage
card_data = JSON.generate({
card_number: '4111111111111111',
expiry_month: '12',
expiry_year: '2025',
cvv: '123'
})
encrypted = card_encrypt(card_data, encryption_key)
```
### Security Best Practices
* Store encryption keys securely in environment variables or a key management service
* Never commit encryption keys to source control
* Rotate encryption keys periodically (we'll notify you before key expiration)
* Use different keys for test and production environments
* Encrypt sensitive data as soon as it's collected
* Clear sensitive data from memory after use
* Never log or store raw card data
* Use HTTPS for all API communications
* Implement Content Security Policy (CSP) headers
* Use Subresource Integrity for external scripts
* Minimize the time sensitive data remains in memory
* Clear form fields after encryption
### Troubleshooting Guide
If you receive an "Invalid encryption format" error:
* Verify the encryption key is correct and valid
* Ensure IV, ciphertext, and tag are properly concatenated with colons
* Check that all components are properly hex-encoded
If you receive an "Authentication failed" error:
* Verify you're using the correct encryption key for your environment
* Check that the authentication tag is being properly generated and included
* Ensure the payload hasn't been modified after encryption
* **Random IV Generation**: Ensure a new random IV is generated for each encryption
* **Memory Management**: Clear sensitive data from variables after use
* **Encoding Issues**: Verify proper encoding/decoding of binary data to hex
* **Library Version Compatibility**: Check cryptographic library versions match requirements
# Payment Initialization
Source: https://docs.juicyway.com/payments/initialize-payment
Payment initialization is the first step in processing any payment through the Juice API. This guide covers the core concepts, supported payment methods, and common parameters required for initializing payments.
## Overview
Before capturing a payment, you must first initialize a payment session with customer and transaction details. The initialization process:
1. Validates the payment request
2. Creates a session identifier
3. Sets up the appropriate payment flow
4. Returns payment session details
## Supported Payment Methods
Credit and Debit cards\[Visa & Mastercard]
Direct bank transfers.
* NGN bank accounts.
* International wires.
* ACH transfers.
Cryptocurrency Stablecoins
*
Direct Binance integration.
* Multiple currencies.
* Instant settlement.
Canadian bank transfers via Interac.
* Email money transfer.
* Instant deposits.
**Coming soon!**
* Multiple providers.
* Regional support.
## Universal Parameters
These parameters are required for all payment initializations regardless of the payment method:
Payment amount in minor units (e.g., cents, kobo)
* Minimum: 100
* Must be positive integer
* Example: 10000 = \$100.00 USD
ISO currency code
* Supported: NGN, USD, CAD, USDT, USDC
* Must match payment method
* Example: "USD"
Customer information object
Valid email address
Customer's first name
Customer's last name
Phone number in E.164 format
Billing address details
Must be of type `business` or `individual`
Customer's ip address
* Must be ipv4 e.g 127.0.0.1
Payment description
* Maximum length: 200 characters
* Will appear on statements
Unique transaction reference
* Must be unique per transaction
* Maximum length: 50 characters
Payment method details
* Must be of type: ""
Order information object
Unique identifier
type must be one of digital,physical
Optional additional data
* Nested objects allowed
## Required Headers
| Header | Description | Example |
| ------------- | -------------------- | ------------------ |
| Authorization | Your API key | `skabc123...` |
| Content-Type | Request content type | `application/json` |
Never expose your API key in client-side code. Always make API calls from your server.
## Basic Flow
Create payment session with customer and transaction details
Complete any required authentication steps (3DS, OTP, etc.)
Finalize the payment after successful authentication
Process success/failure and update your system
## Method-Specific Guides
For detailed implementation steps for each payment method, see:
* [Card Payments](/payments/initialize-payment/cards)
* [Bank Transfers](/payments/initialize-payment/bank-transfers)
* [Stablecoins](/payments/initialize-payment/stablecoins-transfer)
* [Binance Pay](/payments/initialize-payment/binance-pay)
* [Interac e-Transfer](/payments/initialize-payment/interac-e-transfer)
- See our
[API Reference](/api-reference/overview)
- Contact
[support@juicyway.com](mailto:support@juicyway.com)
# Bank Transfer Initialization
Source: https://docs.juicyway.com/payments/initialize-payment/bank-transfers
Accept bank transfer payments through virtual accounts for various currencies and banking systems. This guide covers the initialization process for bank transfer payments.
## Overview
Bank transfers are asynchronous - after initialization, you'll receive a virtual account where the customer can deposit funds. Webhook notifications will inform you of the transfer status.
### Supported Bank Transfer Types
* All major Nigerian banks
* Instant virtual account generation
* Real-time transfer notifications
* Processing time: 1.5 - 10 minutes
## Initialize Transfer Payment
```bash theme={null}
POST /payment-sessions
```
### Request Parameters
Payment amount in minor units (e.g., cents, kobo)
* Minimum: 100
* Must be positive integer
* Example: 10000 = \$100.00 USD
ISO currency code
* Supported: NGN, USD, CAD, USDT, USDC
* Must match payment method
* Example: "USD"
Customer information object
Valid email address
Customer's first name
Customer's last name
Phone number in E.164 format
Billing address details
Must be of type `business` or `individual`
Customer's ip address
* Must be ipv4 e.g 127.0.0.1
Payment description
* Maximum length: 200 characters
* Will appear on statements
Unique transaction reference
* Must be unique per transaction
* Maximum length: 50 characters
Payment method details
* Must be of type: ""
Order information object
Unique identifier
type must be one of digital,physical
Optional additional data
* Nested objects allowed
### Example Request
```bash curl theme={null}
curl -X POST "https://api.spendjuice.com/payment-sessions" \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"customer": {
"first_name": "John",
"last_name": "Doe",
"email": "john.doe@example.com",
"phone_number": "+2348000000000",
"billing_address": {
"line1": "123 Main St",
"line2": "Suite 456",
"city": "Ikoyi",
"state": "LA",
"country": "NG",
"zip_code": "12345"
},
"ip_address": "127.0.0.1"
},
"description": "Order Payment",
"currency": "NGN",
"amount": 100000,
"direction": "incoming",
"payment_method": {
"type": "bank_account"
},
"reference": "ord_xyz_123",
"order": {
"identifier": "ORD12345",
"items": [
{
"name": "Product A",
"type": "digital"
}
]
}
}'
```
```python Python theme={null}
import requests
url = "https://api.spendjuice.com/payment-sessions"
headers = {
"Authorization": " YOUR_API_KEY",
"Content-Type": "application/json"
}
data = {
"customer": {
"first_name": "John",
"last_name": "Doe",
"email": "john.doe@example.com",
"phone_number": "+2348000000000",
"billing_address": {
"line1": "123 Main St",
"line2": "Suite 456",
"city": "Ikoyi",
"state": "LA",
"country": "NG",
"zip_code": "12345"
},
"ip_address": "127.0.0.1"
},
"description": "Order Payment",
"currency": "NGN",
"amount": 100000,
"direction": "incoming",
"payment_method": {
"type": "bank_account"
},
"reference": "ord_xyz_123",
"order": {
"identifier": "ORD12345",
"items": [
{
"name": "Product A",
"type": "digital"
}
]
}
}
response = requests.post(url, json=data, headers=headers)
print(response.json())
```
### Success Response
```json theme={null}
{
"data": {
"auth_type": null,
"expires_at": "2024-03-01T08:43:08.110470Z",
"links": {},
"message": "Virtual account generated successfully",
"payment": {
"amount": 100000,
"cancellation_reason": null,
"correlation_id": "2549dcf4-d743-11ee-9d95-c6d49632367b",
"currency": "NGN",
"customer": {
"billing_address": {
"city": "Ikoyi",
"country": "NG",
"line1": "123 Main St",
"line2": "Suite 456",
"state": "LA",
"zip_code": "12345"
},
"email": "john.doe@example.com",
"first_name": "John",
"id": "d05e51df-809e-498a-ac3f-7acfc0b5d35d",
"last_name": "Doe",
"phone_number": "+2348000000000"
},
"date": "2024-02-29T20:43:08.344264Z",
"description": "Order Payment",
"id": "2549c96c-d743-11ee-aa4d-c6d49632367b",
"order": {
"identifier": "ORD12345",
"items": [
{
"name": "Product A",
"type": "digital"
}
]
}
"mode": "live",
"payment_method": {
"account_name": "JUICE PAYMENTS",
"account_number": "1234567890",
"bank_name": "Test Bank",
"id": "5e21efda-c526-4057-92f6-1b94ee210b47",
"type": "bank_account"
},
"reference": "ord_xyz_123",
"status": "pending"
},
"status": "pending"
}
}
```
## Transfer Limits
Transaction Limits may vary based on
* Account verification level.
* Transaction history.
##
* Minimum: ₦100
* Maximum per transaction: ₦5,000,000
## Processing Times
Transfer processing times vary by:
* Bank type (local vs international)
* Time of day
* Transaction volume
* Bank system availability
| Currency | Transfer Type | Typical Processing Time |
| -------- | ------------- | ----------------------- |
| NGN | Local | 1.5 - 10 minutes |
## Error Handling
```json theme={null}
{
"error": {
"code": "invalid_request",
"message": "Invalid parameters provided",
"details": {
"amount": ["Amount must be at least 100"]
}
}
}
```
```json theme={null}
{
"error": {
"code": "validation_error",
"message": "The request contains invalid parameters",
"details": {
"currency": ["Currency must be one of: NGN, USD"]
}
}
}
```
## Best Practices
1. **Unique References**
* Use unique, idempotent references for each transfer
* Include your internal order ID in the reference
* Store the payment ID returned in the response
2. **Webhook Integration**
* Implement webhook handling for transfer status updates
* Process webhooks asynchronously
* Verify webhook signatures
3. **Error Handling**
* Implement proper retry logic
* Handle timeouts gracefully
* Log all errors with payment references
4. **Customer Communication**
* Display virtual account details clearly
* Show transfer instructions
* Set clear expiration times
* Review the
[Error Handling Guide](/errors)
* Check our
[API Reference](/api-reference/overview)
* Contact
[Support](mailto:support@juicyway.com)
# Card Payment Initialization
Source: https://docs.juicyway.com/payments/initialize-payment/cards
Learn how to initialize card payments securely via the Juicyway API
## Overview
Card payment initialization is the first step in processing a card payment. This endpoint creates a payment session that can be used to securely process credit and debit card transactions.
## Endpoint
```bash theme={null}
POST /payment-sessions
```
## Request Parameters
Payment amount in minor units (e.g., cents, kobo)
* Minimum: 100
* Must be positive integer
* Example: 10000 = \$100.00 USD
ISO currency code
* Supported: NGN, USD, CAD, USDT, USDC
* Must match payment method
* Example: "USD"
Customer information object
Valid email address
Customer's first name
Customer's last name
Phone number in E.164 format
Billing address details
Must be of type `business` or `individual`
Customer's ip address
* Must be ipv4 e.g 127.0.0.1
Payment description
* Maximum length: 200 characters
* Will appear on statements
Unique transaction reference
* Must be unique per transaction
* Maximum length: 50 characters
Payment method details
* Must be of type: ""
Order information object
Unique identifier
type must be one of digital,physical
Optional additional data
* Nested objects allowed
## Example Requests
```json Basic Card Payment theme={null}
{
"customer": {
"first_name": "John",
"last_name": "Doe",
"email": "john.doe@example.com",
"phone_number": "+2348118873422",
"billing_address": {
"line1": "123 Main St",
"line2": "Suite 456",
"city": "Springfield",
"state": "CA",
"country": "US",
"zip_code": "12345"
},
"ip_address": "127.0.0.1"
},
"description": "Premium Package Purchase",
"currency": "USD",
"amount": 100000,
"payment_method": {
"type": "card"
},
"reference": "ord_1234567890",
"order": {
"identifier": "ORD12345",
"items": [
{
"name": "Premium Package",
"type": "digital"
}
]
}
}
```
```json International Card Payment theme={null}
{
"customer": {
"first_name": "Jane",
"last_name": "Smith",
"email": "jane.smith@example.com",
"phone_number": "+2348012345678",
"billing_address": {
"line1": "10 Victoria Island",
"city": "Lagos",
"state": "Lagos",
"country": "NG",
"zip_code": "23401"
},
"ip_address": "127.0.0.1"
},
"description": "International Purchase",
"currency": "NGN",
"amount": 500000,
"payment_method": {
"type": "card"
},
"reference": "ord_intl_12345",
"order": {
"identifier": "INTL12345",
"items": [
{
"name": "International Package",
"type": "digital"
}
]
},
}
```
## Test Cards
Use these test cards in your sandbox environment to simulate different payment scenarios:
**VISA Test Card (NGN)**
* Card Number: 4012000033330026
* Expiry Date: 01/39
* CVV: 100
**Mastercard Test Card (USD)**
* Card Number: 5123450000000008
* Expiry Date: 12/25
* CVV: 100
**VISA 3DS Test Card**
* Card Number: 4761530000000008
* Expiry Date: 05/25
* CVV: 100
* Test OTP: 123456
**Mastercard 3DS Test Card**
* Card Number: 5200000000001005
* Expiry Date: 12/25
* CVV: 100
* Test OTP: 123456
**Insufficient Funds**
* Card Number: 4000000000000010
* Expiry Date: 01/25
* CVV: 100
**Declined Card**
* Card Number: 4000000000000002
* Expiry Date: 01/25
* CVV: 100
## Response Examples
```json 201 Success - Payment Session Created theme={null}
{
"data": {
"auth_type": "3ds",
"expires_at": "2024-03-01T08:43:08.110470Z",
"links": {},
"message": "Created",
"payment": {
"amount": 100000,
"cancellation_reason": null,
"currency": "USD",
"customer": {
"billing_address": {
"city": "Springfield",
"country": "US",
"line1": "123 Main St",
"line2": "Suite 456",
"state": "CA",
"zip_code": "12345"
},
"email": "john.doe@example.com",
"first_name": "John",
"id": "cust_1234567890",
"last_name": "Doe",
"phone_number": "+2348118873422"
},
"date": "2024-02-29T20:43:08.344264Z",
"description": "Premium Package Purchase",
"id": "pay_1234567890",
"order": {
"identifier": "ORD12345",
"items": [
{
"name": "Premium Package",
"type": "digital"
}
]
}
"mode": "live",
"payment_method": {
"type": "card"
},
"reference": "ord_1234567890",
"status": "pending"
},
"status": "pending"
}
}
```
```json 400 Invalid Request theme={null}
{
"error": {
"code": "invalid_request",
"message": "The request was invalid",
"details": {
"amount": ["Amount must be at least 100000"]
}
}
}
```
```json 422 Validation Error theme={null}
{
"error": {
"code": "validation_error",
"message": "The request contains invalid parameters",
"details": {
"currency": ["Currency must be one of: NGN, USD, CAD"]
}
}
}
```
## Authentication Flows
Some card payments may require additional authentication steps. The response will indicate the required authentication type:
If 3DS is required, you'll receive:
```json theme={null}
{
"data": {
"auth_type": "3ds",
"message": "3DS authentication required",
"links": {
"redirect_url": "https://3ds.payment-processor.com/auth"
}
}
}
```
Redirect the customer to complete 3DS verification, then:
1. Listen for webhook notification, or
2. Poll payment status endpoint
For OTP authentication:
```json theme={null}
{
"data": {
"auth_type": "otp",
"message": "Please enter OTP to complete transaction"
}
}
```
Submit OTP via:
```bash theme={null}
POST /payment-sessions/{payment_id}/authorize
{
"otp": "123456"
}
```
For PIN authentication:
```json theme={null}
{
"data": {
"auth_type": "pin",
"message": "Please enter card PIN"
}
}
```
Submit PIN via:
```bash theme={null}
POST /payment-sessions/{payment_id}/authorize
{
"pin": "1234"
}
```
## Security Requirements
* All card data must be encrypted before transmission
* Use our [encryption guide](/payments/encryption-keys) for implementation
* Never log or store raw card details
* Use our secure payment fields when collecting card data
* Follow PCI DSS requirements if handling card data
* Implement proper data sanitization
* Use HTTPS for all API calls
* Include proper authorization headers
* Rotate API keys regularly
## Error Handling
Card declined by issuing bank
* Status code: 402
* Possible reasons:
* Insufficient funds
* Suspicious activity
* Expired card
Invalid card details provided
* Status code: 400
* Check:
* Card number
* Expiry date
* CVV
Failed authentication (3DS/OTP/PIN)
* Status code: 401
* Verify credentials and retry
Common error scenarios to handle:
* Invalid currency code
* Amount below minimum
* Missing customer information
* Invalid phone/email format
* Incorrect billing address
* Network timeouts
## Next Steps
After successful initialization:
1. Handle any required authentication
2. [Capture the payment](/payments/capture-payment/cards)
3. Listen for [webhook notifications](/webhooks)
* Review [Authentication Guide](/authentication)
* Check [Error Handling](/errors)
* Contact [Support](mailto:support@juicyway.com)
# Interac e-Transfer
Source: https://docs.juicyway.com/payments/initialize-payment/interac-e-transfer
Initialize Interac e-Transfer payments for Canadian transactions
## Overview
Interac e-Transfer enables secure money transfers between Canadian bank accounts. This endpoint supports both incoming (receiving) and outgoing (sending) transfers.
## Endpoint
```bash theme={null}
POST /payment-sessions
```
## Common Requirements
**Canadian-Specific Validation:**
* Valid Canadian phone number (+1 format)
* Canadian postal code format
* Province/territory codes (e.g., ON, BC, AB)
* Canadian bank account required
## **Incoming Payments (CAD via Interac Auto-Deposit)**
CAD direct deposits via **Interac Auto-Deposit** streamline the payment process, ensuring that incoming funds are quickly and securely credited to your account, enhancing both convenience and financial management.
Auto-deposit is enabled using the **merchant’s registered email**. Once we receive the merchant’s registered email, we configure it for Interac Auto-Deposit.
Test incoming CAD deposits in **Production**, as deposits are real-time.
### **Confirming Deposits**
To confirm incoming deposits, listen for webhooks.
**Example webhook payload (successful CAD deposit):**
```json theme={null}
{
"checksum": "",
"data": {
"amount": 10000,
"callback_urls": {},
"cancellation_reason": null,
"channel_reference": "",
"collection_mode": null,
"correlation_id": "",
"currency": "NGN",
"customer": {
"account_id": "",
"billing_address": {
"city": "",
"country": "NG",
"line1": "",
"state": "",
"zip_code": ""
},
"email": "",
"first_name": "",
"id": "",
"last_name": "",
"phone_number": "",
"type": ""
},
"date": "",
"description": "",
"fee": null,
"id": "",
"merchant": {
"address": {
"city": "",
"country": "NG",
"line1": "",
"line2": null,
"state": "",
"zip_code": ""
},
"email": "",
"id": "",
"mcc": "",
"name": "",
"phone": ""
},
"order": {
"identifier": "",
"items": [
{
"name": "Transfer",
"type": "digital"
}
]
}
"mode": "live",
"order": {
"identifier": "",
"items": [
{
"name": "Transfer",
"type": "digital"
}
]
},
"payer": {
"account_name": null,
"account_number": null,
"bank_name": ""
},
"payment_method": {
"account_numner": "",
"account_name": "",
"bank_code": "",
"bank_name": "",
"currency": "",
"id": "",
"type": "bank_account"
},
"provider_id": "",
"redirect_url": null,
"reference": "",
"status": "success|failed",
"transaction_id": "",
"type": "payin|payout"
},
"event": "payment.session.succeeded|payment.session.failed"
}
```
**Developer tasks:**
* Provide the merchant’s **registered email** so it can be enabled for auto-deposit.
* Implement an endpoint on your server to receive POST requests from Juicyway.
* Verify the checksum for authenticity.
* Use status (success) + type (payin) to confirm the CAD deposit.
* Update your internal systems (balances, invoices, etc.).
## Overview
Capture an Interac e-Transfer payment by generating a secure payment link that your customer can use to complete the transfer. This endpoint supports incoming (receiving) payments through Canada's Interac e-Transfer system.
Interac e-Transfer is only available for Canadian dollar (CAD) transactions and requires both the sender and recipient to have Canadian bank accounts.
## Endpoint
```bash theme={null}
POST /payment-sessions/{payment_id}
```
## Capture Flow
First create a payment session with [payment initialization](/payments/initialize-payment/interac-e-transfer)
Capture the payment to generate an Interac e-Transfer link
Customer completes the transfer through their online banking
Funds are automatically deposited if enabled, or require security answer
## Response Object
```json theme={null}
{
"data": {
"auth_type": null,
"expires_at": "2024-04-09T01:11:30.239705Z",
"links": {
"redirect_url": "https://gateway-web.fit.interac.ca/reqPayment/eml/CA1MRz75R4Hy"
},
"message": "Waiting for payment",
"payment": {
"amount": 100000, // Amount in cents
"currency": "CAD",
"status": "pending",
"payment_method": {
"type": "interac"
},
"customer": {
"first_name": "John",
"last_name": "Doe",
"email": "john.doe@example.com",
"phone_number": "+14165555555",
"billing_address": {
"line1": "123 Main St",
"line2": "Unit 4B",
"city": "Toronto",
"state": "ON",
"country": "CA",
"zip_code": "M5V 2T6"
}
},
"description": "Invoice payment",
"reference": "inv_20240322_123",
"order": {
"identifier": "ORD12345",
"items": [
{
"name": "Professional Services",
"type": "service"
}
]
}
}
}
}
```
### Important Response Fields
Interac e-Transfer payment link to share with customer
* Valid for payment session duration
* Unique per transaction
* Must be accessed within expires\_at time
ISO 8601 timestamp when the payment session expires
* Default: 1 hours from creation
* Customer must complete transfer before this time
##
##
## Outgoing Transfers
Use this flow when sending payments to recipients through Interac e-Transfer.
### Additional Parameters for Outgoing Transfers
One of: "personal", "business"
Recipient's first name
Recipient's last name
Recipient's Interac-registered email
Recipient's phone number (optional)
Security question for the transfer
Answer to the security question
### Example Request (Outgoing)
```json theme={null}
{
"customer": {
"first_name": "John",
"last_name": "Doe",
"email": "john.doe@example.com",
"phone_number": "+14165555555",
"billing_address": {
"line1": "123 Main St",
"line2": "Unit 4B",
"city": "Toronto",
"state": "ON",
"country": "CA",
"zip_code": "M5V 2T6"
},
"ip_address": "127.0.0.1"
},
"description": "Expense reimbursement",
"currency": "CAD",
"amount": 100000,
"direction": "outgoing",
"payment_method": {
"type": "interac",
"beneficiary_type": "personal",
"first_name": "Jane",
"last_name": "Smith",
"email": "jane.smith@example.com",
"phone_number": "+14165556666",
"question": "What is our project code",
"answer": "ALPHA123"
},
"reference": "exp_20240322_456",
"order": {
"identifier": "EXP12345",
"items": [
{
"name": "Travel Reimbursement",
"type": "expense"
}
]
},
}
```
##
## **Linking Multiple Emails**
In situations where a user has multiple email addresses, we typically advise applying restrictions. However, when necessary, you can link a secondary email (Email 2) to the primary registered email (Email 1) using the endpoint below.
**Endpoint:**
```bash theme={null}
PATCH /customers/:id/register_emails
```
**Request Body:**
```json theme={null}
{
"emails": [
"user1@example.com", // primary registered email (Email 1)
"user2@example.com" // additional linked email (Email 2)
]
}
```
Validation Rules
* Minimum: CAD 100.00 (10000 cents)
* Maximum: CAD 10,000.00 (1000000 cents)
* Must be in Canadian Dollars (CAD)
* Must be a positive integer in cents
* Must begin with +1
* Must be 11 digits total (+1 plus 10-digit number)
* Area code must be valid for Canada
* Must follow Canadian format: "A1A 1A1"
* Letter-number-letter number-letter-number
* First letter cannot be D, F, I, O, Q, U, W, Z
* Required for outgoing transfers
* Question must be 10-100 characters
* Answer must be 3-50 characters
* Cannot contain sensitive information
## Error Handling
Invalid Canadian province/territory code provided.
* Must be one of: AB, BC, MB, NB, NL, NS, NT, NU, ON, PE, QC, SK, YT
Invalid Canadian postal code format.
* Must match pattern: A1A 1A1
Invalid Canadian phone number.
* Must start with +1
* Must be a valid area code
Transfer amount exceeds limits.
* Check minimum/maximum allowed amounts
## Processing Times
* Incoming transfers: Usually processed within 15-30 minutes
* Outgoing transfers: Usually processed within 30-60 minutes
* Cutoff times may apply based on recipient's bank
For support with Interac e-Transfer integration:
* Check our [Error Handling Guide](/errors)
* Contact [Support](mailto:support@juicyway.com)
# Stablecoin Transfer
Source: https://docs.juicyway.com/payments/initialize-payment/stablecoins-transfer
Initialize stablecoin payments with support for multiple tokens and chains
## Overview
Initialize stablecoin payments using supported tokens across multiple blockchain networks. This endpoint supports both inbound and outbound crypto transactions with real-time rate conversion.
## Supported Tokens and Chains
**USDT**
* Tron (TRX)
**USDC**
* Ethereum (ETH)
* Polygon (MATIC)
* Avalanche C-Chain (AVAXC)
Ensure you use the correct chain for each token to avoid lost transactions. Not all tokens are supported on all chains.
## Transaction Limits
* Minimum: 18 USDT/USDC
* Maximum: 50,000 USDT/USDC per transaction
**Transaction limits may vary based on:**
* Account verification level
* Transaction history
* Selected chain/token
## Processing Times
* Average: 1-3 minutes
* Network fee: Low (\<\$2)
* Block confirmations required: 6
* Average: 5-30 minutes
* Network fee: Variable (gas fees)
* Block confirmations required: 12
* Average: 1-5 minutes
* Network fee: Low (\<\$2)
* Block confirmations required: 15
## Initialize Payment
```http theme={null}
POST /payment-sessions
```
### Request Parameters
Payment amount in minor units (e.g., cents, kobo)
* Minimum: 100
* Must be positive integer
* Example: 10000 = \$100.00 USD
ISO currency code
* Supported: NGN, USD, CAD, USDT, USDC
* Must match payment method
* Example: "USD"
Customer information object
Valid email address
Customer's first name
Customer's last name
Phone number in E.164 format
Billing address details
Must be of type `business` or `individual`
Customer's ip address
* Must be ipv4 e.g 127.0.0.1
Payment description
* Maximum length: 200 characters
* Will appear on statements
Unique transaction reference
* Must be unique per transaction
* Maximum length: 50 characters
Payment method details
* Must be of type: ""
Order information object
Unique identifier
type must be one of digital,physical
Optional additional data
* Nested objects allowed
### Request Example
```json theme={null}
{
"customer": {
"first_name": "John",
"last_name": "Doe",
"email": "john.doe@example.com",
"phone_number": "+2348118873422",
"billing_address": {
"line1": "123 Main St",
"line2": "234 Feranmi Drive",
"city": "Springfield",
"state": "CA",
"country": "US",
"zip_code": "12345"
},
"ip_address": "127.0.0.1"
},
"description": "Crypto Payment",
"currency": "USD",
"amount": 100000,
"direction": "incoming",
"payment_method": {
"type": "crypto_address"
},
"reference": "crypto-tx-123",
"order": {
"identifier": "ORD12345",
"items": [
{
"name": "Digital Product",
"type": "digital"
}
]
}
}
```
### Response Example
```json theme={null}
{
"data": {
"status": "pending",
"message": "Payment session initialized",
"payment": {
"id": "pay_123abc456def",
"currency": "USD",
"amount": 100000,
"description": "Crypto Payment",
"payment_method": {
"address": "TRWBqiqoFZysoAeyR1J35ibuyc8EvhUAoY",
"chain": "TRX",
"currency": "USDT",
"type": "crypto_address"
},
"status": "pending",
"date": "2024-03-15T12:00:00Z",
"mode": "live",
"customer": {
"first_name": "John",
"last_name": "Doe",
"email": "john.doe@example.com",
"billing_address": {
"line1": "123 Main St",
"line2": "234 Feranmi Drive",
"city": "Springfield",
"state": "CA",
"zip_code": "12345",
"country": "US"
}
},
"reference": "crypto-tx-123",
"order": {
"identifier": "ORD12345",
"items": [
{
"name": "Digital Product",
"type": "digital"
}
]
}
}
}
}
```
## Validation Rules
* Must be within min/max limits
* Must be in minor units (cents)
* Must be a positive integer
* Must match chain format
* Must be active/valid address
* Must support token type
* Token must be supported on chain
* Chain must be active/operational
* Network fees must be reasonable
## Rate Conversion
* Exchange rates are locked for 15 minutes
* Rates include network fees
* Rate source: aggregated from major exchanges
* Rate updates: every 30 seconds
## Webhooks
Monitor transaction status via webhooks:
* `crypto.payment.pending`- Payment detected but unconfirmed
* `crypto.payment.confirmed`- Required confirmations reached
* `crypto.payment.completed`- Funds credited to account
* `crypto.payment.failed`- Transaction failed or expired
## Best Practices
1. **Security**
* Validate addresses before displaying
* Show clear network/token warnings
* Include QR codes for addresses
2. **User Experience**
* Display real-time rate updates
* Show confirmation progress
* Provide clear payment instructions
3. **Error Handling**
* Handle network congestion
* Implement payment expiry
* Monitor transaction status
For additional assistance:
* Check our [Error Handling](/errors) guide
* Contact [Support](mailto:support@juicyway.com)
* Join our [Discord](https://discord.gg/juice)
# Overview
Source: https://docs.juicyway.com/payments/overview
Accept payments globally with multiple payment methods and currencies
## Introduction
Juicyway's payment system enables businesses to accept payments seamlessly from customers worldwide using various payment methods. Our flexible platform supports both incoming and outgoing transactions, making it ideal for diverse business needs from e-commerce to cross-border payments.
## Payment Directions
Accept payments from customers through multiple channels:
* E-commerce transactions
* Service payments
* Digital product purchases
Send payments to beneficiaries:
* Vendor payments
* Refunds
* Payroll
* Disbursements
## Payment Methods
**Supported Networks**
* Visa
* Mastercard
**Transfer Types**
* NGN bank transfers
**Features**
* Instant account verification
* Automated reconciliation
* Standing instructions
* Bulk transfers
**Supported Tokens**
* USDC (ETH, MATIC, AVAXC)
* USDT (ETH, TRX,AVAXC)
**Features**
* Multi-chain support
* Automated rate conversion
* Real-time settlements
* Low transaction fees
**Canadian Payments**
* Payment link widget
* Direct e-transfer deposit
* Interac Payment link
## Transaction Limits and Processing Times
### Card Payments
**Transaction Limits**
* Minimum: 100NGN, 5 CAD
* Maximum per transaction:
* NGN: 5,000,000
* CAD: 10,000
**Processing Times**
* Standard transactions: Near instant
* 3DS Authentication: 1-5 minutes
* Refunds: 5-7 business days
### Bank Transfers
**Transaction Limits**
* Minimum: 100NGN, 4CAD
* Maximum per transaction:
* NGN: 10,000,000
* CAD: 50,000
**Processing Times**
* NGN transfers: Almost Immediate
* Interac -Almost immediate
### Stablecoins
**Transaction Limits**
* Minimum: 10 USDT/USDC
* Maximum: 100,000 USDT/USDC per transaction
**Processing Times by Network**
* TRX: 1-3 minutes
* ETH: 1-5 minutes
* MATIC: 1-5 minutes
* AVAXC: 1-5 minutes
### Interac e-Transfer
**Transaction Limits**
* Minimum: 5 CAD
* Maximum: 10,000 CAD per transaction
**Processing Times**
* Incoming: 30 secs -2 minutes
* Outgoing: 30 secs -2 minutes
### Payment Method Coverage
* Global acceptance of Visa and Mastercard
* Region-specific features and limits
* 3DS requirements vary by jurisdiction
* Local card processing where available
* NGN: All major Nigerian banks
* CAD: Via Interac only
* Global availability
* Restricted jurisdictions excluded
* Multi-chain support
* Cross-border capabilities
### Interac e-Transfer
* Exclusive to Canadian market
* Requires Canadian bank account
* Supports both personal and business accounts
* Available to all major Canadian financial institutions
## Supported Currencies
Nigerian Naira
* Local bank transfers
* Card payments
* Dynamic deposit
Canadian Dollar
* Interac e-Transfer
* Local transfers
* Card payments
Transaction limits and processing times may vary based on:
* Account verification status
* Business type and history
* Regional regulations
* Risk assessment
* Payment method selected
Contact support for increased limits or special requirements.
* Direct Debit payments
* Mobile Money integration
* Additional currency support
* Enhanced payment features
# Payment Widget
Source: https://docs.juicyway.com/payments/payment-widget
Integrate our secure payment widget into your platform
## Overview
The Juicyway Payment Widget provides a pre-built, customizable checkout experience that you can easily embed into your website or application. This secure, user-friendly solution handles the entire payment flow while maintaining your brand identity.
## Key Features
* **Quick Integration**: Simple implementation with minimal code
* **Customizable UI**: Match your brand's look and feel
* **Secure by Default**: PCI-compliant payment processing
* **Multiple Payment Methods**: Support for cards, bank transfers, and more
* **Responsive Design**: Works seamlessly on all devices
## Benefits
Get up and running quickly with our pre-built solution
Built-in security features and compliance standards
Optimized checkout flow reduces abandonment
Supports various implementation methods
See our [Widget Integration Guide](/payments/payment-widget/widget-integration-guide) for detailed implementation instructions.
# Widget Integration Guide
Source: https://docs.juicyway.com/payments/payment-widget/widget-integration-guide
Step-by-step guide to integrate the Juicyway Payment Widget
This guide will walk you through the process of integrating the Juicyway Payment Widget into your application.
## Overview
The Juicyway Payment Widget provides a secure and customizable payment solution that can be easily integrated into your website or application. Follow these steps to implement the widget in your platform.
## Integration Steps
Add the following script tag to the `` section of your HTML:
```html theme={null}
```
Define a JavaScript function to initialize the payment widget:
```javascript theme={null}
function openWidget() {
Juicyway.PayWithJuice({
// Configuration options detailed below
onClose: () => {
// Called when user closes widget
},
onSuccess: () => {
// Called when payment is successful
},
onError: (error) => {
// Called when payment fails
},
// Required parameters
reference: "unique_ref_123",
amount: 1000,
currency: "USD",
description: "Product purchase",
isLive: true,
key: "YOUR_API_KEY",
order: {
identifier: "ORDER123",
items: [
{
name: "E-book",
type: "digital",
qty: 1,
amount: 1000
}
]
},
// Optional parameters
appName: "Your App Name",
customer: {
email: "customer@email.com",
first_name: "Test",
last_name: "Customer",
phone_number: "+1234567890",
billing_address: {
line1: "123 Main St",
city: "San Francisco",
state: "CA",
zip_code: "94105",
country: "US"
}
},
paymentMethod: {
type: "card"
},
order: {
// Additional payment order
}
});
}
```
Create a button or link that triggers the payment widget:
```html theme={null}
```
## Configuration Parameters
### Required Parameters
A unique identifier for the payment transaction
The payment amount in the smallest denomination of the currency (e.g., cents for USD)
A three-letter ISO 4217 currency code (e.g., USD, NGN, CAD)
A short description of the payment
Set to `true` for production environment, `false` for sandbox testing
Your Juicyway API key
Order details object containing:
Unique identifier for the order
Array of items in the order
Name of the item
Type of item (e.g., "digital", "physical")
Quantity of the item
Price per item
### Optional Parameters
The name of your merchant's business or application
Customer details object containing:
Customer's email address
Customer's first name
Customer's last name
Customer's phone number with country code
Street address
City
State/Province
Postal/ZIP code
Two-letter country code
Payment method configuration:
Payment method type: "card" | "bank\_account" | "interac"
Additional data related to the payment
## Callback Functions
Called when the user closes the payment widget
Called when the payment is successfully completed
Called when an error occurs during payment processing
For security purposes, always ensure you're using the correct API key for your environment (test or live).
# Quickstart Guide
Source: https://docs.juicyway.com/quickstart
Get started with Juicyway API in minutes.
This guide will help you start accepting payments with our API quickly and securely. Follow these steps to begin processing transactions.
## Step 1: Create Your Account
Create your Juicyway business account:
* For live transactions: [Production Dashboard](https://app.juicyway.com)
* For testing: [Sandbox Dashboard](https://sandbox.juicyway.com/)
After signing up:
1. Navigate to the KYC banner on the home page
2. Upload dummy data
3. Submit for immediate approval
After signing up:
1. Navigate to Settings → API Keys.
2. Fetch test and live API keys.
3. Store keys securely - never expose them in client-side code.
Configure webhooks to receive real-time payment updates:
1. Go to Settings → Webhooks
2. Add your webhook URL
## Step 2: Make Your First API Call
Test your integration with this simple API call:
```bash cURL theme={null}
curl -X POST "https://api-sandbox.spendjuice.com/payment-sessions" \
-H "Authorization: YOUR_TEST_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"customer": {
"first_name": "John",
"last_name": "Doe",
"email": "john.doe@example.com",
"phone_number": "+2348118873422",
"billing_address": {
"line1": "123 Test Lane",
"city": "Test City",
"state": "Test State",
"country": "NG",
"zip_code": "12345"
},
"ip_address": "127.0.0.1"
},
"description": "Test Payment",
"currency": "NGN",
"amount": 100000,
"payment_method": {
"type": "card"
},
"reference": "test-payment-123"
}'
```
```javascript Node.js theme={null}
const axios = require('axios');
const response = await axios.post(
'https://api-sandbox.spendjuice.com/payment-sessions',
{
customer: {
first_name: 'John',
last_name: 'Doe',
email: 'john.doe@example.com',
phone_number: '+2348118873422',
billing_address: {
line1: '123 Test Lane',
city: 'Test City',
state: 'Test State',
country: 'NG',
zip_code: '12345'
}
},
description: 'Test Payment',
currency: 'NGN',
amount: 100000,
payment_method: {
type: 'card'
},
reference: 'test-payment-123'
},
{
headers: {
'Authorization': ` YOUR_TEST_API_KEY`,
'Content-Type': 'application/json'
}
}
);
```
```python Python theme={null}
import requests
response = requests.post(
'https://api-sandbox.spendjuice.com/payment-sessions',
json={
'customer': {
'first_name': 'John',
'last_name': 'Doe',
'email': 'john.doe@example.com',
'phone_number': '+2348118873422',
'billing_address': {
'line1': '123 Test Lane',
'city': 'Test City',
'state': 'Test State',
'country': 'NG',
'zip_code': '12345'
}
},
'description': 'Test Payment',
'currency': 'NGN',
'amount': 100000,
'payment_method': {
'type': 'card'
},
'reference': 'test-payment-123'
},
headers={
'Authorization': ' YOUR_TEST_API_KEY',
'Content-Type': 'application/json'
}
)
```
## Step 3: Test Card Payments
Use these test cards to simulate different payment scenarios:
**VISA Test Card**
* Card Number: 4012000033330026
* Expiry: 01/39
* CVV: 100
**Failed Card**
* Card Number: 4000000000000002
* Expiry: 01/25
* CVV: 100
**3DS Card**
* Card Number: 4761530000000008
* Expiry: 05/25
* CVV: 100
* Test OTP: 123456
## Step 4: Handle Webhooks
Set up webhook handling to receive real-time payment updates. Here's a basic example:
```javascript theme={null}
app.post('/webhooks', (req, res) => {
const payload = req.body;
const checksum = payload.checksum;
const businessId = process.env.BUSINESS_ID;
// Validate webhook signature
if (!validateSignature(payload, checksum, businessId)) {
return res.status(401).send('Invalid signature');
}
// Handle different event types
switch(payload.event) {
case 'payment.session.succeeded':
// Handle successful payment
break;
case 'payment.session.failed':
// Handle failed payment
break;
}
res.status(200).send('Webhook received');
});
```
## Next Steps
1. Review our [API Authentication](/authentication) guide for secure API access
2. Set up comprehensive [Webhook Handling](/webhooks)
3. Learn about [Error Handling](/errors)
4. Explore supported [Payment Methods](/payments/overview)
For additional assistance:
* Review our [Error Handling Guide](/errors)
* Contact [support@juicyway.com](mailto:support@juicyway.com)
# Add contact to a market maker
Source: https://docs.juicyway.com/reference/exchange/add-contact-to-a-market-maker
/openapi.json patch /exchange/market-makers/{id}/add-contact
# Cancel an order
Source: https://docs.juicyway.com/reference/exchange/cancel-an-order
/openapi.json put /exchange/orders/{id}/cancel
# Convert an amount from one currency to another
Source: https://docs.juicyway.com/reference/exchange/convert-an-amount-from-one-currency-to-another
/openapi.json post /exchange/convert
# Create a market maker
Source: https://docs.juicyway.com/reference/exchange/create-a-market-maker
/openapi.json post /exchange/market-makers
# Create a rate
Source: https://docs.juicyway.com/reference/exchange/create-a-rate
/openapi.json post /exchange/rates
# Create a standing order
Source: https://docs.juicyway.com/reference/exchange/create-a-standing-order
/openapi.json post /exchange/standing-orders
# Create a swap configuration
Source: https://docs.juicyway.com/reference/exchange/create-a-swap-configuration
/openapi.json post /exchange/swap-configurations
# Create an order
Source: https://docs.juicyway.com/reference/exchange/create-an-order
/openapi.json post /exchange/orders
# Delete a rate
Source: https://docs.juicyway.com/reference/exchange/delete-a-rate
/openapi.json delete /exchange/rates/{id}
# Delete a standing order
Source: https://docs.juicyway.com/reference/exchange/delete-a-standing-order
/openapi.json delete /exchange/standing-orders/{id}
# Delete a swap configuration
Source: https://docs.juicyway.com/reference/exchange/delete-a-swap-configuration
/openapi.json delete /exchange/swap-configurations/{id}
# Fetch current market prices
Source: https://docs.juicyway.com/reference/exchange/fetch-current-market-prices
/openapi.json get /exchange/market-prices{symbol}
# Get order book
Source: https://docs.juicyway.com/reference/exchange/get-order-book
/openapi.json get /exchange/books/{symbol}
# Get rate
Source: https://docs.juicyway.com/reference/exchange/get-rate
/openapi.json get /exchange/rates/{id}
# Get swap
Source: https://docs.juicyway.com/reference/exchange/get-swap
/openapi.json get /exchange/swap/{id}
# Get swap rate
Source: https://docs.juicyway.com/reference/exchange/get-swap-rate
/openapi.json get /exchange/swap/rate
# Increase order book liquidity
Source: https://docs.juicyway.com/reference/exchange/increase-order-book-liquidity
/openapi.json post /exchange/increase-liquidity
# List currencies
Source: https://docs.juicyway.com/reference/exchange/list-currencies
/openapi.json get /exchange/currencies
# List market makers
Source: https://docs.juicyway.com/reference/exchange/list-market-makers
/openapi.json get /exchange/market-makers
# List orders
Source: https://docs.juicyway.com/reference/exchange/list-orders
/openapi.json get /exchange/orders
# List rates
Source: https://docs.juicyway.com/reference/exchange/list-rates
/openapi.json get /exchange/rates
# List standing orders
Source: https://docs.juicyway.com/reference/exchange/list-standing-orders
/openapi.json get /exchange/standing-orders
# List supported rates
Source: https://docs.juicyway.com/reference/exchange/list-supported-rates
/openapi.json get /exchange/pairs
# List swap configuration
Source: https://docs.juicyway.com/reference/exchange/list-swap-configuration
/openapi.json get /exchange/swap-configurations
# List swaps
Source: https://docs.juicyway.com/reference/exchange/list-swaps
/openapi.json get /exchange/swap
# Make a swap
Source: https://docs.juicyway.com/reference/exchange/make-a-swap
/openapi.json post /exchange/swap
# Remove contact from a market maker
Source: https://docs.juicyway.com/reference/exchange/remove-contact-from-a-market-maker
/openapi.json patch /exchange/market-makers/{id}/remove-contact
# Retrieve a market maker
Source: https://docs.juicyway.com/reference/exchange/retrieve-a-market-maker
/openapi.json get /exchange/market-makers/{id}
# Retrieve a standing order
Source: https://docs.juicyway.com/reference/exchange/retrieve-a-standing-order
/openapi.json get /exchange/standing-orders/{id}
# Retrieve a swap configuration
Source: https://docs.juicyway.com/reference/exchange/retrieve-a-swap-configuration
/openapi.json get /exchange/swap-configurations/{id}
# Retrieve an order
Source: https://docs.juicyway.com/reference/exchange/retrieve-an-order
/openapi.json get /exchange/orders/{id}
# Retrieve list of orders created from a standing order
Source: https://docs.juicyway.com/reference/exchange/retrieve-list-of-orders-created-from-a-standing-order
/openapi.json get /exchange/standing-orders/{id}/orders
# Retrieve market maker details for current account
Source: https://docs.juicyway.com/reference/exchange/retrieve-market-maker-details-for-current-account
/openapi.json get /exchange/market-makers/me
# Update a market maker
Source: https://docs.juicyway.com/reference/exchange/update-a-market-maker
/openapi.json patch /exchange/market-makers/{id}
# Update a rate
Source: https://docs.juicyway.com/reference/exchange/update-a-rate
/openapi.json patch /exchange/rates/{id}
# Update a standing order
Source: https://docs.juicyway.com/reference/exchange/update-a-standing-order
/openapi.json patch /exchange/standing-orders/{id}
# Update a swap configuration
Source: https://docs.juicyway.com/reference/exchange/update-a-swap-configuration
/openapi.json patch /exchange/swap-configurations/{id}
# Fetch current market prices
Source: https://docs.juicyway.com/reference/orders/fetch-current-market-prices
/openapi.json get /exchange/market-prices
# Authorize a captured payment session
Source: https://docs.juicyway.com/reference/payments/authorize-a-captured-payment-session
/openapi.json post /payment-sessions/{id}/authorize
# Cancel a running payment session
Source: https://docs.juicyway.com/reference/payments/cancel-a-running-payment-session
/openapi.json post /payment-sessions/{id}/cancel
# Capture a payment session
Source: https://docs.juicyway.com/reference/payments/capture-a-payment-session
/openapi.json post /payment-sessions/{id}
# Create a payment link
Source: https://docs.juicyway.com/reference/payments/create-a-payment-link
/openapi.json post /payment-links
# Export payment details
Source: https://docs.juicyway.com/reference/payments/export-payment-details
/openapi.json get /payments/export
# Get a hosted payment session
Source: https://docs.juicyway.com/reference/payments/get-a-hosted-payment-session
/openapi.json get /hosted-sessions/{id}
# Get a payment link
Source: https://docs.juicyway.com/reference/payments/get-a-payment-link
/openapi.json get /payment-links/{id}
# Get a running payment session
Source: https://docs.juicyway.com/reference/payments/get-a-running-payment-session
/openapi.json get /payment-sessions/{id}
# Get encryption key
Source: https://docs.juicyway.com/reference/payments/get-encryption-key
/openapi.json get /payment-sessions/encryption-keys/{mode}
# Get merchant profile
Source: https://docs.juicyway.com/reference/payments/get-merchant-profile
/openapi.json get /merchants/me
# Get merchant profile
Source: https://docs.juicyway.com/reference/payments/get-merchant-profile-1
/openapi.json patch /merchants/me/settings
# Get payment details
Source: https://docs.juicyway.com/reference/payments/get-payment-details
/openapi.json get /payments
# Get payment details
Source: https://docs.juicyway.com/reference/payments/get-payment-details-1
/openapi.json get /payments/{id}
# Get payment stats
Source: https://docs.juicyway.com/reference/payments/get-payment-stats
/openapi.json get /payments/stats
# Initialize a payment session
Source: https://docs.juicyway.com/reference/payments/initialize-a-payment-session
/openapi.json post /payment-sessions
# Initiate a payment refund
Source: https://docs.juicyway.com/reference/payments/initiate-a-payment-refund
/openapi.json post /payments/{id}/refund
# List payment links
Source: https://docs.juicyway.com/reference/payments/list-payment-links
/openapi.json get /payment-links
# Retry the processing of a pending outgoing payment
Source: https://docs.juicyway.com/reference/payments/retry-the-processing-of-a-pending-outgoing-payment
/openapi.json post /payments/retry
# Update a payment link
Source: https://docs.juicyway.com/reference/payments/update-a-payment-link
/openapi.json patch /payment-links/{id}
# Update a pending payment session
Source: https://docs.juicyway.com/reference/payments/update-a-pending-payment-session
/openapi.json patch /payment-sessions/{id}
# Update merchant profile
Source: https://docs.juicyway.com/reference/payments/update-merchant-profile
/openapi.json patch /merchants/me
# Add transfers
Source: https://docs.juicyway.com/reference/payouts/add-transfers
/openapi.json post /bulk-transfers/transfers
# cancel bulk transfer
Source: https://docs.juicyway.com/reference/payouts/cancel-bulk-transfer
/openapi.json post /bulk-transfers/{id}/cancel
# Delete transfers
Source: https://docs.juicyway.com/reference/payouts/delete-transfers
/openapi.json delete /bulk-transfers/{batch_id}/transfers/{id}
# Execute bulk transfer
Source: https://docs.juicyway.com/reference/payouts/execute-bulk-transfer
/openapi.json post /bulk-transfers/{id}/execute
# Generate a payout receipt
Source: https://docs.juicyway.com/reference/payouts/generate-a-payout-receipt
/openapi.json get /payouts/{id}/receipt
# Get bulk payout details
Source: https://docs.juicyway.com/reference/payouts/get-bulk-payout-details
/openapi.json get /bulk-transfers/{id}
# Get charge for a payout
Source: https://docs.juicyway.com/reference/payouts/get-charge-for-a-payout
/openapi.json get /payouts/charge
# Get payout details
Source: https://docs.juicyway.com/reference/payouts/get-payout-details
/openapi.json get /payouts/{id}
# Initiate a bulk transfer
Source: https://docs.juicyway.com/reference/payouts/initiate-a-bulk-transfer
/openapi.json post /bulk-transfers
# Initiate a payout
Source: https://docs.juicyway.com/reference/payouts/initiate-a-payout
/openapi.json post /payouts
# List bulk payouts
Source: https://docs.juicyway.com/reference/payouts/list-bulk-payouts
/openapi.json get /bulk-transfers
# List payouts
Source: https://docs.juicyway.com/reference/payouts/list-payouts
/openapi.json get /payouts
# Retry failed but retryable transfer
Source: https://docs.juicyway.com/reference/payouts/retry-failed-but-retryable-transfer
/openapi.json post /bulk-transfers/{batch_id}/transfers/{id}/retry
# Get aggregator swap rate
Source: https://docs.juicyway.com/reference/swaps/get-aggregator-swap-rate
/openapi.json get /exchange/fx/rate
# Get quote
Source: https://docs.juicyway.com/reference/swaps/get-quote
/openapi.json get /exchange/quote
# Get swap by reference
Source: https://docs.juicyway.com/reference/swaps/get-swap-by-reference
/openapi.json get /exchange/fx/convert/{reference}
# Lock aggregator swap rate
Source: https://docs.juicyway.com/reference/swaps/lock-aggregator-swap-rate
/openapi.json post /exchange/fx/rate/{id}/lock
# Lock quote
Source: https://docs.juicyway.com/reference/swaps/lock-quote
/openapi.json post /exchange/quote/{id}/lock
# Make a swap with a locked aggregator rate
Source: https://docs.juicyway.com/reference/swaps/make-a-swap-with-a-locked-aggregator-rate
/openapi.json post /exchange/fx/convert
# Create a wallet
Source: https://docs.juicyway.com/reference/wallets/create-a-wallet
/openapi.json post /wallets
# Create a wallet payment method
Source: https://docs.juicyway.com/reference/wallets/create-a-wallet-payment-method
/openapi.json post /wallets/{id}/payment-method
# Create a wallet transaction
Source: https://docs.juicyway.com/reference/wallets/create-a-wallet-transaction
/openapi.json post /wallets/transactions
# List transactions
Source: https://docs.juicyway.com/reference/wallets/list-transactions
/openapi.json get /wallets/transactions
# List wallets
Source: https://docs.juicyway.com/reference/wallets/list-wallets
/openapi.json get /wallets/all
# Retrieve a wallet
Source: https://docs.juicyway.com/reference/wallets/retrieve-a-wallet
/openapi.json get /wallets/{id}
# Retrieve a wallet transaction
Source: https://docs.juicyway.com/reference/wallets/retrieve-a-wallet-transaction
/openapi.json get /wallets/transactions/{id}
# Update a wallet status
Source: https://docs.juicyway.com/reference/wallets/update-a-wallet-status
/openapi.json patch /wallets/{id}/status
# Update wallet balance
Source: https://docs.juicyway.com/reference/wallets/update-wallet-balance
/openapi.json patch /wallets/{id}/balance
# Beneficiaries
Source: https://docs.juicyway.com/transfers/beneficiaries
Manage and store transfer recipients for quick, secure payouts
## Overview
Beneficiaries are pre-validated recipients for your transfers. Managing beneficiaries enables you to:
* Store recipient details securely
* Validate account information upfront
* Execute transfers quickly and safely
* Maintain an auditable recipient database
## Supported Beneficiary Types
**Features**
* Multiple currency support
* Account validation
* Local & international transfers
* Automated verification
**Features**
* Multiple chain support
* Address validation
* Network detection
* Chain verification
**Features**
* Email/phone association
* Auto-deposit support
* Canadian accounts only
* Real-time validation
**Coming Soon**
* Multiple providers
* Number validation
* Regional support
* Instant verification
## Beneficiary Information
### Bank Account Beneficiaries
Bank account number
Account holder name
Bank routing/sort code
Account currency (e.g., NGN, USD, CAD)
### Crypto Address Beneficiaries
Wallet address
Blockchain network (ETH, TRX, etc.)
Token currency (USDT, USDC)
### Interac Recipients
Recipient email
First name
Last name
Optional phone number
## Key Operations
Add new transfer recipients with validated details. See [Create Beneficiary](/transfers/beneficiaries/create-beneficiary).
Fetch beneficiary information by ID. See [Fetch Beneficiary](/transfers/beneficiaries/fetch-beneficiary).
Get a paginated list of all beneficiaries. See [List Beneficiaries](/transfers/beneficiaries/list-beneficiaries).
## Validation Rules
* Account numbers must be valid for the specified bank
* Account name must match bank records
* Bank code must be valid for the country
* Currency must be supported for the bank
* Address must be valid for the specified chain
* Chain must support the selected token
* Address checksum verification
* Network compatibility check
* Valid Canadian email format
* Registered for Interac e-Transfer
* Optional phone number in Canadian format
* Name matching verification
## Best Practices
1. **Validation**
* Verify recipient details before creation
* Test transfer with small amounts
* Implement proper error handling
* Monitor validation responses
2. **Security**
* Store beneficiary IDs, not details
* Validate all input data
* Implement access controls
* Monitor for suspicious patterns
3. **Management**
* Regular beneficiary verification
* Clean up unused beneficiaries
* Track failed validations
* Monitor success rates
Learn how to:
* [Create Beneficiaries](/transfers/beneficiaries/create-beneficiary)
* [Fetch Beneficiary Details](/transfers/beneficiaries/fetch-beneficiary)
* [List All Beneficiaries](/transfers/beneficiaries/list-beneficiaries)
# Create Beneficiary
Source: https://docs.juicyway.com/transfers/beneficiaries/create-beneficiary
Create and save beneficiaries for transfers across multiple payment methods
## Overview
The Create Beneficiary endpoint allows you to save recipient information for future transfers. You can create beneficiaries for bank accounts, crypto wallets, and Interac e-Transfer recipients.
Saved beneficiaries can be reused for future transfers without having to
re-enter the recipient details each time.
## Endpoint
```bash theme={null}
POST /beneficiaries
```
## Supported Beneficiary Types
* NGN bank accounts
* USD bank accounts (ACH/Wire)
* International bank accounts
* USDT addresses
* USDC addresses
* Multiple chains such as AVAX, ETH, TRX, DOGE, ADA, SOL are supported
* Canadian recipients via Interac
## Create NGN Bank Account Beneficiary
### Request Parameters
Must be "bank\_account"
Must be "NGN"
Account holder's name as registered with bank
10-digit Nigerian bank account number
Full bank name
Bank's unique code - get from [List
Banks](/transfers/transfers/list-ngn-banks) endpoint
Must be nuban
### Example Request
```json theme={null}
{
"type": "bank_account",
"currency": "NGN",
"account_name": "John Doe",
"account_number": "0123456789",
"bank_name": "First Bank of Nigeria",
"bank_code": "011",
"rail": "nuban"
}
```
## Create USD Bank Account Beneficiary
### Request Parameters
Must be "bank\_account"
Must be "USD"
9-digit ABA routing number
Payment rail to use ("ach" or "wire")
Bank sort code (if required)
Beneficiary's address information
Street addressAdditional address infoCity nameState code2-letter country codeZIP/Postal code
Bank's physical address
Street addressAdditional address infoCity nameState code2-letter country codeZIP/Postal code
### Example Request
```json theme={null}
{
"type": "bank_account",
"currency": "USD",
"routing_number": "123456789",
"rail": "ach",
"sort_code": "123456",
"address": {
"line1": "15 High Road",
"line2": "Unit 12",
"city": "New York",
"state": "NY",
"country": "US",
"zip_code": "10003"
},
"bank_address": {
"line1": "20 Finance Blvd",
"line2": "Suite 200",
"city": "Los Angeles",
"state": "CA",
"country": "US",
"zip_code": "90001"
}
}
```
## Create Interac e-Transfer Beneficiary
### Request Parameters
Must be "interac"
Must be "CAD"
Type of recipient ("personal" or "business")
Recipient's first name
Recipient's last name
Recipient's email registered with Interac
Recipient's phone number (optional)
Security question for manual deposits
Answer to security question
### Example Request
```json theme={null}
{
"type": "interac",
"currency": "CAD",
"beneficiary_type": "personal",
"first_name": "Alice",
"last_name": "Smith",
"email": "alice@example.com",
"question": "What is your pet's name?",
"answer": "Fluffy",
"phone_number": "1234567890"
}
```
## Create Crypto Address Beneficiary
### Request Parameters
Must be "crypto\_address"
Must be one of `USDC`, `USDT`
Multiple chains such as AVAX, ETH, TRX, DOGE, ADA, SOL are supported
Must be a supported crypto address based on the currency and chain
### Example Request
```json theme={null}
{
"type": "crypto_address",
"label": "Test wallet",
"currency": "USDC|USDT",
"chain": "ETH|TRX|DOGE|ADA|SOL|AVAX",
"address": "0x..."
}
```
## Response Format
Created beneficiary details
Unique beneficiary identifier
Beneficiary type
Currency code
For bank accounts: Account holder name
For bank accounts: Account number
For bank accounts: Account type
For bank accounts: Bank name
For bank accounts: Bank code
For USD accounts: ABA routing number
ID of creating user
### Success Response Example
```json theme={null}
{
"data": {
"account_name": "Michael Asaju",
"account_number": "8036120312",
"account_type": "savings",
"address": null,
"bank_address": null,
"bank_code": "100004",
"bank_id": null,
"bank_name": "OPAY",
"bic": null,
"currency": "NGN",
"id": "d71efb6e-b7f5-4acd-a729-3da08e36eaed",
"lifetime": "permanent",
"routing_number": null,
"sort_code": null,
"type": "bank_account",
"user_id": "c545cbc5-9915-4bfb-98ee-3759894feac2",
"virtual": false
}
}
```
## Error Handling
```json theme={null}
{
"error": {
"code": "invalid_request",
"message": "Invalid parameters provided",
"details": {
"account_number": ["Invalid account number format"]
}
}
}
```
```json theme={null}
{
"error": {
"code": "validation_error",
"message": "Invalid beneficiary details",
"details": {
"routing_number": ["Must be 9 digits for US banks"]
}
}
}
```
```json theme={null}
{
"error": {
"code": "duplicate_beneficiary",
"message": "A beneficiary with these details already exists"
}
}
```
## Validation Rules
1. **NGN Bank Accounts**
* Account numbers must be 10 digits
* Bank code must be valid
* Account name must match bank records
2. **USD Bank Accounts**
* Routing numbers must be 9 digits
* Valid US state codes required
* ZIP codes must match state
3. **Interac e-Transfer**
* Valid Canadian email required
* Security question required if auto-deposit not enabled
* Phone number must be Canadian format
For additional assistance:
* Check our [API Reference](/api-reference/overview)
* Contact [Support](mailto:support@juicyway.com)
* Review our [Error Handling Guide](/errors)
# Fetch Beneficiary
Source: https://docs.juicyway.com/transfers/beneficiaries/fetch-beneficiary
Retrieve a Specific Beneficiary
## **Request Parameters**
The following fields are required to retrieve a specific beneficiary:
* **`type`** (Object, Required): Specifies the type of the request object.
* **`after`** (String, Required): A cursor indicating the starting point for pagination.
* **`before`** (String, Required): A cursor indicating the ending point for pagination.
* **`limit`** (Integer, Required): The maximum number of records to return in the response.
* **`user_id`** (String, Required): The unique identifier of the user associated with the beneficiary.
* **`account_id`** (String, Required): The unique identifier of the account associated with the beneficiary.
## Initialization
To retrieve a specific beneficiary, ensure all required fields are included in the request.
```json theme={null}
GET /beneficiaries/{id}
```
**Sample Response**
```json theme={null}
{
"data":{
"account_name": "MICHAEL ENITAN ASAJU",
"account_number": "0821081314",
"account_type": "savings",
"address": {},
"bank_address": {},
"bank_code": "000014",
"bank_id": "",
"bank_name": "ACCESS BANK",
"bic": null,
"currency": "NGN",
"id": "d8c0226b-048c-4c44-9606-a93333f56283",
"lifetime": "permanent",
"routing_number": null,
"sort_code": null,
"type": "bank_account",
"user_id": "c545cbc5-9915-4bfb-98ee-3759894feac2",
"virtual": false
}
}
```
#### Notes
* Ensure the `after` and `before` cursors are correctly formatted to avoid pagination errors.
* The `limit` value must be a positive integer and should not exceed the system's maximum allowed limit.
* The `user_id` and `account_id` must correspond to valid and existing records in the system.
* The response includes detailed information about the beneficiary, such as account details, bank information, and associated metadata.
# List Beneficiaries
Source: https://docs.juicyway.com/transfers/beneficiaries/list-beneficiaries
Retrieve a paginated list of beneficiaries associated with your account.
This endpoint supports filtering and sorting options to help you manage large numbers of beneficiaries efficiently.
```bash theme={null}
GET /beneficiaries
```
## Query Parameters
Number of records to return per page (max: 100)
Cursor for fetching next page of results
Cursor for fetching previous page of results
Filter by currency (e.g., NGN, USD, CAD)
Filter by beneficiary type (e.g., bank\_account, crypto\_address)
## Response Object
Array of beneficiary objects
Unique identifier for the beneficiary
Type of beneficiary (bank\_account, crypto\_address)
Currency code for the beneficiary account
Name on the bank account (for bank\_account type)
Account number (for bank\_account type)
Bank name (for bank\_account type)
Bank identifier code
Whether this is a virtual account
Duration of beneficiary validity
Cursor for the previous page
Cursor for the next page
Current page size
## Examples
### List All Beneficiaries
```bash cURL theme={null}
curl -X GET "https://api.spendjuice.com/beneficiaries?limit=2" \
-H "Authorization: YOUR_API_KEY"
```
```javascript Node.js theme={null}
const response = await fetch(
'https://api.spendjuice.com/beneficiaries?limit=2',
{
headers: {
'Authorization': ' YOUR_API_KEY'
}
}
);
```
```python Python theme={null}
import requests
response = requests.get(
'https://api.spendjuice.com/beneficiaries',
params={'limit': 2},
headers={'Authorization': ' YOUR_API_KEY'}
)
```
### Success Response
```json theme={null}
{
"data": [
{
"account_name": "MICHAEL ENITAN ASAJU",
"account_number": "0821081314",
"account_type": "savings",
"address": null,
"bank_address": null,
"bank_code": "000014",
"bank_id": null,
"bank_name": "ACCESS BANK",
"bic": null,
"currency": "NGN",
"id": "d8c0226b-048c-4c44-9606-a93333f56283",
"lifetime": "permanent",
"routing_number": null,
"sort_code": null,
"type": "bank_account",
"user_id": "c545cbc5-9915-4bfb-98ee-3759894feac2",
"virtual": false
},
{
"account_name": "Michael Asaju",
"account_number": "8036120312",
"account_type": "savings",
"address": null,
"bank_address": null,
"bank_code": "100004",
"bank_id": null,
"bank_name": "OPAY",
"bic": null,
"currency": "NGN",
"id": "d71efb6e-b7f5-4acd-a729-3da08e36eaed",
"lifetime": "permanent",
"routing_number": null,
"sort_code": null,
"type": "bank_account",
"user_id": "c545cbc5-9915-4bfb-98ee-3759894feac2",
"virtual": false
}
],
"pagination": {
"after": "d71efb6e-b7f5-4acd-a729-3da08e36eaed",
"before": null,
"limit": 2
}
}
```
## Pagination
The API uses cursor-based pagination. To fetch subsequent pages:
1. Get the `after` cursor from the pagination object
2. Include it in your next request
3. Repeat until no more `after` cursor is returned
For optimal performance:
* Use reasonable page sizes (15-50 records)
* Cache results when possible
* Implement progressive loading in your UI
## Error Responses
```json theme={null}
{
"error": {
"code": "invalid_request",
"message": "Invalid query parameters",
"details": {
"limit": ["Must be between 1 and 100"]
}
}
}
```
```json theme={null}
{
"error": {
"code": "unauthorized",
"message": "Invalid or missing API key"
}
}
```
## Best Practices
1. **Efficient Filtering**
* Use filters to reduce response size
* Combine filters for precise results
* Cache frequently accessed data
2. **Pagination Handling**
* Store cursors temporarily for navigation
* Implement infinite scroll for large lists
* Show loading states during fetches
3. **Error Handling**
* Implement proper retry logic
* Handle rate limits gracefully
* Log pagination errors
For additional assistance:
* Check our [Error Handling Guide](/errors)
* Contact [Support](mailto:support@juicyway.com)
# Cancel Bulk Transfer
Source: https://docs.juicyway.com/transfers/bulk-transfers/cancel-bulk-transfer
Cancel a pending bulk transfer or individual transfers within a batch
## Overview
The Cancel Bulk Transfer endpoint allows you to stop a pending bulk transfer from being processed. You can cancel the entire batch or specific transfers within it, depending on their current status.
Only bulk transfers in `created` or `executing` status can be cancelled. Completed, expired, or already cancelled transfers cannot be modified.
## Endpoint
```bash theme={null}
POST /bulk-transfers/{id}/cancel
```
## Path Parameters
The unique identifier of the bulk transfer to cancel
## Request Example
```bash cURL theme={null}
curl -X POST "https://api.spendjuice.com/bulk-transfers/7d528558-1c20-4bb6-9a9a-a03c8292b297/cancel" \
-H "Authorization: YOUR_API_KEY"
```
```javascript Node.js theme={null}
const response = await fetch(
'https://api.spendjuice.com/bulk-transfers/7d528558-1c20-4bb6-9a9a-a03c8292b297/cancel',
{
method: 'POST',
headers: {
'Authorization': ' YOUR_API_KEY'
}
}
);
```
```python Python theme={null}
import requests
response = requests.post(
'https://api.spendjuice.com/bulk-transfers/7d528558-1c20-4bb6-9a9a-a03c8292b297/cancel',
headers={'Authorization': ' YOUR_API_KEY'}
)
```
## Response Examples
```json 200 Success theme={null}
{
"data": {
"created_at": "2024-10-02T17:39:26.049258",
"description": "Monthly Vendor Payments",
"expires_at": "2024-10-03T17:39:25Z",
"failed_transfer_count": 0,
"id": "7d528558-1c20-4bb6-9a9a-a03c8292b297",
"items": [],
"metadata": {},
"owner": {
"id": "65fb1bf9-10e7-4556-8005-0c3249b8df36",
"type": "personal"
},
"reference": "46f3ef38-22de-4498-a6d3-13749aa2a0a7",
"status": "cancelled",
"successful_transfer_count": 0,
"total_transfer_count": 0,
"updated_at": "2024-10-02T17:39:26Z"
}
}
```
```json 404 Not Found theme={null}
{
"error": {
"code": "bulk_transfer_not_found",
"message": "No bulk transfer found with ID: 7d528558-1c20-4bb6-9a9a-a03c8292b297"
}
}
```
```json 409 Conflict theme={null}
{
"error": {
"code": "invalid_state",
"message": "Bulk transfer cannot be cancelled in its current state"
}
}
```
## Status Transitions
When you cancel a bulk transfer:
1. Status changes from `created`/`executing` to `cancelled`
2. All pending transfers are marked as `cancelled`
3. In-progress transfers complete normally
4. Completed transfers remain unchanged
## Webhook Events
Monitor these events for cancellation status:
Fired when the bulk transfer is successfully cancelled
```json theme={null}
{
"event": "bulk_transfer.cancelled",
"data": {
"id": "7d528558-1c20-4bb6-9a9a-a03c8292b297",
"status": "cancelled",
"cancelled_at": "2024-10-02T18:00:00Z",
"cancelled_transfers": 5,
"completed_transfers": 2
}
}
```
Fired for each cancelled transfer in the batch
```json theme={null}
{
"event": "bulk_transfer.transfer.cancelled",
"data": {
"bulk_transfer_id": "7d528558-1c20-4bb6-9a9a-a03c8292b297",
"transfer_id": "tr_123abc",
"status": "cancelled",
"cancelled_at": "2024-10-02T18:00:00Z"
}
}
```
## Error Handling
The specified bulk transfer doesn't exist
* Verify the bulk transfer ID
* Check the ID format
Transfer cannot be cancelled in current state
* Only created/executing transfers can be cancelled
* Check current transfer status
Some transfers could not be cancelled
* In-progress transfers will complete
* Check individual transfer statuses
## Refund Handling
For transfers that require refunds:
1. Successfully cancelled transfers are automatically reversed
2. Funds are returned to your balance
3. Refund status is tracked via webhooks
4. Processing time varies by payment method
Some payment methods may have specific refund restrictions or processing times.
## Best Practices
1. **Pre-cancellation Checks**
* Verify bulk transfer status
* Check for in-progress transfers
* Consider timing of cancellation
2. **Monitoring**
* Implement webhook handling
* Track cancellation status
* Monitor refund processing
3. **Error Handling**
* Handle partial cancellations
* Implement retry logic
* Log cancellation attempts
For additional assistance:
* Review [Error Handling Guide](/errors)
* Contact [Support](mailto:support@juicyway.com)
* Check [Webhook Documentation](/webhooks)
# Delete from Bulk Transfer
Source: https://docs.juicyway.com/transfers/bulk-transfers/delete-bulk-transfer
Remove individual transfers from a bulk transfer batch before execution
## Overview
The Delete Transfer endpoint allows you to remove individual transfers from a bulk transfer batch that hasn't been executed. This is useful for correcting errors or removing unnecessary transfers before batch execution.
You can only delete transfers from batches that are in the `created` status. Once a batch is executing or completed, transfers cannot be deleted.
## Endpoint
```bash theme={null}
DELETE /bulk-transfers/{batch_id}/transfers/{id}
```
## Path Parameters
The unique identifier of the bulk transfer batch
* Must be a valid UUID
* Batch must be in `created` status
The unique identifier of the transfer to delete
* Must be a valid UUID
* Transfer must be part of the specified batch
## Request Example
```bash cURL theme={null}
curl -X DELETE "https://api.spendjuice.com/bulk-transfers/88dbcb86-5025-4ac9-9750-4aa5a77a723c/transfers/e2df31d2-828e-11ef-8f08-acde48001122" \
-H "Authorization: YOUR_API_KEY"
```
```javascript Node.js theme={null}
const response = await fetch(
'https://api.spendjuice.com/bulk-transfers/88dbcb86-5025-4ac9-9750-4aa5a77a723c/transfers/e2df31d2-828e-11ef-8f08-acde48001122',
{
method: 'DELETE',
headers: {
'Authorization': ' YOUR_API_KEY'
}
}
);
```
```python Python theme={null}
import requests
response = requests.delete(
'https://api.spendjuice.com/bulk-transfers/88dbcb86-5025-4ac9-9750-4aa5a77a723c/transfers/e2df31d2-828e-11ef-8f08-acde48001122',
headers={'Authorization': ' YOUR_API_KEY'}
)
```
## Response
A successful delete operation returns an HTTP 204 (No Content) response with no response body.
## Error Responses
```json theme={null}
{
"error": {
"code": "invalid_request",
"message": "Invalid batch or transfer ID format"
}
}
```
```json theme={null}
{
"error": {
"code": "not_found",
"message": "Transfer or batch not found"
}
}
```
```json theme={null}
{
"error": {
"code": "invalid_state",
"message": "Cannot delete transfer from batch in current status"
}
}
```
## Validation Rules
1. **Batch Status**
* Only transfers in batches with `created` status can be deleted
* Deletion blocked if batch is executing/completed
* Batch must belong to your account
2. **Transfer Requirements**
* Transfer must exist in the specified batch
* Transfer must not be in processing state
* Transfer ID must be valid format
## Status Impact
Deleting a transfer:
* Reduces the batch's total transfer count
* Updates batch metadata
* Cannot be undone - requires re-adding if needed
* Does not affect other transfers in the batch
## Best Practices
1. **Validation**
* Verify batch and transfer status before deletion
* Handle expected error cases gracefully
* Log deletion attempts for audit purposes
2. **Error Handling**
* Implement retry logic for network errors
* Show clear error messages to users
* Monitor deletion success rates
3. **Security**
* Validate user permissions
* Log all deletion operations
* Implement rate limiting
* Use HTTPS for all requests
For additional assistance:
* Check our [Error Handling Guide](/errors)
* Review [Bulk Transfer Overview](/transfers/bulk-transfers/overview)
* Contact [Support](mailto:support@juicyway.com)
# Execute Bulk Transfer
Source: https://docs.juicyway.com/transfers/bulk-transfers/execute-bulk-transfer
Execute a prepared bulk transfer by triggering the payment process for all included transfers
## Overview
The Execute Bulk Transfer endpoint initiates the processing of all transfers within a prepared bulk transfer batch. This operation transitions the bulk transfer from `created` status to `executing` and begins processing individual transfers.
Before executing a bulk transfer:
1. Ensure all transfer details are correct
2. Verify sufficient balance for all transfers
3. Check that the bulk transfer hasn't expired
4. Confirm no validation errors in transfer items
## Endpoint
```http theme={null}
POST /bulk-transfers/{id}/execute
```
### Path Parameters
The unique identifier of the bulk transfer to execute
* Must be in `created` status
* Must not be expired
* Must have at least one valid transfer
## Prerequisites
Before execution can begin:
* All transfers must have valid beneficiary details
* Total transfer amount must not exceed your limits
* Your account must have sufficient balance
* The bulk transfer must not be expired
* No pending validation issues
## Example Request
```bash cURL theme={null}
curl -X POST "https://api.spendjuice.com/bulk-transfers/7d528558-1c20-4bb6-9a9a-a03c8292b297/execute" \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json"
```
```javascript Node.js theme={null}
const response = await fetch(
'https://api.spendjuice.com/bulk-transfers/7d528558-1c20-4bb6-9a9a-a03c8292b297/execute',
{
method: 'POST',
headers: {
'Authorization': ' YOUR_API_KEY',
'Content-Type': 'application/json'
}
}
);
```
```python Python theme={null}
import requests
response = requests.post(
'https://api.spendjuice.com/bulk-transfers/7d528558-1c20-4bb6-9a9a-a03c8292b297/execute',
headers={
'Authorization': ' YOUR_API_KEY',
'Content-Type': 'application/json'
}
)
```
## Response Format
### Success Response (202 Accepted)
```json theme={null}
{
"data": {
"id": "7d528558-1c20-4bb6-9a9a-a03c8292b297",
"status": "executing",
"total_transfer_count": 10,
"successful_transfer_count": 0,
"failed_transfer_count": 0,
"created_at": "2024-03-15T10:30:00Z",
"updated_at": "2024-03-15T10:35:00Z",
"execution_started_at": "2024-03-15T10:35:00Z"
}
}
```
## Status Transitions
When a bulk transfer is executed, it goes through these status changes:
Initial transition when execution begins
All transfers processed successfully
Some transfers succeeded, some failed
All transfers failed to process
## Webhook Events
Monitor these webhook events for bulk transfer status:
Triggered when execution begins
```json theme={null}
{
"event": "bulk_transfer.executing",
"data": {
"id": "7d528558-1c20-4bb6-9a9a-a03c8292b297",
"status": "executing",
"total_transfer_count": 10
}
}
```
Triggered when all transfers complete successfully
```json theme={null}
{
"event": "bulk_transfer.completed",
"data": {
"id": "7d528558-1c20-4bb6-9a9a-a03c8292b297",
"status": "completed",
"successful_transfer_count": 10,
"failed_transfer_count": 0
}
}
```
Triggered if execution fails
```json theme={null}
{
"event": "bulk_transfer.failed",
"data": {
"id": "7d528558-1c20-4bb6-9a9a-a03c8292b297",
"status": "failed",
"error": {
"code": "insufficient_balance",
"message": "Insufficient balance for transfer"
}
}
}
```
## Error Handling
Bulk transfer is not in executable state
* Status code: 400
* Must be in `created` status
Insufficient balance for transfers
* Status code: 400
* Check available balance
Bulk transfer has expired
* Status code: 400
* Create new bulk transfer
One or more transfers invalid
* Status code: 422
* Fix validation issues first
## Rate Limits
Bulk transfer execution is subject to these limits:
* Maximum 1 execution request per bulk transfer
* Maximum 100 transfers per bulk transfer
* Maximum 10 concurrent executing bulk transfers
## Best Practices
1. **Pre-execution Validation**
* Verify all beneficiary details
* Check sufficient balance
* Validate transfer amounts
* Monitor expiration time
2. **Error Handling**
* Implement webhook handling
* Monitor individual transfer status
* Handle partial completions
* Log execution attempts
3. **Monitoring**
* Track execution progress
* Monitor success rates
* Set up alerts for failures
* Review execution logs
For additional assistance:
* Check our [Webhooks Guide](/webhooks)
* Review [Error Handling](/errors)
* Contact [Support](mailto:support@juicyway.com)
# Get Bulk Transfer Details
Source: https://docs.juicyway.com/transfers/bulk-transfers/get-bulk-transfer-details
Retrieve detailed information about a specific bulk transfer including its status, items, and execution results
## Overview
The Get Bulk Transfer Details endpoint allows you to retrieve comprehensive information about a specific bulk transfer including its current status, all included transfers, success/failure counts, and execution results.
## Endpoint
```bash theme={null}
GET /bulk-transfers/{id}
```
## Path Parameters
The unique identifier of the bulk transfer to retrieve
* Format: UUID v4
* Example: `7d528558-1c20-4bb6-9a9a-a03c8292b297`
## Response Format
Unique identifier for the bulk transfer
User-provided description of the bulk transfer
Current status of the bulk transfer. One of:
* `created` - Initial state
* `executing` - Transfers in progress
* `completed` - All transfers processed
* `cancelled` - Manually cancelled
* `expired` - Past expiration date
ISO 8601 timestamp of creation
ISO 8601 timestamp of last update
ISO 8601 timestamp when transfer expires
Optional additional data for the bulk transfer
Details about the transfer owner
Owner's unique identifier
Owner type (e.g., "personal", "business")
Array of individual transfers in this batch
Your unique reference for this bulk transfer
Total number of transfers in the batch
Number of successfully completed transfers
Number of failed transfers
## Example Request
```bash cURL theme={null}
curl -X GET "https://payout-staging.spendjuice.com/v1/bulk-transfers/7d528558-1c20-4bb6-9a9a-a03c8292b297" \
-H "Authorization: YOUR_API_KEY"
```
```javascript Node.js theme={null}
const response = await fetch(
'https://payout-staging.spendjuice.com/v1/bulk-transfers/7d528558-1c20-4bb6-9a9a-a03c8292b297',
{
headers: {
'Authorization': ' YOUR_API_KEY'
}
}
);
```
```python Python theme={null}
import requests
response = requests.get(
'https://payout-staging.spendjuice.com/v1/bulk-transfers/7d528558-1c20-4bb6-9a9a-a03c8292b297',
headers={'Authorization': ' YOUR_API_KEY'}
)
```
## Response Examples
```json 200 Success theme={null}
{
"data": {
"created_at": "2024-10-02T17:39:26.049258",
"description": "October Vendor Payments",
"expires_at": "2024-10-03T17:39:25Z",
"failed_transfer_count": 0,
"id": "7d528558-1c20-4bb6-9a9a-a03c8292b297",
"items": [
{
"amount": 100000,
"beneficiary": {
"account_name": "ACME Corp",
"account_number": "0123456789",
"bank_name": "Example Bank"
},
"status": "pending",
"created_at": "2024-10-02T17:39:26Z",
"reference": "vendor_payment_123"
}
],
"metadata": {
"department": "finance",
"batch_id": "OCT2024_001"
},
"owner": {
"id": "65fb1bf9-10e7-4556-8005-0c3249b8df36",
"type": "business"
},
"reference": "46f3ef38-22de-4498-a6d3-13749aa2a0a7",
"status": "created",
"successful_transfer_count": 0,
"total_transfer_count": 1,
"updated_at": "2024-10-02T17:39:26Z"
}
}
```
```json 404 Not Found theme={null}
{
"error": {
"code": "bulk_transfer_not_found",
"message": "Bulk transfer not found",
"type": "not_found_error"
}
}
```
```json 401 Unauthorized theme={null}
{
"error": {
"code": "unauthorized",
"message": "Invalid or expired API key",
"type": "authentication_error"
}
}
```
## Status Lifecycle
Bulk transfers progress through the following states:
Initial state after creation
* Transfers validated but not executed
* Can be modified or cancelled
Transfers being processed
* Individual transfers updating
* Cannot be modified
* Can be cancelled
All transfers processed
* Final success/failure counts available
* Cannot be modified or cancelled
Manually cancelled
* Incomplete transfers stopped
* Cannot be restarted
Past expiration date
* Not executed
* Cannot be modified or executed
## Error Handling
* Invalid API key provided
* API key expired or revoked
* Missing authorization header
* Insufficient permissions
* API key doesn't have access
* Account restrictions
* Invalid bulk transfer ID
* Transfer deleted
* Transfer not accessible
* Temporary service disruption
* Retry with exponential backoff
* Contact support if persistent
## Rate Limits
This endpoint has the following rate limits:
* 120 requests per minute per API key
* Burst limit: 20 requests per second
* Headers included:
* X-RateLimit-Limit
* X-RateLimit-Remaining
* X-RateLimit-Reset
## Best Practices
1. **Monitoring**
* Poll sparingly during execution
* Use webhooks for status updates
* Monitor failed transfers
* Track execution progress
2. **Error Handling**
* Implement exponential backoff
* Handle rate limits gracefully
* Log all request failures
* Set appropriate timeouts
3. **Response Processing**
* Cache stable responses
* Track status changes
* Monitor success rates
* Alert on high failure rates
For additional assistance:
* Check our [Error Handling Guide](/errors)
* Review [Webhook Implementation](/webhooks)
* Contact [support@juicyway.com](mailto:support@juicyway.com)
# Initiate Bulk Transfer
Source: https://docs.juicyway.com/transfers/bulk-transfers/initiate-bulk-transfers
Create a new bulk transfer session for processing multiple transfers efficiently
## Overview
Bulk transfers allow you to process multiple transfers in a single batch operation. This endpoint creates a new bulk transfer session that you can later populate with individual transfers and execute as a group.
Before initiating a bulk transfer:
* Ensure sufficient balance for the expected total
* Have your beneficiary details ready
* Review the transfer limits and cut-off times
## Endpoint
```bash theme={null}
POST /bulk-transfers
```
## Request Parameters
* Maximum length: 200 characters
* Used for reference and reporting
Timestamp when the bulk transfer session expires
* Format: ISO 8601 (e.g., "2024-10-03T18:38:31Z")
* Maximum: 72 hours from creation
* Default: 24 hours from creation
Your unique reference for this bulk transfer
* Must be unique across all bulk transfers
* Maximum length: 64 characters
* Alphanumeric characters, hyphens, and underscores only
Additional data about the bulk transfer
* Maximum size: 20KB
* Key-value pairs of strings
## Request Examples
```json Basic Request theme={null}
{
"description": "Monthly vendor payments",
"expires_at": "2024-10-03T18:38:31Z",
"reference": "juice-bulk-transfer-5d906f6d-933b-4de9-927f-c7522823f5ec"
}
```
```json With Metadata theme={null}
{
"description": "Q4 contractor payments",
"expires_at": "2024-10-03T18:38:31Z",
"reference": "juice-bulk-q4-contractors-2024",
"metadata": {
"department": "engineering",
"batch_type": "contractors",
"period": "Q4-2024"
}
}
```
## Response Format
Created bulk transfer session details
Unique identifier for the bulk transfer
Creation timestamp in ISO 8601 format
Expiration timestamp in ISO 8601 format
Provided description
Current status of the bulk transfer:
* created - Initial state
* executing - Transfers in progress
* completed - All transfers processed
* cancelled - Manually cancelled
* expired - Session timeout
Number of failed transfers in the batch
Number of successful transfers in the batch
Total number of transfers in the batch
List of individual transfers (empty on creation)
Additional metadata provided
Details about the creating entity
## Response Examples
```json 201 Created theme={null}
{
"data": {
"created_at": "2024-10-02T17:39:26.049258Z",
"description": "Monthly vendor payments",
"expires_at": "2024-10-03T18:38:31Z",
"failed_transfer_count": 0,
"id": "7d528558-1c20-4bb6-9a9a-a03c8292b297",
"items": [],
"metadata": {},
"owner": {
"id": "65fb1bf9-10e7-4556-8005-0c3249b8df36",
"type": "personal"
},
"reference": "juice-bulk-transfer-5d906f6d-933b-4de9-927f-c7522823f5ec",
"status": "created",
"successful_transfer_count": 0,
"total_transfer_count": 0,
"updated_at": "2024-10-02T17:39:26Z"
}
}
```
```json 400 Invalid Request theme={null}
{
"error": {
"code": "invalid_request",
"message": "The request contains invalid parameters",
"details": {
"reference": ["Must be unique across all bulk transfers"]
}
}
}
```
```json 422 Validation Error theme={null}
{
"error": {
"code": "validation_error",
"message": "Invalid expiration time",
"details": {
"expires_at": ["Must be between 1 and 72 hours from now"]
}
}
}
```
## Validation Rules
* Must be unique across all bulk transfers
* Length: 1-64 characters
* Allowed characters: A-Z, a-z, 0-9, -, \_
* Cannot start or end with hyphen/underscore
* Must be in future
* Minimum: 1 hour from creation
* Maximum: 72 hours from creation
* Must be valid ISO 8601 format
* Maximum length: 200 characters
* Cannot contain HTML or special characters
* Optional but recommended for tracking
* Maximum size: 20KB
* Keys must be strings
* Values must be strings
* No nested objects allowed
## Rate Limits
* 10 bulk transfer initiations per minute
* Maximum of 100 transfers per batch
* Burst limit: 2 requests per second
## Best Practices
1. **Reference Generation**
* Use structured, meaningful references
* Include date/time components
* Add batch type identifiers
* Store references for reconciliation
2. **Error Handling**
* Implement proper retry logic
* Monitor rate limits
* Log all attempts
* Handle timeouts gracefully
3. **Session Management**
* Set reasonable expiration times
* Plan for session timeouts
* Monitor session status
* Handle expired sessions
After creating a bulk transfer session:
1. [Add transfers](/transfers/bulk-transfers/update-bulk-transfer) to the batch
2. [Execute the bulk transfer](/transfers/bulk-transfers/execute-bulk-transfer)
3. [Monitor status](/transfers/bulk-transfers/get-bulk-transfer-details)
# List bulk transfers
Source: https://docs.juicyway.com/transfers/bulk-transfers/list-bulk-transfers
# List Bulk Transfers
Retrieve a paginated list of bulk transfers with support for filtering, sorting, and status tracking. This endpoint returns all bulk transfers associated with your account in chronological order.
## Endpoint
```bash theme={null}
GET /bulk-transfers
```
## Query Parameters
Filter transfers by their current status:
* `created` - Initialized but not executed
* `executing` - Currently processing
* `cancelled` - Manually cancelled
* `expired` - Past execution window
* `completed` - All transfers processed
Cursor for fetching next page of results
* Use value from `pagination.after` in previous response
Cursor for fetching previous page of results
* Use value from `pagination.before` in previous response
Number of records to return per page
* Minimum: 1
* Maximum: 100
* Default: 10
## Response Format
Array of bulk transfer objects
Unique identifier for the bulk transfer
Optional description of the bulk transfer
Your unique reference for the bulk transfer
Current status of the bulk transfer
Total number of transfers in the batch
Number of successfully completed transfers
Number of failed transfers
ISO-8601 timestamp when the bulk transfer expires
ISO-8601 timestamp of creation
ISO-8601 timestamp of last update
Additional metadata about the transfer
Cursor for the previous page
Cursor for the next page
Number of records per page
## Example Request
```bash cURL theme={null}
curl -X GET "https://payout-staging.spendjuice.com/v1/bulk-transfers?limit=10" \
-H "Authorization: YOUR_API_KEY"
```
```javascript Node.js theme={null}
const response = await fetch(
'https://payout-staging.spendjuice.com/v1/bulk-transfers?limit=10',
{
headers: {
'Authorization': ' YOUR_API_KEY'
}
}
);
```
```python Python theme={null}
import requests
response = requests.get(
'https://payout-staging.spendjuice.com/v1/bulk-transfers',
params={'limit': 10},
headers={'Authorization': ' YOUR_API_KEY'}
)
```
## Response Examples
```json 200 Success theme={null}
{
"data": [
{
"created_at": "2024-10-02T17:39:26.049258",
"description": "October Vendor Payments",
"expires_at": "2024-10-03T17:39:25Z",
"failed_transfer_count": 0,
"id": "7d528558-1c20-4bb6-9a9a-a03c8292b297",
"items": [],
"metadata": {},
"owner": {
"id": "65fb1bf9-10e7-4556-8005-0c3249b8df36",
"type": "personal"
},
"reference": "oct_2024_vendors",
"status": "created",
"successful_transfer_count": 0,
"total_transfer_count": 0,
"updated_at": "2024-10-02T17:39:26Z"
}
],
"pagination": {
"after": "b101f718-d133-450c-a572-c281c7341803",
"before": null,
"limit": 10
}
}
```
```json 400 Invalid Parameters theme={null}
{
"error": {
"code": "invalid_request",
"message": "Invalid query parameters",
"details": {
"limit": ["Must be between 1 and 100"]
}
}
}
```
## Error Handling
Occurs when:
* Invalid status value provided
* Limit outside allowed range
* Invalid cursor format
Occurs when:
* Missing API key
* Invalid API key
* Expired API key
Occurs when:
* Insufficient permissions
* Account restrictions
## Pagination
The API uses cursor-based pagination for reliable list operations:
1. Initial request: Specify desired `limit`
2. Subsequent requests: Use the `after` cursor from previous response
3. Previous page: Use the `before` cursor if available
For optimal performance:
* Use reasonable page sizes (10-50 records)
* Cache results when appropriate
* Implement progressive loading in your UI
## Rate Limits
This endpoint has the following rate limits:
* 100 requests per minute per API key
* Maximum of 1000 requests per hour
* Burst limit: 20 requests per second
## Best Practices
1. **Efficient Filtering**
* Use status filters to reduce response size
* Combine filters for precise results
* Cache frequently accessed data
2. **Pagination Handling**
* Store cursors temporarily for navigation
* Implement infinite scroll for large lists
* Show loading states during fetches
3. **Error Handling**
* Implement proper retry logic
* Handle rate limits gracefully
* Log pagination errors
4. **Performance**
* Use appropriate page sizes
* Cache responses when possible
* Monitor API response times
For additional assistance:
* Check our [Error Handling Guide](/errors)
* Review [Pagination Best Practices](/api-overview/pagination)
* Contact [Support](mailto:support@juicyway.com)
# Retry Transfer
Source: https://docs.juicyway.com/transfers/bulk-transfers/retry-transfer
Retry a previously failed transfer within a bulk transfer batch
## Overview
The retry endpoint allows you to reattempt a failed transfer that is marked as retriable within a bulk transfer batch. This is useful when transfers fail due to temporary issues like network problems or bank system downtime.
Only transfers with `retryable: true` in their status can be retried. Non-retriable failures (like invalid account numbers) cannot be retried.
## Endpoint
```bash theme={null}
POST /bulk-transfers/{batch_id}/transfers/{id}/retry
```
### Path Parameters
The unique identifier of the bulk transfer batch
The unique identifier of the failed transfer to retry
## Example Request
```bash cURL theme={null}
curl -X POST "https://api.spendjuice.com/bulk-transfers/{batch_id}/transfers/{id}/retry" \
-H "Authorization: YOUR_API_KEY"
```
```javascript Node.js theme={null}
const response = await fetch(
`https://api.spendjuice.com/bulk-transfers/${batchId}/transfers/${transferId}/retry`,
{
method: 'POST',
headers: {
'Authorization': ` ${apiKey}`
}
}
);
```
```python Python theme={null}
import requests
response = requests.post(
f'https://api.spendjuice.com/bulk-transfers/{batch_id}/transfers/{transfer_id}/retry',
headers={'Authorization': f' {api_key}'}
)
```
## Response
Retry request accepted successfully
## Error Responses
```json theme={null}
{
"error": {
"code": "transfer_not_found",
"message": "No transfer found with the provided ID"
}
}
```
```json theme={null}
{
"error": {
"code": "not_retriable",
"message": "This transfer cannot be retried"
}
}
```
```json theme={null}
{
"error": {
"code": "retry_in_progress",
"message": "Transfer is already being retried"
}
}
```
## Retry Limits
* Maximum 3 retry attempts per transfer
* 5-minute wait period between retries
* 24-hour maximum retry window from initial failure
* Retries count towards daily transfer limits
## Status Transitions
1. Initial failed status: `failed` with `retryable: true`
2. After retry request: `processing`
3. Final status:
* Success: `succeeded`
* Failure: `failed` (may be retriable again)
## Webhook Events
Monitor these events for retry status:
* `bulk.transfer.retry.started` - Retry attempt initiated
* `bulk.transfer.retry.succeeded` - Retry completed successfully
* `bulk.transfer.retry.failed` - Retry attempt failed
## Best Practices
1. **Retry Strategy**
* Implement exponential backoff between retries
* Track retry attempt count
* Consider time of day for retries
* Monitor success rates by failure reason
2. **Error Handling**
* Log all retry attempts
* Track retry outcomes
* Handle webhook notifications
* Monitor retry limits
3. **User Communication**
* Notify users of retry status
* Provide clear error messages
* Suggest alternative actions for non-retriable failures
* Set expectations for processing time
For retry-related assistance:
* Check our [Error Handling](/errors) guide
* Contact [Support](mailto:support@juicyway.com)
* Review [Webhook Events](/webhooks)
# Update Bulk Transfer
Source: https://docs.juicyway.com/transfers/bulk-transfers/update-bulk-transfer
Add or modify transfers within an existing bulk transfer batch
## Overview
The Update Bulk Transfer endpoint allows you to add transfers to an existing bulk transfer batch. Use this endpoint to populate your bulk transfer with individual payment instructions before execution.
Before adding transfers:
* Ensure the bulk transfer is in `created` status
* Verify the batch hasn't expired
* Check that you haven't exceeded maximum transfer limits
## Endpoint
```http theme={null}
POST /bulk-transfers/{id}/transfers
```
## Request Parameters
The unique identifier of the bulk transfer to update
Array of transfer items to add to the batch
Transfer amount in smallest currency unit (e.g., cents)
Beneficiary payment details
Name on the beneficiary account
Account number for the beneficiary
Bank identifier code
Name of the beneficiary bank
Bank routing number (required for US transfers)
Type of beneficiary account (e.g., "bank\_account")
Three-letter currency code
Whether to save beneficiary for future use
Currency code for the source amount
Currency code for the destination amount
Unique reference for this transfer
Description or reason for the transfer
## Example Request
```bash cURL theme={null}
curl -X POST "https://api.spendjuice.com/bulk-transfers/88dbcb86-5025-4ac9-9750-4aa5a77a723c/transfers" \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"items": [
{
"amount": 100000,
"beneficiary": {
"account_name": "Rodrigo Kerluke",
"account_number": "1111111111",
"bank_code": "101",
"bank_name": "McKenzie Bank",
"routing_number": "111000038",
"type": "bank_account",
"currency": "USD",
"save_beneficiary": true
},
"destination_currency": "USD",
"source_currency": "USD",
"reference": "transfer-ref-001",
"reason": "Monthly salary payment"
}
]
}'
```
```javascript Node.js theme={null}
const response = await fetch(
'https://api.spendjuice.com/bulk-transfers/88dbcb86-5025-4ac9-9750-4aa5a77a723c/transfers',
{
method: 'POST',
headers: {
'Authorization': ' YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
items: [
{
amount: 100000,
beneficiary: {
account_name: "Rodrigo Kerluke",
account_number: "1111111111",
bank_code: "101",
bank_name: "McKenzie Bank",
routing_number: "111000038",
type: "bank_account",
currency: "USD",
save_beneficiary: true
},
destination_currency: "USD",
source_currency: "USD",
reference: "transfer-ref-001",
reason: "Monthly salary payment"
}
]
})
}
);
```
```python Python theme={null}
import requests
response = requests.post(
'https://api.spendjuice.com/bulk-transfers/88dbcb86-5025-4ac9-9750-4aa5a77a723c/transfers',
headers={
'Authorization': ' YOUR_API_KEY',
'Content-Type': 'application/json'
},
json={
'items': [{
'amount': 100000,
'beneficiary': {
'account_name': 'Rodrigo Kerluke',
'account_number': '1111111111',
'bank_code': '101',
'bank_name': 'McKenzie Bank',
'routing_number': '111000038',
'type': 'bank_account',
'currency': 'USD',
'save_beneficiary': True
},
'destination_currency': 'USD',
'source_currency': 'USD',
'reference': 'transfer-ref-001',
'reason': 'Monthly salary payment'
}]
}
)
```
## Response Format
Array of created transfer items
Unique identifier for the transfer
ID of the parent bulk transfer
Current status of the transfer:
* created - Initial state
* processing - Transfer in progress
* completed - Successfully processed
* failed - Processing failed
Creation timestamp (ISO 8601)
Last update timestamp (ISO 8601)
Amount and currency of the transfer
Converted amount and currency (if applicable)
Exchange rate used (if applicable)
## Validation Rules
* Maximum 100 transfers per batch
* Minimum amount: \$1 equivalent
* Maximum amount: Based on account tier
* Must be unique within the batch
* Maximum length: 64 characters
* Alphanumeric characters, hyphens, and underscores only
* Must be valid ISO currency codes
* Source currency must match account currency
* Currency conversion fees may apply
## Error Handling
Bulk transfer is not in editable state
* Status code: 400
* Must be in `created` status
Maximum number of transfers reached
* Status code: 400
* Remove existing transfers first
Invalid transfer parameters
* Status code: 422
* Check error details for specific fields
## Best Practices
1. **Batch Organization**
* Group similar transfers together
* Use consistent currencies when possible
* Include clear references and descriptions
* Validate beneficiary details before adding
2. **Error Management**
* Implement proper error handling
* Validate transfers before submission
* Keep track of failed additions
* Retry failed transfers with corrected data
3. **Performance**
* Add transfers in reasonable batch sizes
* Monitor rate limits
* Handle timeouts appropriately
* Log all operations
After adding transfers:
* [Review the bulk transfer](/transfers/bulk-transfers/get-bulk-transfer-details)
* [Execute the transfers](/transfers/bulk-transfers/execute-bulk-transfer)
* Monitor progress via webhooks
# Transfers Overview
Source: https://docs.juicyway.com/transfers/overview
Initiate and manage fund transfers across multiple payment methods and currencies
## Introduction
The Transfers API enables secure movement of funds between accounts using various payment methods. Whether you're sending payments to vendors, paying out to customers, or managing internal transfers, our flexible API supports both domestic and international transactions.
## Transfer Types
Send money to beneficiaries:
* Vendor payments
* Customer refunds
* Payroll disbursements
* Business expenses
Move funds between accounts:
* Currency conversions
* Balance management
* Account consolidation
* Settlement transfers
## Supported Payment Methods
**Features**
* Direct bank deposits
* Real-time transfers (where available)
* Automated account validation
**Supported Regions**
* Nigeria (NGN transfers)
* Canada (Interac)
**Processing Times**
* NGN transfers:Almost Immediate
* Interac (Canada): Almost Immediate
**Transaction Limits**
* NGN: ₦100 - ₦99,900,000 per transaction
* CAD Interac: C5-C25,000 per transaction
**Supported Tokens & Networks**
* USDT: Ethereum (ETH), Tron (TRX), BNB Smart Chain (BSC)
* USDC: Ethereum (ETH), Polygon (MATIC), Avalanche (AVAXC)
**Features**
* Multi-chain support
* Low transaction fees
* Fast settlement times
* Cross-border capability
**Processing Times**
* TRX Network: 1-3 minutes (6 confirmations)
* ETH Network: 5-30 minutes (12 confirmations)
* MATIC Network: 1-5 minutes (15 confirmations)
* AVAXC Network: 1-5 minutes (15 confirmations)
**Transaction Limits**
* Minimum: 10 USDT/USDC
* Maximum: 100,000 USDT/USDC per transaction
* Daily Limit: 500,000 USDT/USDC
**Network Fees**
* TRX: \~1 USDT
* ETH: Variable (gas fees)
* MATIC: \~0.1 USDC
* AVAXC: \~0.1 USDC
**Features**
* Email money transfers
* Real-time notifications
* Automated deposits
* Canadian bank support
**Requirements**
* Canadian bank account
* Valid email/phone
* Account verification
**Processing Times**
* Standard Transfer: 15-30 minutes
* Auto-deposit: 5-15 minutes
* After-hours: Next business day
* Failed transfer reversals: 3-5 business days
**Transaction Limits**
* Minimum: C\$100
* Maximum: C\$10,000 per transaction
* Daily Limit: C\$20,000
* 7-day Limit: C\$70,000
## Currency Support & Exchange
* Local bank transfers
* Real-time payments
* Account validation
* Daily Limit: ₦100,000,000
* Interac e-Transfer
* EFT payments
* Wire transfers
* Daily Limit: C\$100,000
## Key Concepts
### Beneficiaries
A beneficiary represents a recipient of funds. They can be:
* Bank account holders
* Crypto wallet addresses
* Interac recipients
Each beneficiary type requires specific validation:
* Crypto addresses: Chain and address format validation
* Interac: Email registration verification
### Transfer Flow
Add and validate recipient details
* Verify account/address information
* Validate against destination requirements
* Store beneficiary ID for future use
Specify amount, currency, and purpose
* Check against transfer limits
* Verify sufficient balance
* Include required reference information
Complete any required verification
* 2FA if enabled
* Transfer PIN validation
* Additional security checks
Monitor transfer status via webhooks
* Track transfer progress
* Handle notifications
* Process confirmations
### Transfer Status Lifecycle
Transfers progress through these states:
1. `created` - Transfer initiated and validated
2. `processing` - Funds being transferred
3. `successful` - Confirmed and completed
4. `failed` - Transfer unsuccessful
5. `cancelled` - Manually or automatically cancelled
Each status change triggers a webhook notification to your registered endpoint.
## Best Practices
1. **Pre-transfer Validation**
* Verify beneficiary details before transfer
* Check sufficient balance availability
* Validate against all applicable limits
* Consider currency exchange rates
* Use test mode for integration
2. **Error Handling**
* Implement proper retry logic
* Monitor transfer status
* Handle timeout scenarios
* Log all transfer attempts
* Process webhook notifications
3. **Security & Compliance**
* Implement proper authentication
* Validate webhook signatures
* Monitor for suspicious patterns
* Follow regulatory requirements
* Maintain audit trails
4. **Rate Management**
* Cache exchange rates appropriately
* Handle rate expiration
* Implement rate refresh logic
* Show clear rate information
Learn more about:
* [Creating Beneficiaries](/transfers/beneficiaries/create-beneficiary)
* [Initiating Transfers](/transfers/transfers/initiate-bank-transfer)
* [Listing Transfers](/transfers/transfers/list-transfers)
* [Error Handling](/errors)
# Initiate a Stablecoin Transfer
Source: https://docs.juicyway.com/transfers/transfers/initiate-a-stablecoin-transfer
Send stablecoin transfers to crypto addresses with support for multiple chains
## Overview
Transfer stablecoins from your Juice balance to external crypto addresses across multiple supported chains. This endpoint handles stablecoin payouts with automated rate conversion and chain validation.
## Supported Tokens and Chains
**USDT Support**
* Ethereum (ETH)
* Tron (TRX)
* BNB Smart Chain (BSC)
**USDC Support**
* Ethereum (ETH)
* Polygon (MATIC)
* Avalanche C-Chain (AVAXC)
Always verify the destination chain matches the selected token to avoid lost transactions. Not all tokens are supported on all chains.
## Transaction Limits
* Minimum: 10 USDT/USDC
* Maximum: 50,000 USDT/USDC per transaction
* Daily Limit: 100,000 USDT/USDC
## Endpoint
```bash theme={null}
POST /payouts
```
### Request Parameters
Amount in minor units (e.g., 100000 = 1000.00 USD)
* Minimum: 1000 (10 USD)
* Maximum: 10000000 (100,000 USD)
Beneficiary object
```json theme={null}
"beneficiary": {
"id": "",
"type": ""
}
```
Must be "crypto\_address"
Purpose or description of the transfer
* Maximum length: 140 characters
Stablecoin token type
* Supported values: "USDT", "USDC"
Must be "USD"
Unique identifier for the transfer
* Must be unique across all transfers
* Alphanumeric characters only
Must be one of: sender, recipient\
Default: sender
### Example Request
```json theme={null}
{
"amount": 100000,
"beneficiary": {
"id": "juice-payout-5d906f6d-933b-4de9-927f-c7522823f5ec",
"type": "bank_account",
},
"description": "Payment for services",
"destination_currency": "USDT",
"pin": "123456",
"reference": "juice-payout-5d906f6d-933b-4de9-927f-c7522823f5ec",
"source_currency": "USD",
"fee_charged_to": "sender"
}
```
### Success Response
```json theme={null}
{
"data": {
"beneficiary": {
"chain": "TRX",
"address": "TRDFGhjkytywooiueonuoo",
"id": "d8c0226b-048c-4c44-9606-a93333f56283",
"type": "crypto_address"
},
"beneficiary_type": "crypto_address",
"created_at": "2024-03-01T02:29:49Z",
"destination_amount": 100000,
"destination_currency": "USDT",
"id": "93cf071e-d773-11ee-bf78-c6d49632367b",
"source_amount": 100000,
"source_currency": "USD",
"status": "pending",
"updated_at": "2024-03-01T02:29:53Z"
}
}
```
## Error Responses
```json theme={null}
{
"error": {
"code": "invalid_request",
"message": "Invalid parameters provided",
"details": {
"amount": ["Amount must be at least 1000"]
}
}
}
```
```json theme={null}
{
"error": {
"code": "invalid_pin",
"message": "Invalid authorization PIN provided"
}
}
```
```json theme={null}
{
"error": {
"code": "validation_error",
"message": "The request contains invalid parameters",
"details": {
"destination_currency": ["Must be one of: USDT, USDC"]
}
}
}
```
```json theme={null}
{
"error": {
"code": "rate_limit_exceeded",
"message": "Too many requests. Please try again in 60 seconds."
}
}
```
## Best Practices
1. **Chain Selection**
* Use TRX for lowest fees
* Consider ETH during low gas periods
* Use MATIC/AVAXC for faster confirmations
2. **Error Handling**
* Implement retry logic with exponential backoff
* Monitor network congestion
* Handle timeouts gracefully
3. **Validation**
* Verify beneficiary addresses before transfer
* Check sufficient balance
* Validate against transfer limits
4. **Monitoring**
* Track transfer status via webhooks
* Monitor blockchain confirmations
* Log all transfer attempts
For additional assistance:
* Review our [Error Handling Guide](/errors)
* Contact [support@juicyway.com](mailto:support@juicyway.com)
# Initiate Bank Transfer
Source: https://docs.juicyway.com/transfers/transfers/initiate-bank-transfer
Send bank transfers to saved or new beneficiaries
## Overview
Initiate bank transfers from your Juicyway balance to bank accounts. This endpoint supports both domestic and international transfers with real-time rate conversion where applicable.
Before initiating a transfer:
1. Ensure sufficient balance in the source currency
2. Verify beneficiary account details
3. Confirm the charge
4. Check transfer limits for your account tier in our [Overview](/transfers/overview#processing-times)
## Charge Endpoint
```bash theme={null}
GET /payouts/Charge
```
## Request Parameters
Amount to charge
Cyrrency to charge e.g (USD,NGN,CAD)
Cyrrency rail to use e.g (USD,NGN,CAD)
### Response
```json Response theme={null}
{
"data": {
"can_perform": true,
"fee": {
"amount": 0,
"currency": "string"
},
"reason": "string"
}
}
```
`Request`
# \\
Payout Endpoint
```bash theme={null}
POST /payouts
```
## Request Parameters
Transfer amount in minor units (e.g., cents, kobo)
* Must be within [transfer limits](/transfers/overview#processing-times)
* Minimum and maximum vary by currency
Beneficiary object
```json theme={null}
"beneficiary": {
"id": "",
"type": ""
}
```
Purpose or description of the transfer
* Maximum length: 200 characters
Currency code for the destination account
* Supported: NGN, USD, CAD
Your unique reference for this transfer
* Must be unique across all transfers
* Used for idempotency
Currency to debit from your balance
* Must match destination\_currency for local transfers
* Rate conversion applies for cross-currency transfers
Must be one of: sender, recipient\
Default: sender
## Request Examples
### Local Bank Transfer (NGN)
```json Request theme={null}
{
"amount": 100000,
"beneficiary": {
"id": "juice-payout-5d906f6d-933b-4de9-927f-c7522823f5ec",
"type": "bank_account",
},
"description": "Vendor Payment",
"destination_currency": "NGN",
"pin": "123456",
"reference": "pmt_vendor_123",
"source_currency": "NGN",
"fee_charged_to": "sender"
}
```
```json Response theme={null}
{
"data": {
"beneficiary": {
"account_name": "ACME CORPORATION",
"account_number": "0821081314",
"account_type": "current",
"bank_name": "ACCESS BANK",
"id": "d8c0226b-048c-4c44-9606-a93333f56283",
"type": "bank_account"
},
"beneficiary_type": "bank_account",
"created_at": "2024-03-01T02:29:49Z",
"destination_amount": 100000,
"destination_currency": "NGN",
"id": "93cf071e-d773-11ee-bf78-c6d49632367b",
"source_amount": 100000,
"source_currency": "NGN",
"status": "pending",
"updated_at": "2024-03-01T02:29:53Z"
}
}
```
### International Transfer (USD)
```json Request theme={null}
{
"amount": 50000,
"beneficiary": {
"id": "us_ben_789xyz",
"type": "bank_account"
},
"description": "International Payment",
"destination_currency": "USD",
"pin": "123456",
"reference": "intl_pmt_456",
"source_currency": "NGN",
"fee_charged_to": "sender"
}
```
```json Response theme={null}
{
"data": {
"beneficiary": {
"account_name": "Global Services LLC",
"account_number": "12345678",
"routing_number": "021000021",
"bank_name": "CHASE",
"id": "us_ben_789xyz",
"type": "bank_account"
},
"beneficiary_type": "bank_account",
"created_at": "2024-03-15T14:30:00Z",
"destination_amount": 50000,
"destination_currency": "USD",
"id": "intl_tx_789abc",
"source_amount": 45000000, // NGN equivalent
"source_currency": "NGN",
"status": "pending",
"updated_at": "2024-03-15T14:30:00Z"
}
}
```
## Error Handling
Balance too low for transfer
* Status code: 400
* Check available balance
* Consider exchange rates for international transfers
Invalid or inactive beneficiary
* Status code: 400
* Verify beneficiary\_id
* Check account status
Transfer exceeds account limits
* Status code: 400
* Review transfer limits
* Contact support for limit increases
## Best Practices
1. **Idempotency**
* Use unique references
* Handle duplicate requests
* Store transfer IDs
2. **Validation**
* Verify account details
* Check currency support
* Validate amounts
3. **Monitoring**
* Implement webhook handling
* Track transfer status
* Log all attempts
4. **Security**
* Use transfer PINs
* Implement 2FA where available
* Monitor for suspicious patterns
* Review [Transfer Limits](/transfers/overview#processing-times)
* Set up [Webhook Handling](/webhooks) for transfer status updates
* Learn about [Error Handling](/errors)
For additional assistance:
* Review our [Error Handling Guide](/errors)
* Contact [support@juicyway.com](mailto:support@juicyway.com)
# List Nigerian Banks
Source: https://docs.juicyway.com/transfers/transfers/list-ngn-banks
Retrieve a list of all supported Nigerian banks with their codes
## Overview
This endpoint returns a comprehensive list of supported Nigerian banks and their corresponding codes. Use this endpoint to obtain the correct bank codes needed for bank transfers and account number resolution.
Bank codes are required for:
* Validating account numbers
* Creating bank transfer beneficiaries
* Initiating bank transfers
## Endpoint
```bash theme={null}
GET /payment-methods/banks
```
## Response Format
Array of bank objects containing:
Bank code required for transfers
* Format: 6-digit string
* Example: "000023"
Official bank name
* Example: "PROVIDUS BANK"
## Example Request
```bash cURL theme={null}
curl -X GET "https://api.spendjuice.com/payment-methods/banks" \
-H "Authorization: YOUR_API_KEY"
```
```javascript Node.js theme={null}
const response = await fetch('https://api.spendjuice.com/payment-methods/banks', {
headers: {
'Authorization': ' YOUR_API_KEY'
}
});
const banks = await response.json();
```
```python Python theme={null}
import requests
response = requests.get(
'https://api.spendjuice.com/payment-methods/banks',
headers={'Authorization': ' YOUR_API_KEY'}
)
banks = response.json()
```
## Example Response
```json 200 Success theme={null}
{
"data": [
{
"code": "000014",
"name": "ACCESS BANK"
},
{
"code": "000023",
"name": "PROVIDUS BANK"
},
{
"code": "000013",
"name": "ZENITH BANK"
},
{
"code": "000017",
"name": "GUARANTY TRUST BANK"
}
]
}
```
```json 401 Unauthorized theme={null}
{
"error": {
"code": "unauthorized",
"message": "Invalid or missing API key"
}
}
```
```json 500 Server Error theme={null}
{
"error": {
"code": "server_error",
"message": "An unexpected error occurred"
}
}
```
## Error Handling
Indicates invalid or missing API key
* Verify your API key is valid
* Check authorization header format
Indicates insufficient permissions
* Verify your API key has correct permissions
* Check your account status
Indicates an internal server error
* Retry the request after a short delay
* Contact support if the error persists
## Usage Tips
1. **Cache Results**
* Bank list changes infrequently
* Cache results for up to 24 hours
* Implement cache invalidation on errors
2. **Error Handling**
* Implement retry logic for failed requests
* Maintain a fallback bank list if needed
* Log any persistent errors
3. **Data Validation**
* Verify bank codes are 6 digits
* Handle missing or null values
* Validate against your supported banks list
## Best Practices
To ensure reliable bank transfers:
* Always use current bank codes
* Refresh cached bank lists daily
* Validate codes before transactions
* Handle bank name variations
* Log any unrecognized bank codes
Never hardcode bank codes in your application. Always fetch them dynamically to ensure you're using the most current codes.
# Resolve NGN Account Number
Source: https://docs.juicyway.com/transfers/transfers/resolve-ngn-account-number
Verify Nigerian bank account details before initiating payments
## Overview
The account resolution endpoint allows you to validate Nigerian bank account numbers and retrieve account holder names before initiating transfers. This verification helps prevent failed transactions and ensures accurate payments.
This endpoint should be called before creating beneficiaries or initiating
transfers to Nigerian bank accounts.
## Endpoint
```bash theme={null}
POST /payment-methods/resolve-bank-account
```
## Request Parameters
Bank account number to verify \* Must be exactly 10 digits \* Numbers only (0-9)
Bank code from the [List Banks](/transfers/transfers/list-ngn-banks) endpoint
* 3-6 digit identifier \* Must be for an active Nigerian bank
## Example Request
```bash cURL theme={null}
curl -X POST "https://api.spendjuice.com/payment-methods/resolve-bank-account" \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"account_number": "0234247896",
"bank_code": "058"
}'
```
```javascript Node.js theme={null}
const response = await fetch(
"https://api.spendjuice.com/payment-methods/resolve-bank-account",
{
method: "POST",
headers: {
Authorization: " YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
account_number: "0234247896",
bank_code: "058",
}),
},
);
const data = await response.json();
```
```python Python theme={null}
import requests
response = requests.post(
'https://api.spendjuice.com/payment-methods/resolve-bank-account',
headers={
'Authorization': ' YOUR_API_KEY',
'Content-Type': 'application/json'
},
json={
'account_number': '0234247896',
'bank_code': '058'
}
)
```
## Response Examples
```json 200 Success theme={null}
{
"data": {
"account_name": "ANON NYMOUS",
"account_number": "0234247896",
"bank_code": "058"
}
}
```
```json 400 Invalid Account Number theme={null}
{
"error": {
"code": "invalid_account_number",
"message": "Invalid account number provided",
"type": "validation_error"
}
}
```
```json 404 Account Not Found theme={null}
{
"error": {
"code": "account_not_found",
"message": "Account number not found for the specified bank",
"type": "not_found_error"
}
}
```
```json 503 Bank Unavailable theme={null}
{
"error": {
"code": "bank_not_available",
"message": "Bank resolution service temporarily unavailable",
"type": "service_error"
}
}
```
For additional assistance:
* Review our [Error Handling Guide](/errors)
* Contact [support@juicyway.com](mailto:support@juicyway.com)
# Add Payment Method
Source: https://docs.juicyway.com/waas/add-payment-method
This endpoint allows you to attach a payment method to an existing wallet. A payment method defines how funds can be added to or withdrawn from a wallet, such as via a bank account.
## Endpoint
```json theme={null}
POST /wallets/{id}/payment-method
```
## Description
Use this endpoint to add a payment method to a wallet that has already been created. Once a payment method is added, the wallet can be funded or used for payouts through the specified channel.
***
## Path Parameters
| Parameter | Type | Required | Description |
| :-------- | :------------ | :------- | :---------------------------------- |
| `id` | string (UUID) | Yes | The unique identifier of the wallet |
***
## Request Body
```json theme={null}
{
"type": "bank_account"
}
```
### Request Fields
| Field | Type | Required | Description |
| :----- | :----- | :------- | :-------------------------------- |
| `type` | string | Yes | The type of payment method to add |
### Supported Payment Method Types
| Type | Description |
| :------------- | :-------------------------------------------------------- |
| `bank_account` | Links a bank account to the wallet for funding or payouts |
> Additional payment method types may be supported depending on your integration and region.
***
## Response
### Success Response (200 OK)
```json theme={null}
{
"data": {
"id": "3d2e3f3e-3b3c-4907-a4fd-e241203440d7",
"status": "active",
"payment_methods": [
{
"account_name": "Prosacco Erdman",
"account_number": "3515200757",
"account_type": "savings",
"address": null,
"bank_address": "9896 Bulah Roads, Suite 256, North Carolina, Kansas, 09819, US",
"bank_code": "035",
"bank_name": "Wema Bank"
}
],
"balance": {
"amount": 0,
"currency": "NGN"
}
}
}
```
## Response Fields
| Field | Type | Description |
| :----------------- | :----- | :------------------------------------------------- |
| `id` | string | The wallet ID |
| `status` | string | Current wallet status (`active`, `inactive`, etc.) |
| `payment_methods` | array | List of payment methods linked to the wallet |
| `balance.amount` | number | Wallet balance amount |
| `balance.currency` | string | Wallet currency |
> The `payment_methods` array may initially be empty if additional verification or setup is required before activation.
***
## Example cURL Request
```bash theme={null}
curl -X POST https://api.yourdomain.com/wallets/{id}/payment-method \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "bank_account"
}'
```
***
## Common Errors
| Status Code | Reason |
| :---------- | :----------------------------------------- |
| `400` | Invalid request body |
| `401` | Unauthorized request |
| `404` | Wallet not found |
| `422` | Unsupported or invalid payment method type |
***
## Notes & Best Practices
* Ensure the wallet exists and is active before adding a payment method.
* Some payment methods may require additional verification steps before they become usable.
* Always store and reference the wallet ID securely.
* Use sandbox mode to test payment method creation before moving to production.
***
## Next Steps
After successfully adding a payment method, you can:
* Fund the wallet
* Initiate payouts
* Retrieve wallet details
* Monitor wallet activity via webhooks
# Additional Operations
Source: https://docs.juicyway.com/waas/additional-operations
This endpoint retrieves a list of wallets. You can filter results by customer, currency, or wallet status.
## Endpoint
```json theme={null}
GET /wallets/all
```
## Description
Use this endpoint to fetch all wallets associated with your account. Filters can be applied to narrow results based on customer or wallet attributes.
## Query Parameters (Filters)
| Parameter | Type | Description |
| :------------ | :------------ | :------------------------------------------------------- |
| `customer_id` | string (UUID) | Filter wallets by customer |
| `currency` | string | Filter wallets by currency (e.g. `NGN`, `USD`) |
| `status` | string | Filter wallets by status (`active`, `frozen`, `deleted`) |
## Example cURL Request
```bash theme={null}
curl -X GET "https://api.spendjuice.com/wallets/all?currency=NGN&status=active" \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json"
```
***
## Response
### Success Response (200 OK)
```json theme={null}
{
"data": [
{
"id": "wallet_id",
"customer_id": "customer_id",
"currency": "NGN",
"status": "active",
"balance": {
"amount": 1500,
"currency": "NGN"
}
}
]
}
```
***
# List Wallet Transactions
This endpoint retrieves a list of wallet transactions. You can filter transactions by wallet or transaction type.
***
## Endpoint
```json theme={null}
GET /wallets/transactions
```
## Description
Use this endpoint to list all transactions across wallets or to retrieve transactions for a specific wallet.
## Query Parameters (Filters)
| Parameter | Type | Description |
| :---------- | :------------ | :--------------------------------------------- |
| `wallet_id` | string (UUID) | Filter transactions by wallet |
| `type` | string | Filter by transaction type (`debit`, `credit`) |
***
## Example cURL Request
```
curl -X GET "https://api.spendjuice.com/wallets/transactions?wallet_id=wallet_id&type=debit" \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json"
```
## Response
### Success Response (200 OK)
```json theme={null}
{
"data": [
{
"id": "transaction_id",
"wallet_id": "wallet_id",
"type": "debit",
"amount": 500,
"description": "Customer payout",
"created_at": "2025-07-24T10:15:30Z"
}
]
}
```
***
# Retrieve a Transaction
This endpoint retrieves the details of a single wallet transaction by its ID.
## Endpoint
```json theme={null}
GET /wallets/transactions/{id}
```
## Description
Use this endpoint to fetch full details of a specific transaction, including amount, type, and timestamps.
## Path Parameters
| Parameter | Type | Required | Description |
| :-------- | :------------ | :------- | :---------------------------- |
| `id` | string (UUID) | Yes | Unique transaction identifier |
## Example cURL Request
```bash theme={null}
curl -X GET "https://api.spendjuice.com/wallets/transactions/{id}" \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json"
```
## Response
### Success Response (200 OK)
```json theme={null}
{
"data": {
"id": "transaction_id",
"wallet_id": "wallet_id",
"type": "credit",
"amount": 1000,
"description": "Wallet top-up",
"created_at": "2025-07-24T09:45:00Z"
}
}
```
***
## Common Errors
| Status Code | Description |
| :---------- | :------------------------- |
| `401` | Unauthorized |
| `404` | Resource not found |
| `400` | Invalid request parameters |
***
## Notes & Best Practices
* Use filters to reduce payload size and improve performance.
* Always verify wallet status before initiating related actions.
* Paginate responses if supported to handle large result sets.
* Use transaction IDs for reconciliation and audit purposes.
# Create Customer
Source: https://docs.juicyway.com/waas/create-customer
Before creating a wallet, you must first create a customer. A customer can be an individual or a business and represents the entity that owns one or more wallets.
## Endpoint
```json theme={null}
POST /customers
```
## Description
This endpoint provisions a customer in the system. The customer record is required to associate wallets, transactions, and payment methods. After creation, the customer typically starts in a `pending_kyc` status until verification is completed.
## Request Body
```json theme={null}
{
"first_name": "James",
"last_name": "Okafor",
"email": "james.okafor@example.com",
"phone": "+2348012345678",
"type": "individual",
"billing_address": {
"line1": "123 Test Lane",
"line2": "Suite 456",
"city": "Lagos",
"state": "Lagos",
"zip_code": "100001",
"country": "NG"
}
}
```
***
## Request Fields
| Field | Type | Required | Description |
| :---------------- | :----- | :------- | :------------------------------------------ |
| `first_name` | string | Yes | Customer’s first name |
| `last_name` | string | Yes | Customer’s last name |
| `email` | string | Yes | Customer’s email address |
| `phone` | string | Yes | Customer’s phone number (with country code) |
| `type` | string | Yes | Customer type: `individual` or `business` |
| `billing_address` | object | Yes | Customer’s billing address |
### Billing Address Fields
| Field | Type | Required | Description |
| :--------- | :----- | :------- | :------------------------ |
| `line1` | string | Yes | Street address line 1 |
| `line2` | string | No | Street address line 2 |
| `city` | string | Yes | City |
| `state` | string | Yes | State or region |
| `zip_code` | string | Yes | Postal code |
| `country` | string | Yes | ISO 2-letter country code |
***
## Response
### Success Response (201 Created)
```
{
"data": {
"id": "7da75a46-a1bc-11ee-9a32-560f156a658b",
"status": "pending_kyc",
"created_at": "2025-09-22T09:01:09Z"
}
}
```
***
## Response Fields
| Field | Type | Description |
| :----------- | :----- | :---------------------------------------------- |
| `id` | string | Unique customer identifier |
| `status` | string | Customer status (`pending_kyc`, `active`, etc.) |
| `created_at` | string | Timestamp when the customer was created |
***
## Example cURL Request
```bash theme={null}
curl -X POST https://api.yourdomain.com/customers \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"first_name": "James",
"last_name": "Okafor",
"email": "james.okafor@example.com",
"phone": "+2348012345678",
"type": "individual",
"billing_address": {
"line1": "123 Test Lane",
"line2": "Suite 456",
"city": "Lagos",
"state": "Lagos",
"zip_code": "100001",
"country": "NG"
}
}'
```
***
## Common Errors
| Status Code | Description |
| :---------- | :----------------------------------------- |
| `400` | Invalid request or missing required fields |
| `401` | Unauthorized |
| `409` | Customer already exists |
| `422` | Invalid field values |
***
## Notes & Best Practices
* Ensure all mandatory fields are provided and formatted correctly.
* The `status` starts as `pending_kyc` if verification is required.
* Store the returned `id` as it is needed to create wallets and associate transactions.
* Validate emails and phone numbers to prevent errors in subsequent wallet creation.
***
## Typical Flow
1. Create a customer via `POST /customers`.
2. Verify customer if required (KYC).
3. Create a wallet for the customer using `POST /wallets`.
4. Add payment methods and perform transactions as needed.
# Create Wallet
Source: https://docs.juicyway.com/waas/create-wallet
This endpoint allows you to create a new wallet for a specific customer in a chosen currency. Each wallet is linked to a customer and can be used to manage balances, transactions, and payment methods.
## Endpoint
```json theme={null}
POST /wallets
```
## Description
Use this endpoint to provision a wallet for a customer. The wallet is automatically assigned a unique ID and starts with a **zero balance**. The wallet status is set to `active` upon creation.
***
## Request Body
```json theme={null}
{
"currency": "NGN",
"customer_id": "7da75a46-a1bc-11ee-9a32-560f156a658b"
}
```
***
## Request Fields
| Field | Type | Required | Description |
| :------------ | :------------ | :------- | :------------------------------------------------ |
| `customer_id` | string (UUID) | Yes | The customer for whom the wallet is being created |
| `currency` | string | Yes | The currency for the wallet (e.g., `NGN`, `USD`) |
***
## Response
### Success Response (201 Created)
```json theme={null}
{
"data": {
"id": "3d2e3f3e-3b3c-4907-a4fd-e241203440d7",
"account_id": "f55ca88c-71aa-4dab-a10a-4d818c11e8e6",
"customer_id": "a08bf5a3-8459-4e65-a5bb-34a1feef94cf",
"balance": {
"amount": 0,
"currency": "NGN"
},
"status": "active"
}
}
```
***
## Response Fields
| Field | Type | Description |
| :----------------- | :----- | :-------------------------------------- |
| `id` | string | Unique wallet ID |
| `account_id` | string | Internal account identifier |
| `customer_id` | string | ID of the customer linked to the wallet |
| `balance.amount` | number | Current wallet balance (starts at 0) |
| `balance.currency` | string | Currency of the wallet |
| `status` | string | Wallet status (`active`) |
***
## Example cURL Request
```bash theme={null}
curl -X POST https://api.yourdomain.com/wallets \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"currency": "NGN",
"customer_id": "7da75a46-a1bc-11ee-9a32-560f156a658b"
}'
```
***
## Common Errors
| Status Code | Description |
| :---------- | :--------------------------------------------------- |
| `400` | Invalid request or unsupported currency |
| `401` | Unauthorized |
| `404` | Customer not found |
| `409` | Wallet already exists for this customer and currency |
***
## Notes & Best Practices
* Ensure the customer exists before creating a wallet.
* Only create one wallet per customer per currency to avoid duplicates.
* The wallet starts with a zero balance and `active` status.
* Use the wallet `id` for all subsequent transactions, payment methods, or status updates.
***
## Common Use Cases
* Provision wallets when a new customer signs up
* Enable multi-currency wallet management for existing customers
* Prepare wallets for payouts, funding, or transaction processing
# Overview
Source: https://docs.juicyway.com/waas/overview
The Juicyway Wallet API enables businesses to programmatically create and manage customer wallets, fund wallets, and process payouts across supported currencies. This guide describes the required endpoints, request/response formats, and recommended integration flow for Wallet-as-a-Service (WaaS).
## Wallet-as-a-Service (WaaS)
Wallet-as-a-Service (WaaS) provides an API-driven abstraction for wallet creation, funding, payouts, and transaction tracking.
WaaS handles:
* Wallet lifecycle management
* Multi-currency balances
* Credit and debit transactions
* Wallet status controls
* Transaction reconciliation
***
## Core Features & APIs
The Wallet API supports the following operations:
* **Customer Management**
* Create and manage customer profiles
* **Wallet Management**
* Create wallets per customer and currency
* Retrieve wallet details and balances
* Update wallet status (active, frozen, deleted)
* **Payment Methods**
* Add supported payment methods to wallets
* **Transactions**
* Credit transactions (funding)
* Debit transactions (payouts)
* Transaction listing and retrieval
***
## Base URL
```
https://api.spendjuice.com
```
***
## Authentication
All API requests require authentication using an API key.
**Header**
```
Authorization: YOUR_API_KEY
```
## Typical Merchant Flow
### Customer Onboarding
1. Create customer
2. Complete KYC verification
3. Create wallet
4. Add payment method
### Daily Operations
* Fund wallet (credit)
* Process payouts (debit)
* Retrieve balances
* Monitor transactions
### Account Management
* Freeze wallet
```json theme={null}
PATCH /wallets/{id}/status
```
* Delete wallet
```json theme={null}
PATCH /wallets/{id}/status
```
***
## Error Handling
| Code | Description |
| :--- | :------------------------------ |
| 400 | Invalid request parameters |
| 401 | Unauthorized (invalid API key) |
| 404 | Resource not found |
| 422 | Business rule validation failed |
| 500 | Internal server error |
## Best Practices
* Complete customer KYC before wallet activation.
* Use idempotency keys for wallet and transaction creation.
* Persist transaction IDs for reconciliation.
* Keep wallet status synchronized with internal user state.
* Use sandbox mode before production deployment.
# Update wallet balance
Source: https://docs.juicyway.com/waas/process-payout
This endpoint is used to debit or credit a wallet balance. It supports internal wallet adjustments such as payouts, refunds, top-ups, or manual balance corrections.
## Endpoint
```json theme={null}
POST /wallets/transactions
```
## Description
Use this endpoint to create a transaction that either **adds funds to a wallet (credit)** or **removes funds from a wallet (debit)**. The wallet balance is updated immediately upon successful processing.
## Request Body
```json theme={null}
{
"amount": 500,
"description": "Customer payout",
"type": "debit",
"wallet_id": "3d2e3f3e-3b3c-4907-a4fd-e241203440d7"
}
```
***
## Request Fields
| Field | Type | Required | Description |
| :------------ | :------------ | :------- | :-------------------------------------- |
| `wallet_id` | string (UUID) | Yes | Wallet to be debited or credited |
| `amount` | number | Yes | Transaction amount (in wallet currency) |
| `type` | string | Yes | Transaction type: `debit` or `credit` |
| `description` | string | No | Reason or note for the transaction |
***
## Supported Transaction Types
| Type | Description |
| :------- | :------------------------------------ |
| `credit` | Adds funds to the wallet balance |
| `debit` | Removes funds from the wallet balance |
***
## Response
### Success Response (200 OK)
```json theme={null}
{
"data": {
"transaction_id": "transaction_id",
"wallet_id": "wallet_id",
"type": "debit",
"amount": 500,
"balance_after": 1500,
"created_at": "2025-07-24T10:15:30Z"
}
}
```
***
## Common Errors
| Status Code | Description |
| :---------- | :----------------------------- |
| `400` | Invalid request |
| `401` | Unauthorized |
| `404` | Wallet not found |
| `409` | Insufficient balance for debit |
| `422` | Invalid transaction type |
***
## Notes & Best Practices
* Ensure the wallet is **active** before initiating a transaction.
* Debits will fail if the wallet balance is insufficient.
* Use clear and descriptive transaction descriptions for auditing.
* Avoid using this endpoint for external payments; use dedicated payout or funding endpoints instead.
***
## Common Use Cases
* Customer payouts
* Refunds
* Wallet top-ups
* Internal balance adjustments
# Retrieve Wallet
Source: https://docs.juicyway.com/waas/retrieve-wallet
This endpoint retrieves the full details of a wallet, including its balance, status, linked payment methods, and historical events. It is commonly used to display wallet information, verify wallet state, and support operational or compliance workflows.
## Endpoint
```json theme={null}
GET /wallets/{id}
```
## Description
Use this endpoint to fetch the current state of a wallet. The response includes balance information, associated customer and account IDs, payment methods, wallet status, and lifecycle events.
## Path Parameters
| Parameter | Type | Required | Description |
| :-------- | :------------ | :------- | :------------------------------ |
| `id` | string (UUID) | Yes | Unique identifier of the wallet |
## Response
### Success Response (200 OK)
```json theme={null}
{
"data": {
"account_id": "f55ca88c-71aa-4dab-a10a-4d818c11e8e6",
"balance": {
"amount": 0,
"currency": "USD"
},
"customer_id": "a08bf5a3-8459-4e65-a5bb-34a1feef94cf",
"events": [
{
"action": "create",
"id": "6a2a5833-609d-4dff-a4e6-0eaf452d7826",
"inserted_at": "2025-07-24T08:08:07Z",
"reason": null,
"wallet_id": "55a76a42-ed3a-4d0b-b74c-2887d64612f6"
}
],
"id": "3d2e3f3e-3b3c-4907-a4fd-e241203440d7",
"payment_methods": [
{
"account_name": "Prosacco Erdman",
"account_number": "3515200757",
"account_type": "savings",
"address": null,
"bank_address": "9896 Bulah Roads, Suite 256, North Carolina, Kansas, 09819, US",
"bank_code": "035",
"bank_name": "Wema Bank"
}
],
"status": "active"
}
}
```
***
## Response Fields
### Wallet Information
| Field | Type | Description |
| :------------ | :----- | :---------------------------------- |
| `id` | string | Wallet ID |
| `status` | string | Current wallet status |
| `customer_id` | string | Customer associated with the wallet |
| `account_id` | string | Internal account identifier |
***
### Balance
| Field | Type | Description |
| :----------------- | :----- | :--------------------- |
| `balance.amount` | number | Current wallet balance |
| `balance.currency` | string | Wallet currency |
***
### Payment Methods
| Field | Type | Description |
| :---------------- | :----- | :-------------------------------------------- |
| `payment_methods` | array | List of payment methods linked to the wallet |
| `account_name` | string | Name on the bank account |
| `account_number` | string | Bank account number |
| `account_type` | string | Type of bank account (e.g., savings, current) |
| `bank_name` | string | Name of the bank |
| `bank_code` | string | Bank routing or institution code |
| `bank_address` | string | Bank branch address |
> Sensitive fields may be partially masked depending on environment and permissions.
***
### Events
| Field | Type | Description |
| :------------ | :---------------- | :---------------------------------------------- |
| `events` | array | Historical actions performed on the wallet |
| `action` | string | Event type (e.g., `create`, `freeze`, `delete`) |
| `inserted_at` | string (ISO 8601) | Timestamp of the event |
| `reason` | string | Reason for the action, if provided |
***
## Example cURL Request
```bash theme={null}
curl -X GET https://api.yourdomain.com/wallets/{id} \
-H "Authorization: Bearer YOUR_API_KEY"
```
***
## Common Errors
| Status Code | Description |
| :---------- | :--------------- |
| `401` | Unauthorized |
| `404` | Wallet not found |
| `403` | Access denied |
***
## Use Cases
* Display wallet details in a dashboard
* Check wallet balance and status before transactions
* Review linked payment methods
* Audit wallet activity and lifecycle events
***
## Notes & Best Practices
* Always confirm wallet status before initiating funding or payouts.
* Cache wallet responses carefully to avoid stale balance data.
* Use wallet events for audit logs and compliance reviews.
# Update Wallet Status
Source: https://docs.juicyway.com/waas/update-wallet-status
This endpoint allows you to update the operational status of an existing wallet. Wallet status controls whether the wallet can be used for transactions and helps enforce risk, compliance, and lifecycle management rules.
## Endpoint
```json theme={null}
PATCH /wallets/{id}/status
```
## Description
Use this endpoint to change the status of a wallet to **active**, **frozen**, or **deleted**.\
Status updates are commonly used to temporarily restrict wallet activity, permanently disable a wallet, or re-enable it after review.
## Path Parameters
| Parameter | Type | Required | Description |
| :-------- | :------------ | :------- | :------------------------------ |
| `id` | string (UUID) | Yes | Unique identifier of the wallet |
***
## Request Body
```
{
"status": "frozen",
"reason": "Suspicious activity detected"
}
```
***
## Request Fields
| Field | Type | Required | Description |
| :------- | :----- | :------- | :----------------------------------------------------------------------- |
| `status` | string | Yes | New status to apply to the wallet |
| `reason` | string | No | Explanation for the status change (recommended for audit and compliance) |
***
## Supported Statuses
| Status | Description |
| :-------- | :------------------------------------------------------- |
| `active` | Wallet is enabled and can perform transactions |
| `frozen` | Wallet is temporarily disabled; transactions are blocked |
| `deleted` | Wallet is permanently disabled and cannot be reactivated |
***
## Response
### Success Response (200 OK)
```
{
"data": {
"id": "wallet_id",
"status": "frozen"
}
}
```
***
## Response Fields
| Field | Type | Description |
| :------- | :----- | :-------------------- |
| `id` | string | Wallet identifier |
| `status` | string | Updated wallet status |
***
## Example cURL Request
```
curl -X PATCH https://api.yourdomain.com/wallets/{id}/status \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"status": "frozen",
"reason": "Suspicious activity detected"
}'
```
***
## Common Errors
| Status Code | Reason |
| :---------- | :------------------------ |
| `400` | Invalid status value |
| `401` | Unauthorized request |
| `404` | Wallet not found |
| `422` | Invalid status transition |
***
## Status Transition Rules (Recommended)
* `active` → `frozen` ✅
* `frozen` → `active` ✅
* `active` → `deleted` ✅
* `frozen` → `deleted` ✅
* `deleted` → any status ❌ (not allowed)
***
## Notes & Best Practices
* Always include a `reason` when freezing or deleting a wallet for audit and compliance purposes.
* Freezing a wallet should immediately block:
* Incoming transfers
* Outgoing transfers
* Payment method usage
* Deleting a wallet should be treated as irreversible.
* Log all status changes for traceability and risk monitoring.
***
## Common Use Cases
* **Freeze wallet** due to suspicious or fraudulent activity
* **Reactivate wallet** after compliance review
* **Delete wallet** when a customer account is closed
***
## Next Steps
After updating a wallet’s status, you may want to:
* Notify the user of the status change
* Review transaction history
* Trigger internal compliance or risk workflows
# Webhooks
Source: https://docs.juicyway.com/webhooks
Integration Guide for Webhook Events
Before integrating webhooks, make sure you've completed the
[Quickstart](/quickstart) guide and have your authentication set up.
## Overview
When you make a request to our API, you'll typically get an immediate response. However, some operations like payments can take time to process. Instead of timing out, we return a pending status and use webhooks to notify you of the final result.
You have two options for handling these async operations:
* Poll the API endpoints periodically (not recommended for production)
* **Use webhooks to receive real-time event updates (recommended)**
### Webhooks vs Polling
* Make repeated GET requests to check transaction status - Higher latency
and more resource intensive - May miss state changes between polls - Better
suited for testing/debugging
* Receive instant notifications when state changes - More efficient and
scalable - No missed events - Recommended for production use
## Setting Up Webhooks
### 1. Create Your Webhook URL
Create a POST endpoint on your server to receive webhook events. The endpoint should:
1. Accept JSON payloads
2. Return a 200 OK response
3. Process events idempotently (handle duplicates safely)
```python Python theme={null} theme={null} theme={null}
from flask import Flask, request
import hmac
import hashlib
import json
app = Flask(__name__)
def validate_signature(payload, checksum, business_id):
# Separate event and data
event = payload['event']
data = json.dumps(payload['data'])
message = f"{event}|{data}"
# Create HMAC SHA256 hash
expected = hmac.new(
business_id.encode('utf-8'),
message.encode('utf-8'),
hashlib.sha256
).hexdigest().upper()
return hmac.compare_digest(expected, checksum)
@app.route('/webhook', methods=['POST'])
def handle_webhook():
payload = request.json
checksum = payload.get('checksum')
business_id = 'YOUR_BUSINESS_ID'
# Validate webhook signature
if not validate_signature(payload, checksum, business_id):
return 'Invalid signature', 401
# Process the webhook event
event_type = payload.get('event')
if event_type == 'payment.session.succeeded':
handle_successful_payment(payload['data'])
elif event_type == 'payment.session.failed':
handle_failed_payment(payload['data'])
# Return 200 to acknowledge receipt
return 'Webhook received', 200
```
```javascript Node.js theme={null} theme={null} theme={null}
import crypto from "crypto";
import express from "express";
import stringify from "json-stable-stringify";
const app = express();
app.use(express.json());
function validateSignature(payload, checksum, businessId) {
const { event, data } = payload;
const stringData = JSON.stringify(data);
const message = `${event}|${stringData}`;
// Create HMAC SHA256 hash
const expectedChecksum = crypto
.createHmac("sha256", businessId)
.update(message)
.digest("hex")
.toUpperCase();
return crypto.timingSafeEqual(
Buffer.from(expectedChecksum),
Buffer.from(checksum),
);
}
app.post("/webhook", (req, res) => {
const payload = req.body;
const checksum = payload.checksum;
const businessId = "YOUR_BUSINESS_ID";
// Validate webhook signature
if (!validateSignature(payload, checksum, businessId)) {
return res.status(401).send("Invalid signature");
}
// Process webhook event
const eventType = payload.event;
switch (eventType) {
case "payment.session.succeeded":
handleSuccessfulPayment(payload.data);
break;
case "payment.session.failed":
handleFailedPayment(payload.data);
break;
}
// Acknowledge receipt
res.status(200).send("Webhook received");
});
```
```php PHP theme={null} theme={null} theme={null}
event;
$data = json_encode($payload->data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
$message = $event . '|' . $data;
$expected = strtolower(hash_hmac('sha256', $message, $business_id));
$checksum = strtolower($checksum);
return hash_equals($expected, $checksum);
}
$data = file_get_contents('php://input');
$payload = json_decode($data);
$checksum = $payload->checksum;
$business_id = '';
// Validate webhook signature
if (!validate_signature($payload, $checksum, $business_id)) {
http_response_code(401);
echo 'Invalid signature' . "\n";
exit;
}
// Process webhook event
$eventType = $payload->event;
switch($eventType) {
case 'payment.session.succeeded':
handleSuccessfulPayment($payload->data->);
break;
case 'payment.session.failed':
handleFailedPayment($payload->data);
break;
}
// Acknowledge receipt
http_response_code(200);
echo 'Webhook received';
```
### 2. Register Your Webhook URL
Add your webhook URL to your account settings:
```bash theme={null}
PATCH /accounts/settings
```
```json Request theme={null}
{
"webhook_urls": ["https://your-domain.com/webhooks"]
}
```
```json Response theme={null}
{
"data": {
"settings": {
"webhook_urls": ["https://your-domain.com/webhooks"]
}
}
}
```
## Security
**Important Security Considerations:**
* Never expose sensitive credentials in client-side code or VCS
* Always validate request signatures and origins
* Use HTTPS for all API communications
* Implement proper access control and authentication
* Follow secure key management practices
**Never Share or Expose:**
* API Keys
* Secret Keys
* Encryption Keys
* Webhook Secrets
* Authentication Tokens
**Key Security Measures:**
1. Store sensitive data in secure environment variables or dedicated key management systems
2. Implement IP whitelisting where possible
3. Validate all incoming webhook signatures
4. Use strong TLS/SSL for all connections
5. Rotate credentials regularly
6. Log and monitor access attempts
7. Follow the principle of least privilege
**Implementation Tips:**
```javascript theme={null} theme={null} theme={null}
// ❌ Avoid hardcoding secrets
const apiKey = "sk_live_123..."; // Bad practice
// ✅ Use environment variables
const apiKey = process.env.API_KEY; // Good practice
// ✅ Validate webhook signatures
const isValidSignature = verifyWebhookSignature(
payload,
signature,
webhookSecret,
);
```
For additional security best practices, refer to our Security Guidelines in the documentation.
### Verifying Webhook Origins
Secure your webhook endpoint using either or both:
#### 1. Checksum Validation
Each webhook includes a checksum for verification:
```json theme={null}
{
"checksum": "32762AE880695AE7343A649CB9C36CA6FF83AA258A139804AEF7D73B421DE097",
"data": {
"card_id": "81817411-9ffd-42ba-8bc8-f407b5cef9d9",
"amount": 1000,
"reference": "b070b0d2-e394-4783-a6f0-f10ccb3cae89",
"currency": "USD"
},
"event": "card.transaction"
}
```
To validate:
1. Concatenate: `event|json_encoded_data`
2. Create HMAC SHA-256 hash using your business ID as the key
3. Compare with the received checksum
The encoded data must exclude the checksum field and be in alphabetical order:
```json Valid Order theme={null}
{
"amount": 1000,
"card_id": "81817411-9ffd-42ba-8bc8-f407b5cef9d9",
"currency": "USD",
"reference": "b070b0d2-e394-4783-a6f0-f10ccb3cae89"
}
```
#### 2. IP Whitelisting
Whitelist these Juicyway IPs:
```bash theme={null}
104.248.130.0
104.248.136.223
142.93.166.85
142.93.170.65
159.65.121.43
165.22.78.88
209.38.217.122
209.38.227.232
46.101.179.170
46.101.190.207
64.226.91.150
167.172.97.202
```
## Go-Live Checklist
Ensure your webhook URL is publicly accessible (no localhost)
Add trailing `/` if using .htaccessVerify JSON parsing and 200 OK responses
Return 200 OK before processing lengthy operations
Track non-200 responses in your logs
Handle duplicate events safely
## Supported Events
In sandbox, successful transactions remain pending. Only failure events are
sent.
### Payment Events
```json theme={null}
{
"checksum": "",
"data": {
"amount": 10000,
"callback_urls": {},
"cancellation_reason": null,
"channel_reference": "",
"collection_mode": null,
"correlation_id": "",
"currency": "NGN",
"customer": {
"account_id": "",
"billing_address": {
"city": "",
"country": "NG",
"line1": "",
"state": "",
"zip_code": ""
},
"email": "",
"first_name": "",
"id": "",
"last_name": "",
"phone_number": "",
"type": ""
},
"date": "",
"description": "",
"fee": null,
"id": "",
"merchant": {
"address": {
"city": "",
"country": "NG",
"line1": "",
"line2": null,
"state": "",
"zip_code": ""
},
"email": "",
"id": "",
"mcc": "",
"name": "",
"phone": ""
},
"order": {
"identifier": "",
"items": [
{
"name": "Transfer",
"type": "digital"
}
]
}
"mode": "live",
"order": {
"identifier": "",
"items": [
{
"name": "Transfer",
"type": "digital"
}
]
},
"payer": {
"account_name": null,
"account_number": null,
"bank_name": ""
},
"payment_method": {
"account_numner": "",
"account_name": "",
"bank_code": "",
"bank_name": "",
"currency": "",
"id": "",
"type": "bank_account"
},
"provider_id": "",
"redirect_url": null,
"reference": "",
"status": "success|failed",
"transaction_id": "",
"type": "payin|payout"
},
"event": "payment.session.succeeded|payment.session.failed"
}
```
* Learn about [API Request Authentication](/authentication) - Review common
[Error Handling](/errors) - Explore the full [API
Reference](/api-reference/overview)
```
```