Api-development
Detailed documentation and implementation guides.
๐ API Development Guide
This guide provides comprehensive information about developing and consuming Mercury CRM's RESTful APIs, including authentication patterns, best practices, and practical examples.
๐ฏ API Overview
Mercury CRM provides a robust RESTful API architecture designed for:
- ๐ Security - Multi-layer authentication and authorization
- ๐ Performance - Optimized queries and intelligent caching
- ๐ Scalability - Rate limiting and load balancing
- ๐ Documentation - Interactive Swagger documentation
Base URL Structure
Production: https://mercury-crm.com/api
Staging: https://staging.mercury-crm.com/api
Development: http://localhost:8000/api
๐ Authentication
Bearer Token Authentication
All API requests require authentication via Bearer tokens:
Authorization: Bearer {your-api-token}
Content-Type: application/json
Accept: application/json
Obtaining Access Tokens
POST /api/auth/login
Content-Type: application/json
{
"email": "user@example.com",
"password": "password123",
"device_name": "mobile_app"
}
Response:
{
"success": true,
"message": "Login successful",
"data": {
"user": {
"id": 1,
"name": "John Doe",
"email": "user@example.com"
},
"token": "1|abc123def456ghi789...",
"token_type": "Bearer"
}
}
Token Management
// Generate API token
$token = $user->createToken('api-access')->plainTextToken;
// Revoke specific token
$user->tokens()->where('id', $tokenId)->delete();
// Revoke all tokens
$user->tokens()->delete();
๐ Request/Response Patterns
Standard Response Format
All API responses follow a consistent structure:
{
"success": true|false,
"message": "Human readable message",
"data": {
// Response payload
},
"meta": {
// Pagination, timing, etc.
},
"errors": {
// Validation errors (if any)
}
}
Success Response Example
{
"success": true,
"message": "Waha sessions retrieved successfully",
"data": [
{
"id": 1,
"name": "business-account-1",
"status": "working",
"created_at": "2024-01-15T10:30:00Z"
}
],
"meta": {
"current_page": 1,
"total": 15,
"per_page": 10
}
}
Error Response Example
{
"success": false,
"message": "Validation failed",
"errors": {
"name": ["The name field is required."],
"email": ["The email must be a valid email address."]
}
}
๐ Core API Endpoints
Waha WhatsApp Integration
Session Management
# List sessions
GET /api/waha/sessions
Authorization: Bearer {token}
# Create session
POST /api/waha/sessions
Authorization: Bearer {token}
Content-Type: application/json
{
"name": "business-account-1",
"config": {
"timeout": 60,
"retry_attempts": 3
}
}
# Get session details
GET /api/waha/sessions/{id}
Authorization: Bearer {token}
# Update session
PUT /api/waha/sessions/{id}
Authorization: Bearer {token}
Content-Type: application/json
{
"name": "updated-account-name",
"config": {
"timeout": 120
}
}
# Delete session
DELETE /api/waha/sessions/{id}
Authorization: Bearer {token}
Session Control
# Get QR code for authentication
GET /api/waha/sessions/{id}/qr
Authorization: Bearer {token}
# Start session
POST /api/waha/sessions/{id}/start
Authorization: Bearer {token}
# Stop session
POST /api/waha/sessions/{id}/stop
Authorization: Bearer {token}
Message Operations
# Send message
POST /api/waha/messages/send
Authorization: Bearer {token}
Content-Type: application/json
{
"session": "business-account-1",
"chatId": "1234567890@c.us",
"text": "Hello from Mercury CRM!",
"options": {
"mentions": ["1234567890@c.us"],
"linkPreview": true
}
}
# Get messages
GET /api/waha/messages?session_id=1&limit=50
Authorization: Bearer {token}
# Mark message as read
POST /api/waha/messages/{id}/read
Authorization: Bearer {token}
Call Logs
# Get all calls
GET /api/waha/calls
Authorization: Bearer {token}
# Get session-specific calls
GET /api/waha/calls/session/{id}
Authorization: Bearer {token}
# Get call statistics
GET /api/waha/calls/session/{id}/stats
Authorization: Bearer {token}
File Management
# Upload file
POST /api/attachments
Authorization: Bearer {token}
Content-Type: multipart/form-data
attachment: (file)
display_name: "Document Name"
type_id: 1
model_type: "App\\Models\\User"
model_id: 123
# Get file
GET /api/attachments/{id}
Authorization: Bearer {token}
# Delete file
DELETE /api/attachments/{id}
Authorization: Bearer {token}
๐ง Advanced Features
Pagination
GET /api/waha/messages?page=2&per_page=25
Authorization: Bearer {token}
Response:
{
"data": [...],
"meta": {
"current_page": 2,
"from": 26,
"last_page": 5,
"per_page": 25,
"to": 50,
"total": 125
},
"links": {
"first": "/api/waha/messages?page=1",
"last": "/api/waha/messages?page=5",
"prev": "/api/waha/messages?page=1",
"next": "/api/waha/messages?page=3"
}
}
Filtering and Sorting
# Filter by status and sort by date
GET /api/waha/sessions?status=working&sort=-created_at
Authorization: Bearer {token}
# Search messages
GET /api/waha/messages?search=hello&date_from=2024-01-01&date_to=2024-01-31
Authorization: Bearer {token}
Field Selection
# Select specific fields only
GET /api/waha/sessions?fields=id,name,status
Authorization: Bearer {token}
Including Relationships
# Include related data
GET /api/waha/sessions?include=messages,users
Authorization: Bearer {token}
๐ Rate Limiting
Rate limits are enforced to ensure API stability:
HTTP/1.1 200 OK
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 59
X-RateLimit-Reset: 1640995200
Rate Limits:
- Authenticated requests: 60 requests per minute
- Unauthenticated requests: 10 requests per minute
- File uploads: 5 requests per minute
Handling Rate Limits
// JavaScript example with retry logic
async function makeAPIRequest(url, options) {
try {
const response = await fetch(url, options);
if (response.status === 429) {
const resetTime = response.headers.get('X-RateLimit-Reset');
const waitTime = (resetTime * 1000) - Date.now();
await new Promise(resolve => setTimeout(resolve, waitTime));
return makeAPIRequest(url, options); // Retry
}
return response.json();
} catch (error) {
console.error('API request failed:', error);
throw error;
}
}
๐ก๏ธ Error Handling
HTTP Status Codes
| Code | Meaning | Description |
|---|---|---|
| 200 | OK | Request successful |
| 201 | Created | Resource created successfully |
| 400 | Bad Request | Invalid request syntax |
| 401 | Unauthorized | Authentication required |
| 403 | Forbidden | Insufficient permissions |
| 404 | Not Found | Resource not found |
| 422 | Unprocessable Entity | Validation errors |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Internal Server Error | Server error |
Error Response Structure
{
"success": false,
"message": "The given data was invalid.",
"errors": {
"field_name": [
"Specific error message for this field"
]
},
"debug": {
"request_id": "req_123456789",
"timestamp": "2024-01-15T10:30:00Z"
}
}
Client Error Handling
// PHP example with Guzzle
try {
$response = $client->post('/api/waha/sessions', [
'json' => $sessionData,
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json'
]
]);
$data = json_decode($response->getBody(), true);
} catch (ClientException $e) {
$response = $e->getResponse();
$statusCode = $response->getStatusCode();
$error = json_decode($response->getBody(), true);
if ($statusCode === 422) {
// Handle validation errors
foreach ($error['errors'] as $field => $messages) {
echo "Field: $field, Errors: " . implode(', ', $messages);
}
}
}
๐ Webhooks
Webhook Configuration
Configure webhooks to receive real-time notifications:
POST /api/webhooks
Authorization: Bearer {token}
Content-Type: application/json
{
"url": "https://your-app.com/webhooks/waha",
"events": ["message.received", "call.incoming"],
"secret": "your-webhook-secret"
}
Webhook Payload
{
"event": "message.received",
"session": "business-account-1",
"timestamp": "2024-01-15T10:30:00Z",
"payload": {
"id": "msg_123456",
"from": "1234567890@c.us",
"body": "Hello!",
"type": "text"
}
}
Webhook Verification
// Verify webhook signature
function verifyWebhook($payload, $signature, $secret) {
$expectedSignature = hash_hmac('sha256', $payload, $secret);
return hash_equals($expectedSignature, $signature);
}
// In your webhook handler
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
if (!verifyWebhook($payload, $signature, $webhookSecret)) {
http_response_code(401);
exit('Invalid signature');
}
$data = json_decode($payload, true);
// Process webhook data...
๐งช Testing APIs
Using cURL
# Test authentication
curl -X POST https://api.mercury-crm.com/api/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"user@example.com","password":"password123"}'
# Test authenticated endpoint
curl -X GET https://api.mercury-crm.com/api/waha/sessions \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Accept: application/json"
Using Postman
-
Create Environment Variables:
base_url:https://api.mercury-crm.com/apiauth_token:Your Bearer Token
-
Authentication Setup:
Type: Bearer Token Token: {{auth_token}} -
Pre-request Script for Auto-auth:
pm.sendRequest({ url: pm.environment.get("base_url") + "/auth/login", method: 'POST', header: { 'Content-Type': 'application/json', }, body: { mode: 'raw', raw: JSON.stringify({ email: "your-email@example.com", password: "your-password" }) } }, function (err, response) { if (response.json().success) { pm.environment.set("auth_token", response.json().data.token); } });
PHP SDK Example
// Create a simple SDK wrapper
class MercuryCRMAPI
{
private $baseUrl;
private $token;
private $client;
public function __construct($baseUrl, $token)
{
$this->baseUrl = rtrim($baseUrl, '/');
$this->token = $token;
$this->client = new GuzzleHttp\Client();
}
public function getWahaSessions($params = [])
{
return $this->makeRequest('GET', '/waha/sessions', ['query' => $params]);
}
public function createWahaSession($data)
{
return $this->makeRequest('POST', '/waha/sessions', ['json' => $data]);
}
public function sendMessage($data)
{
return $this->makeRequest('POST', '/waha/messages/send', ['json' => $data]);
}
private function makeRequest($method, $endpoint, $options = [])
{
$options['headers'] = array_merge($options['headers'] ?? [], [
'Authorization' => 'Bearer ' . $this->token,
'Accept' => 'application/json'
]);
$response = $this->client->request(
$method,
$this->baseUrl . $endpoint,
$options
);
return json_decode($response->getBody(), true);
}
}
// Usage
$api = new MercuryCRMAPI('https://api.mercury-crm.com/api', $token);
$sessions = $api->getWahaSessions(['status' => 'working']);
๐ฏ Best Practices
Request Best Practices
-
Always Include Accept Header
Accept: application/json -
Use Proper HTTP Methods
- GET: Retrieve data
- POST: Create resources
- PUT: Update entire resource
- PATCH: Partial updates
- DELETE: Remove resources
-
Handle Pagination
// Always check for pagination do { $response = $api->getMessages(['page' => $page]); $messages = array_merge($messages, $response['data']); $page++; } while ($response['meta']['current_page'] < $response['meta']['last_page']); -
Implement Retry Logic
function apiCallWithRetry($callback, $maxRetries = 3) { $attempt = 0; do { try { return $callback(); } catch (Exception $e) { $attempt++; if ($attempt >= $maxRetries) { throw $e; } sleep(pow(2, $attempt)); // Exponential backoff } } while ($attempt < $maxRetries); }
Performance Optimization
-
Use Field Selection
GET /api/waha/sessions?fields=id,name,status -
Leverage Caching
// Cache frequently accessed data $sessions = Cache::remember('user_sessions_' . $userId, 300, function () use ($api) { return $api->getWahaSessions(); }); -
Batch Operations When Possible
POST /api/waha/messages/bulk Content-Type: application/json { "messages": [ {"chatId": "123@c.us", "text": "Message 1"}, {"chatId": "456@c.us", "text": "Message 2"} ] }
Security Best Practices
-
Store Tokens Securely
// Use environment variables or secure storage $token = env('MERCURY_CRM_API_TOKEN'); -
Validate Webhook Signatures
// Always verify webhook authenticity if (!verifyWebhookSignature($payload, $signature, $secret)) { return response('Unauthorized', 401); } -
Use HTTPS in Production
// Enforce HTTPS for all API calls if (!request()->secure() && app()->environment('production')) { abort(403, 'HTTPS required'); }
๐ Interactive Documentation
Swagger UI
Access interactive API documentation:
- Admin API: /docs/admin
- Instructor API: /docs/instructor
Testing in Swagger
- Authenticate: Click "Authorize" button
- Enter Token:
Bearer YOUR_TOKEN_HERE - Test Endpoints: Use "Try it out" feature
- View Responses: See real response structures
๐ Debugging
Debug Headers
Add debug information to responses:
X-Debug-Mode: true
Debug Response:
{
"data": {...},
"debug": {
"queries": 5,
"query_time": "23.5ms",
"memory_usage": "12MB",
"request_id": "req_123456789"
}
}
Logging API Requests
// Log all API requests
class APIRequestLogger
{
public function log($request, $response, $duration)
{
Log::info('API Request', [
'method' => $request->method(),
'url' => $request->fullUrl(),
'status' => $response->status(),
'duration' => $duration . 'ms',
'user_id' => auth()->id(),
'ip' => $request->ip()
]);
}
}
๐ Quick Start Checklist
- [ ] Obtain API token via
/api/auth/login - [ ] Set up authentication headers
- [ ] Test basic endpoints with Postman/cURL
- [ ] Implement error handling
- [ ] Add rate limiting awareness
- [ ] Set up webhook handlers (if needed)
- [ ] Configure monitoring and logging
For complete API reference, visit our Interactive Swagger Documentation. For module-specific guides, see Waha Documentation and Database Guide.