API Reference Guide
Complete REST API documentation for the CRM platform
Last Updated: October 27, 2025
Table of Contents
- Overview
- Authentication
- Base URL
- Common Headers
- Error Codes
- Rate Limiting
- Public Endpoints
- Contact Endpoints
- Campaign Endpoints
- Distribution List Endpoints
- Email Template Endpoints
- Tag Endpoints
- Analytics Endpoints
Overview
The CRM platform provides a RESTful API with 30+ endpoints for managing contacts, campaigns, distribution lists, and email templates. The API uses JSON for request and response bodies.
API Characteristics
- Protocol: HTTPS only
- Format: JSON
- Authentication: JWT tokens via Amazon Cognito
- Region: ca-central-1 (Canada Central)
- Architecture: AWS Lambda + API Gateway
Versioning
Current version: v1 (no version prefix in URLs)
Authentication
Overview
All authenticated endpoints require a valid JWT token obtained from Amazon Cognito. Public endpoints (subscription, unsubscribe) do not require authentication.
Obtaining Tokens
Step 1: Authenticate with Cognito
// Using Amazon Cognito Identity SDK
const authenticationData = {
Username: 'user@example.com',
Password: 'password123'
};
const authenticationDetails = new AmazonCognitoIdentity.AuthenticationDetails(authenticationData);
const poolData = {
UserPoolId: 'ca-central-1_KY0FKXuer',
ClientId: '65ejgncojr16d12d3nktdmg93'
};
const userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData);
const userData = {
Username: 'user@example.com',
Pool: userPool
};
const cognitoUser = new AmazonCognitoIdentity.CognitoUser(userData);
cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: function(result) {
const idToken = result.getIdToken().getJwtToken();
console.log('Token:', idToken);
},
onFailure: function(err) {
console.error('Authentication failed:', err);
}
});
Step 2: Include Token in Requests
fetch('https://zqkprqp60h.execute-api.ca-central-1.amazonaws.com/Prod/contacts', {
method: 'GET',
headers: {
'Authorization': `Bearer ${idToken}`,
'Content-Type': 'application/json'
}
});
Token Format
JWT tokens include: - sub: User ID (UUID) - email: User email address - custom:tenantId: Tenant ID for multi-tenancy - custom:organizationName: Organization name - exp: Expiration timestamp (1 hour)
Token Refresh
Tokens expire after 1 hour. Use the refresh token to obtain new tokens without re-authentication.
Base URL
Production: https://zqkprqp60h.execute-api.ca-central-1.amazonaws.com/Prod
Replace with your actual API Gateway URL from AWS deployment.
Example:
https://abc123xyz.execute-api.ca-central-1.amazonaws.com/Prod
Common Headers
Request Headers
| Header | Required | Description |
|---|---|---|
| Authorization | Yes (except public) | Bearer token from Cognito |
| Content-Type | Yes | application/json |
| Accept | No | application/json |
Response Headers
| Header | Description |
|---|---|
| Content-Type | application/json |
| Access-Control-Allow-Origin | * (CORS enabled) |
| Access-Control-Allow-Methods | GET, POST, PUT, DELETE, OPTIONS |
Error Codes
HTTP Status Codes
| Code | Meaning | Description |
|---|---|---|
| 200 | OK | Request successful |
| 201 | Created | Resource created successfully |
| 400 | Bad Request | Invalid request parameters |
| 401 | Unauthorized | Missing or invalid authentication |
| 403 | Forbidden | Insufficient permissions |
| 404 | Not Found | Resource not found |
| 500 | Internal Server Error | Server error occurred |
Error Response Format
{
"error": "Error message describing what went wrong"
}
Common Errors
401 Unauthorized:
{
"error": "Unauthorized - Missing or invalid token"
}
400 Bad Request:
{
"error": "Missing required field: email"
}
404 Not Found:
{
"error": "Contact not found"
}
500 Internal Server Error:
{
"error": "Failed to process request"
}
Rate Limiting
Current Limits
- Authenticated endpoints: No rate limits (controlled by Lambda concurrency)
- Public endpoints: No rate limits (consider implementing for production)
Best Practices
- Implement client-side request throttling
- Use exponential backoff for retries
- Cache responses when appropriate
- Batch operations when possible
Public Endpoints
Subscribe to List
Endpoint: POST /public/subscribe
Authentication: None required
Description: Add a new contact to a distribution list without authentication.
Request Body:
{
"email": "user@example.com",
"listId": "550e8400-e29b-41d4-a716-446655440000",
"firstName": "John",
"lastName": "Doe"
}
Parameters:
| Field | Type | Required | Description |
|---|---|---|---|
| string | Yes | Valid email address | |
| listId | string | Yes | Distribution list UUID |
| firstName | string | No | Contact's first name |
| lastName | string | No | Contact's last name |
Success Response (201):
{
"message": "Successfully subscribed to the list",
"contactId": "abc123-contact-id",
"listId": "550e8400-e29b-41d4-a716-446655440000"
}
Error Response (400):
{
"error": "Missing required field: email"
}
Example:
const response = await fetch('https://zqkprqp60h.execute-api.ca-central-1.amazonaws.com/Prod/public/subscribe', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: 'user@example.com',
firstName: 'John',
lastName: 'Doe',
listId: '550e8400-e29b-41d4-a716-446655440000'
})
});
const data = await response.json();
console.log(data);
Unsubscribe from List
Endpoint: GET /public/unsubscribe
Authentication: None required
Description: Remove a contact from a distribution list and mark as unsubscribed.
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| string | Yes | Contact email address | |
| listId | string | Yes | Distribution list UUID |
URL Format:
GET /public/unsubscribe?email=user@example.com&listId=550e8400-e29b-41d4-a716-446655440000
Success Response (200):
{
"message": "Successfully unsubscribed"
}
Error Response (400):
{
"error": "Missing required parameter: email"
}
Example:
const email = 'user@example.com';
const listId = '550e8400-e29b-41d4-a716-446655440000';
const response = await fetch(
`https://zqkprqp60h.execute-api.ca-central-1.amazonaws.com/Prod/public/unsubscribe?email=${email}&listId=${listId}`
);
const data = await response.json();
console.log(data);
Contact Endpoints
List Contacts
Endpoint: GET /contacts
Authentication: Required
Description: Retrieve all contacts for the authenticated tenant.
Success Response (200):
{
"contacts": [
{
"contactId": "abc123",
"email": "john@example.com",
"firstName": "John",
"lastName": "Doe",
"organizationName": "Acme Corp",
"status": "active",
"tenantId": "tenant-123",
"createdAt": "2025-01-15T10:30:00Z",
"updatedAt": "2025-01-15T10:30:00Z"
}
]
}
Example:
const response = await fetch('https://zqkprqp60h.execute-api.ca-central-1.amazonaws.com/Prod/contacts', {
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
});
const data = await response.json();
console.log(data.contacts);
Get Contact
Endpoint: GET /contacts/{contactId}
Authentication: Required
Description: Retrieve a specific contact by ID.
Path Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| contactId | string | Yes | Contact UUID |
Success Response (200):
{
"contactId": "abc123",
"email": "john@example.com",
"firstName": "John",
"lastName": "Doe",
"organizationName": "Acme Corp",
"status": "active",
"tenantId": "tenant-123",
"createdAt": "2025-01-15T10:30:00Z",
"updatedAt": "2025-01-15T10:30:00Z"
}
Error Response (404):
{
"error": "Contact not found"
}
Create Contact
Endpoint: POST /contacts
Authentication: Required
Description: Create a new contact.
Request Body:
{
"email": "john@example.com",
"firstName": "John",
"lastName": "Doe",
"organizationName": "Acme Corp",
"status": "active"
}
Parameters:
| Field | Type | Required | Description |
|---|---|---|---|
| string | Yes | Valid email address | |
| firstName | string | No | First name |
| lastName | string | No | Last name |
| organizationName | string | No | Organization name |
| status | string | No | Status (active, unsubscribed, bounced, pending) |
Success Response (201):
{
"message": "Contact created successfully",
"contact": {
"contactId": "abc123",
"email": "john@example.com",
"firstName": "John",
"lastName": "Doe",
"organizationName": "Acme Corp",
"status": "active",
"tenantId": "tenant-123",
"createdAt": "2025-01-15T10:30:00Z"
}
}
Example:
const response = await fetch('https://zqkprqp60h.execute-api.ca-central-1.amazonaws.com/Prod/contacts', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: 'john@example.com',
firstName: 'John',
lastName: 'Doe',
organizationName: 'Acme Corp'
})
});
const data = await response.json();
console.log(data.contact);
Update Contact
Endpoint: PUT /contacts/{contactId}
Authentication: Required
Description: Update an existing contact.
Path Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| contactId | string | Yes | Contact UUID |
Request Body:
{
"firstName": "John",
"lastName": "Doe",
"organizationName": "New Company Inc",
"status": "active"
}
Success Response (200):
{
"message": "Contact updated successfully",
"contact": {
"contactId": "abc123",
"email": "john@example.com",
"firstName": "John",
"lastName": "Doe",
"organizationName": "New Company Inc",
"status": "active",
"updatedAt": "2025-01-15T11:45:00Z"
}
}
Delete Contact
Endpoint: DELETE /contacts/{contactId}
Authentication: Required
Description: Delete a contact permanently.
Path Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| contactId | string | Yes | Contact UUID |
Success Response (200):
{
"message": "Contact deleted successfully"
}
Example:
const response = await fetch(`https://zqkprqp60h.execute-api.ca-central-1.amazonaws.com/Prod/contacts/${contactId}`, {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
});
const data = await response.json();
console.log(data.message);
Campaign Endpoints
List Campaigns
Endpoint: GET /campaigns
Authentication: Required
Description: Retrieve all campaigns for the authenticated tenant.
Success Response (200):
{
"campaigns": [
{
"campaignId": "campaign-123",
"name": "Monthly Newsletter - January 2025",
"subject": "What's New This Month",
"status": "sent",
"sentCount": 250,
"deliveredCount": 245,
"openedCount": 120,
"clickedCount": 45,
"bouncedCount": 5,
"createdAt": "2025-01-10T09:00:00Z",
"sentAt": "2025-01-15T14:00:00Z"
}
]
}
Get Campaign
Endpoint: GET /campaigns/{campaignId}
Authentication: Required
Description: Retrieve a specific campaign by ID.
Success Response (200):
{
"campaignId": "campaign-123",
"name": "Monthly Newsletter - January 2025",
"subject": "What's New This Month",
"htmlBody": "<html>...</html>",
"status": "sent",
"sentCount": 250,
"deliveredCount": 245,
"openedCount": 120,
"clickedCount": 45,
"bouncedCount": 5,
"tenantId": "tenant-123",
"createdAt": "2025-01-10T09:00:00Z",
"sentAt": "2025-01-15T14:00:00Z"
}
Create Campaign
Endpoint: POST /campaigns
Authentication: Required
Description: Create a new email campaign.
Request Body:
{
"name": "Monthly Newsletter - February 2025",
"subject": "February Updates",
"htmlBody": "<html><body><h1>Hello!</h1></body></html>"
}
Parameters:
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Campaign name |
| subject | string | Yes | Email subject line |
| htmlBody | string | Yes | HTML email content |
Success Response (201):
{
"message": "Campaign created successfully",
"campaign": {
"campaignId": "campaign-456",
"name": "Monthly Newsletter - February 2025",
"subject": "February Updates",
"status": "draft",
"createdAt": "2025-02-01T10:00:00Z"
}
}
Send Campaign
Endpoint: POST /campaigns/{campaignId}/send
Authentication: Required
Description: Send a campaign to a distribution list.
Path Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| campaignId | string | Yes | Campaign UUID |
Request Body:
{
"listId": "list-123"
}
Success Response (200):
{
"message": "Campaign sent successfully",
"sentCount": 250
}
Example:
const response = await fetch(
`https://zqkprqp60h.execute-api.ca-central-1.amazonaws.com/Prod/campaigns/${campaignId}/send`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
listId: 'list-123'
})
}
);
const data = await response.json();
console.log(data.message);
Clone Campaign
Endpoint: POST /campaigns/{campaignId}/clone
Authentication: Required
Description: Create a copy of an existing campaign.
Path Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| campaignId | string | Yes | Campaign UUID to clone |
Success Response (201):
{
"message": "Campaign cloned successfully",
"campaign": {
"campaignId": "new-campaign-789",
"name": "Monthly Newsletter - February 2025 (Copy)",
"subject": "February Updates",
"status": "draft",
"createdAt": "2025-02-05T11:00:00Z"
}
}
Delete Campaign
Endpoint: DELETE /campaigns/{campaignId}
Authentication: Required
Description: Delete a campaign permanently.
Success Response (200):
{
"message": "Campaign deleted successfully"
}
Distribution List Endpoints
List Distribution Lists
Endpoint: GET /lists
Authentication: Required
Description: Retrieve all distribution lists for the authenticated tenant.
Success Response (200):
{
"lists": [
{
"listId": "list-123",
"name": "Monthly Newsletter Subscribers",
"description": "Main newsletter distribution list",
"memberCount": 250,
"tenantId": "tenant-123",
"createdAt": "2024-12-01T10:00:00Z"
}
]
}
Get Distribution List
Endpoint: GET /lists/{listId}
Authentication: Required
Description: Retrieve a specific distribution list by ID.
Success Response (200):
{
"listId": "list-123",
"name": "Monthly Newsletter Subscribers",
"description": "Main newsletter distribution list",
"memberCount": 250,
"tenantId": "tenant-123",
"createdAt": "2024-12-01T10:00:00Z"
}
Create Distribution List
Endpoint: POST /lists
Authentication: Required
Description: Create a new distribution list.
Request Body:
{
"name": "Product Launch List",
"description": "Contacts interested in product launches"
}
Parameters:
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | List name |
| description | string | No | List description |
Success Response (201):
{
"message": "List created successfully",
"list": {
"listId": "list-456",
"name": "Product Launch List",
"description": "Contacts interested in product launches",
"memberCount": 0,
"createdAt": "2025-02-01T10:00:00Z"
}
}
Update Distribution List
Endpoint: PUT /lists/{listId}
Authentication: Required
Description: Update an existing distribution list.
Request Body:
{
"name": "Updated List Name",
"description": "Updated description"
}
Success Response (200):
{
"message": "List updated successfully"
}
Delete Distribution List
Endpoint: DELETE /lists/{listId}
Authentication: Required
Description: Delete a distribution list permanently.
Success Response (200):
{
"message": "List deleted successfully"
}
Get List Members
Endpoint: GET /lists/{listId}/members
Authentication: Required
Description: Retrieve all members of a distribution list.
Success Response (200):
{
"members": [
{
"contactId": "contact-123",
"email": "john@example.com",
"firstName": "John",
"lastName": "Doe",
"status": "active",
"addedAt": "2025-01-01T10:00:00Z"
}
]
}
Add Contact to List
Endpoint: POST /lists/{listId}/members
Authentication: Required
Description: Add a contact to a distribution list.
Request Body:
{
"contactId": "contact-123"
}
Success Response (201):
{
"message": "Contact added to list successfully"
}
Remove Contact from List
Endpoint: DELETE /lists/{listId}/members/{contactId}
Authentication: Required
Description: Remove a contact from a distribution list.
Success Response (200):
{
"message": "Contact removed from list successfully"
}
Duplicate Distribution List
Endpoint: POST /lists/{listId}/duplicate
Authentication: Required
Description: Create a copy of a distribution list including all members.
Success Response (201):
{
"message": "List duplicated successfully",
"list": {
"listId": "new-list-789",
"name": "Monthly Newsletter Subscribers (Copy)",
"memberCount": 250,
"createdAt": "2025-02-05T11:00:00Z"
}
}
Email Template Endpoints
List Templates
Endpoint: GET /templates
Authentication: Required
Description: Retrieve all email templates for the authenticated tenant.
Success Response (200):
{
"templates": [
{
"templateId": "template-123",
"name": "Monthly Newsletter Template",
"subject": "{{month}} Newsletter",
"tenantId": "tenant-123",
"createdAt": "2024-11-15T10:00:00Z"
}
]
}
Get Template
Endpoint: GET /templates/{templateId}
Authentication: Required
Description: Retrieve a specific template by ID.
Success Response (200):
{
"templateId": "template-123",
"name": "Monthly Newsletter Template",
"subject": "{{month}} Newsletter",
"htmlBody": "<html>...</html>",
"tenantId": "tenant-123",
"createdAt": "2024-11-15T10:00:00Z"
}
Create Template
Endpoint: POST /templates
Authentication: Required
Description: Create a new email template.
Request Body:
{
"name": "Product Announcement Template",
"subject": "Introducing {{productName}}",
"htmlBody": "<html><body><h1>Check out {{productName}}</h1></body></html>"
}
Success Response (201):
{
"message": "Template created successfully",
"template": {
"templateId": "template-456",
"name": "Product Announcement Template",
"createdAt": "2025-02-01T10:00:00Z"
}
}
Update Template
Endpoint: PUT /templates/{templateId}
Authentication: Required
Description: Update an existing template.
Request Body:
{
"name": "Updated Template Name",
"subject": "Updated Subject",
"htmlBody": "<html>...</html>"
}
Success Response (200):
{
"message": "Template updated successfully"
}
Delete Template
Endpoint: DELETE /templates/{templateId}
Authentication: Required
Description: Delete a template permanently.
Success Response (200):
{
"message": "Template deleted successfully"
}
Tag Endpoints
List Contact Tags
Endpoint: GET /contacts/{contactId}/tags
Authentication: Required
Description: Retrieve all tags for a specific contact.
Success Response (200):
{
"tags": [
{
"tagId": "tag-123",
"tagName": "VIP Customer",
"color": "purple",
"createdAt": "2025-01-10T10:00:00Z"
},
{
"tagId": "tag-456",
"tagName": "Newsletter Subscriber",
"color": "blue",
"createdAt": "2025-01-15T11:00:00Z"
}
]
}
Add Tag to Contact
Endpoint: POST /contacts/{contactId}/tags
Authentication: Required
Description: Add a tag to a contact.
Request Body:
{
"tagName": "VIP Customer",
"color": "purple"
}
Parameters:
| Field | Type | Required | Description |
|---|---|---|---|
| tagName | string | Yes | Tag name |
| color | string | Yes | Color (red, orange, yellow, green, blue, purple, pink, gray) |
Success Response (201):
{
"message": "Tag added successfully",
"tag": {
"tagId": "tag-789",
"tagName": "VIP Customer",
"color": "purple",
"contactId": "contact-123",
"createdAt": "2025-02-01T10:00:00Z"
}
}
Remove Tag from Contact
Endpoint: DELETE /contacts/{contactId}/tags/{tagId}
Authentication: Required
Description: Remove a tag from a contact.
Success Response (200):
{
"message": "Tag removed successfully"
}
Analytics Endpoints
Get Dashboard Statistics
Endpoint: GET /analytics/dashboard
Authentication: Required
Description: Retrieve overall platform statistics for the dashboard.
Success Response (200):
{
"totalCampaigns": 25,
"totalEmailsSent": 5000,
"avgDeliveryRate": 98.5,
"totalContacts": 850,
"campaignsByStatus": {
"draft": 5,
"sent": 18,
"scheduled": 2
},
"deliveryStats": {
"delivered": 4925,
"bounced": 75
},
"contactGrowth": [
{"month": "2024-11", "count": 500},
{"month": "2024-12", "count": 650},
{"month": "2025-01", "count": 850}
],
"topCampaigns": [
{
"name": "January Newsletter",
"openRate": 45.2,
"clickRate": 12.5
}
]
}
Complete Endpoint List
Public Endpoints (No Auth)
POST /public/subscribe- Subscribe to listGET /public/unsubscribe- Unsubscribe from list
Contact Management
GET /contacts- List all contactsGET /contacts/{contactId}- Get contact detailsPOST /contacts- Create contactPUT /contacts/{contactId}- Update contactDELETE /contacts/{contactId}- Delete contact
Campaign Management
GET /campaigns- List all campaignsGET /campaigns/{campaignId}- Get campaign detailsPOST /campaigns- Create campaignPOST /campaigns/{campaignId}/send- Send campaignPOST /campaigns/{campaignId}/clone- Clone campaignDELETE /campaigns/{campaignId}- Delete campaign
Distribution Lists
GET /lists- List all distribution listsGET /lists/{listId}- Get list detailsPOST /lists- Create listPUT /lists/{listId}- Update listDELETE /lists/{listId}- Delete listGET /lists/{listId}/members- Get list membersPOST /lists/{listId}/members- Add contact to listDELETE /lists/{listId}/members/{contactId}- Remove from listPOST /lists/{listId}/duplicate- Duplicate list
Email Templates
GET /templates- List all templatesGET /templates/{templateId}- Get template detailsPOST /templates- Create templatePUT /templates/{templateId}- Update templateDELETE /templates/{templateId}- Delete template
Contact Tags
GET /contacts/{contactId}/tags- List contact tagsPOST /contacts/{contactId}/tags- Add tag to contactDELETE /contacts/{contactId}/tags/{tagId}- Remove tag
Analytics
GET /analytics/dashboard- Get dashboard statistics
Code Examples
Complete JavaScript Client
class CRMClient {
constructor(apiUrl, token) {
this.apiUrl = apiUrl;
this.token = token;
}
async request(endpoint, options = {}) {
const url = `${this.apiUrl}${endpoint}`;
const headers = {
'Content-Type': 'application/json',
...options.headers
};
if (this.token) {
headers['Authorization'] = `Bearer ${this.token}`;
}
const response = await fetch(url, {
...options,
headers
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.error || 'Request failed');
}
return response.json();
}
// Contacts
async listContacts() {
return this.request('/contacts');
}
async getContact(contactId) {
return this.request(`/contacts/${contactId}`);
}
async createContact(contact) {
return this.request('/contacts', {
method: 'POST',
body: JSON.stringify(contact)
});
}
async updateContact(contactId, updates) {
return this.request(`/contacts/${contactId}`, {
method: 'PUT',
body: JSON.stringify(updates)
});
}
async deleteContact(contactId) {
return this.request(`/contacts/${contactId}`, {
method: 'DELETE'
});
}
// Campaigns
async listCampaigns() {
return this.request('/campaigns');
}
async createCampaign(campaign) {
return this.request('/campaigns', {
method: 'POST',
body: JSON.stringify(campaign)
});
}
async sendCampaign(campaignId, listId) {
return this.request(`/campaigns/${campaignId}/send`, {
method: 'POST',
body: JSON.stringify({ listId })
});
}
// Lists
async listDistributionLists() {
return this.request('/lists');
}
async createList(list) {
return this.request('/lists', {
method: 'POST',
body: JSON.stringify(list)
});
}
async addToList(listId, contactId) {
return this.request(`/lists/${listId}/members`, {
method: 'POST',
body: JSON.stringify({ contactId })
});
}
// Tags
async addTag(contactId, tagName, color) {
return this.request(`/contacts/${contactId}/tags`, {
method: 'POST',
body: JSON.stringify({ tagName, color })
});
}
async removeTag(contactId, tagId) {
return this.request(`/contacts/${contactId}/tags/${tagId}`, {
method: 'DELETE'
});
}
// Analytics
async getDashboardStats() {
return this.request('/analytics/dashboard');
}
}
// Usage
const client = new CRMClient('https://zqkprqp60h.execute-api.ca-central-1.amazonaws.com/Prod', 'your-jwt-token');
// Create a contact
const contact = await client.createContact({
email: 'john@example.com',
firstName: 'John',
lastName: 'Doe'
});
// Create and send a campaign
const campaign = await client.createCampaign({
name: 'Welcome Email',
subject: 'Welcome to our platform!',
htmlBody: '<h1>Welcome!</h1>'
});
await client.sendCampaign(campaign.campaign.campaignId, 'list-id');
Postman Collection
Import this JSON into Postman for easy API testing:
{
"info": {
"name": "CRM Platform API",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
"auth": {
"type": "bearer",
"bearer": [
{
"key": "token",
"value": "{{jwt_token}}",
"type": "string"
}
]
},
"variable": [
{
"key": "base_url",
"value": "https://zqkprqp60h.execute-api.ca-central-1.amazonaws.com/Prod"
},
{
"key": "jwt_token",
"value": "your-token-here"
}
],
"item": [
{
"name": "Contacts",
"item": [
{
"name": "List Contacts",
"request": {
"method": "GET",
"url": "{{base_url}}/contacts"
}
},
{
"name": "Create Contact",
"request": {
"method": "POST",
"url": "{{base_url}}/contacts",
"body": {
"mode": "raw",
"raw": "{\n \"email\": \"test@example.com\",\n \"firstName\": \"Test\",\n \"lastName\": \"User\"\n}"
}
}
}
]
}
]
}
Best Practices
1. Error Handling
Always handle errors gracefully:
try {
const response = await fetch('https://zqkprqp60h.execute-api.ca-central-1.amazonaws.com/Prod/contacts', {
headers: { 'Authorization': `Bearer ${token}` }
});
if (!response.ok) {
const error = await response.json();
console.error('API Error:', error.error);
// Show user-friendly message
return;
}
const data = await response.json();
// Process data
} catch (error) {
console.error('Network Error:', error);
// Show connection error message
}
2. Token Management
Store and refresh tokens properly:
// Store token securely
localStorage.setItem('crm_token', token);
// Check expiration before requests
function isTokenExpired(token) {
const payload = JSON.parse(atob(token.split('.')[1]));
return Date.now() >= payload.exp * 1000;
}
// Refresh if needed
if (isTokenExpired(token)) {
token = await refreshToken();
}
3. Request Optimization
Batch requests when possible:
// Instead of multiple sequential requests
const contacts = await Promise.all([
client.getContact('id1'),
client.getContact('id2'),
client.getContact('id3')
]);
4. CORS Handling
Ensure CORS is properly configured:
// API Gateway CORS configuration
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization
Support
For API issues:
- Check CloudWatch Logs: /aws/lambda/crm-*-dev
- Verify authentication tokens
- Review request/response in browser DevTools
- See troubleshooting in COMPLETE_FEATURE_GUIDE.md
Document Version: 1.0 Last Updated: October 27, 2025 API Version: v1