API Reference
Mail
Mail API

Mail API

Base URL: https://mail-api.pcampus.co


Send Email

POST /v1/mail/send

ส่ง transactional email ทันที

POST https://mail-api.pcampus.co/v1/mail/send
Authorization: Bearer <pip_api_key>
x-tenant-id: your-tenant-id
 
{
  "to": "somchai@example.com",
  "templateId": "tmpl_order_confirm",
  "variables": {
    "customerName": "สมชาย",
    "orderId": "ORD-001",
    "total": "฿850",
    "items": [
      { "name": "Amlodipine 5mg 30 เม็ด", "qty": 1, "price": "฿180" }
    ]
  },
  "from": {
    "name": "Pharmacy App",
    "email": "noreply@pharmacy-app.co.th"
  }
}

Response:

{
  "messageId": "msg_xxx",
  "status": "queued",
  "to": "somchai@example.com",
  "queuedAt": "2026-07-15T10:00:00.000Z"
}

POST /v1/mail/send-raw

ส่ง email โดยไม่ใช้ template (raw HTML)

POST https://mail-api.pcampus.co/v1/mail/send-raw
Authorization: Bearer <pip_api_key>
 
{
  "to": ["somchai@example.com"],
  "subject": "ยืนยันคำสั่งซื้อ #ORD-001",
  "html": "<h1>ขอบคุณครับ</h1><p>คำสั่งซื้อของคุณได้รับแล้ว</p>",
  "from": { "name": "Pharmacy", "email": "noreply@pharmacy-app.co.th" }
}

Templates

GET /v1/templates

POST /v1/templates — HTML

สร้าง template แบบ raw HTML:

POST https://mail-api.pcampus.co/v1/templates
Authorization: Bearer <pip_api_key>
x-tenant-id: your-tenant-id
 
{
  "templateId": "tmpl_order_confirm",
  "name": "Order Confirmation",
  "type": "html",
  "subject": "ยืนยันคำสั่งซื้อ #{{orderId}}",
  "htmlBody": "<h1>สวัสดีครับ {{customerName}}</h1><p>คำสั่งซื้อ {{orderId}} ได้รับแล้วครับ</p>",
  "variables": ["customerName", "orderId", "total", "items"]
}

POST /v1/templates — Visual Block Builder

สร้าง template แบบ block-based (type: "block") — block JSON render เป็น responsive HTML ณ เวลาส่ง:

POST https://mail-api.pcampus.co/v1/templates
Authorization: Bearer <pip_api_key>
x-tenant-id: your-tenant-id
 
{
  "templateId": "tmpl_winback",
  "name": "Win-back Campaign",
  "type": "block",
  "subject": "คิดถึงคุณ {{customerName}} ครับ",
  "blocks": [
    {
      "type": "header",
      "logo": "https://cdn.pcampus.co/pharmacy/logo.png",
      "backgroundColor": "#2563eb",
      "brandName": "Pharmacy App"
    },
    {
      "type": "hero_image",
      "imageUrl": "https://cdn.pcampus.co/pharmacy/winback-banner.jpg",
      "linkUrl": "{{shopUrl}}",
      "altText": "กลับมาซื้อยากับเราได้เลย"
    },
    {
      "type": "text",
      "content": "สวัสดีครับ คุณ {{customerName}} ยา {{lastProduct}} ของคุณน่าจะใกล้หมดแล้วนะครับ",
      "fontSize": "16px"
    },
    {
      "type": "button",
      "label": "สั่งยาซ้ำเลยครับ",
      "url": "{{reorderUrl}}",
      "style": "filled",
      "color": "#2563eb"
    },
    { "type": "divider" },
    {
      "type": "footer",
      "unsubscribeText": "ไม่ต้องการรับอีเมล? {{unsubscribeLink}}",
      "copyright": "© 2026 Pharmacy App"
    }
  ],
  "variables": ["customerName", "lastProduct", "reorderUrl", "shopUrl", "unsubscribeLink"]
}

Block types: header | hero_image | text | button | product_card | divider | columns | social | footer

POST /v1/templates/:templateId/render

Preview template — render block JSON เป็น HTML ด้วย test variables:

POST https://mail-api.pcampus.co/v1/templates/tmpl_winback/render
Authorization: Bearer <pip_api_key>
 
{
  "variables": {
    "customerName": "สมชาย",
    "lastProduct": "Amlodipine 5mg",
    "reorderUrl": "https://pharmacy-app.co.th/reorder/cust_001",
    "shopUrl": "https://pharmacy-app.co.th"
  }
}

Response:

{
  "html": "<html><!-- responsive email HTML via MJML --></html>",
  "subject": "คิดถึงคุณ สมชาย ครับ"
}

PATCH /v1/templates/:templateId

DELETE /v1/templates/:templateId


Delivery Status

GET /v1/mail/:messageId

GET https://mail-api.pcampus.co/v1/mail/msg_xxx
Authorization: Bearer <pip_api_key>

Response:

{
  "messageId": "msg_xxx",
  "to": "somchai@example.com",
  "subject": "ยืนยันคำสั่งซื้อ #ORD-001",
  "status": "delivered",
  "sentAt": "2026-07-15T10:00:00.000Z",
  "deliveredAt": "2026-07-15T10:00:05.000Z",
  "openedAt": "2026-07-15T10:15:00.000Z",
  "clickedAt": null,
  "bounced": false
}

Status values: queued | sent | delivered | opened | clicked | bounced | spam


Subscriber Lists

POST /v1/lists

สร้าง subscriber list สำหรับ marketing email

POST https://mail-api.pcampus.co/v1/lists
Authorization: Bearer <pip_api_key>
 
{
  "name": "ลูกค้า at-risk",
  "description": "ลูกค้าที่ไม่ซื้อเกิน 60 วัน"
}

POST /v1/lists/:listId/subscribers

เพิ่ม subscriber

POST https://mail-api.pcampus.co/v1/lists/lst_xxx/subscribers
Authorization: Bearer <pip_api_key>
 
{
  "subscribers": [
    { "email": "somchai@example.com", "name": "สมชาย" },
    { "email": "somsri@example.com", "name": "สมศรี" }
  ]
}

DELETE /v1/lists/:listId/subscribers/:email


Domain Authentication

GET /v1/domains

ดู domain authentication status

GET https://mail-api.pcampus.co/v1/domains
Authorization: Bearer <pip_api_key>
x-tenant-id: your-tenant-id

Response:

{
  "domains": [
    {
      "domain": "pharmacy-app.co.th",
      "spf": "verified",
      "dkim": "verified",
      "dmarc": "pending",
      "verifiedAt": "2026-07-01T00:00:00.000Z"
    }
  ]
}

POST /v1/domains

POST https://mail-api.pcampus.co/v1/domains
Authorization: Bearer <pip_api_key>
 
{ "domain": "pharmacy-app.co.th" }

Response จะ return DNS records (SPF, DKIM, DMARC) ที่ต้องเพิ่มใน DNS provider


Digest Templates

POST /v1/digest/templates

สร้าง digest template (personalized หรือ group):

POST https://mail-api.pcampus.co/v1/digest/templates
Authorization: Bearer <pip_api_key>
x-tenant-id: your-tenant-id
 
{
  "templateId": "tmpl_monthly_summary",
  "name": "Monthly Customer Digest",
  "type": "digest",
  "subject": "สรุปกิจกรรมของคุณ {{customerName}} — {{month}}",
  "digestConfig": {
    "dataSource": "customer_story",
    "personalized": true,
    "fields": [
      "totalSpend30d",
      "visitCount30d",
      "topProducts",
      "loyaltyPoints",
      "nextReward",
      "recommendations"
    ]
  },
  "blocks": [
    { "type": "header", "brandName": "Pharmacy App" },
    {
      "type": "stat_row",
      "stats": [
        { "label": "ยอดซื้อรวม", "value": "{{totalSpend30d}}", "unit": "บาท" },
        { "label": "จำนวนครั้ง", "value": "{{visitCount30d}}", "unit": "ครั้ง" },
        { "label": "คะแนนสะสม", "value": "{{loyaltyPoints}}", "unit": "แต้ม" }
      ]
    },
    { "type": "product_list", "title": "สินค้าที่ซื้อบ่อย", "items": "{{topProducts}}" },
    { "type": "footer" }
  ]
}

digestConfig.fields ที่ระบุจะถูก pull จาก Customer Story ของแต่ละ recipient อัตโนมัติ — ไม่ต้องส่ง variables ตอน send

POST /v1/digest/templates/:templateId/preview

Preview digest email ของ customer คนหนึ่ง:

POST https://mail-api.pcampus.co/v1/digest/templates/tmpl_monthly_summary/preview
Authorization: Bearer <pip_api_key>
 
{ "customerId": "cust_001" }

Response: rendered HTML + subject สำหรับ customer นั้น

GET /v1/digest/templates

PATCH /v1/digest/templates/:templateId

DELETE /v1/digest/templates/:templateId


Scheduler

GET /v1/scheduler/broadcasts

List scheduled email broadcasts

GET https://mail-api.pcampus.co/v1/scheduler/broadcasts?status=scheduled&from=2026-07-01&to=2026-07-31
Authorization: Bearer <pip_api_key>
x-tenant-id: your-tenant-id

Response:

{
  "data": [
    {
      "broadcastId": "bcast_abc",
      "name": "Monthly Customer Digest",
      "templateId": "tmpl_monthly_summary",
      "templateType": "digest",
      "recipientCount": 1204,
      "scheduledAt": "2026-07-18T08:00:00.000Z",
      "status": "scheduled",
      "recurrence": { "cron": "0 8 1 * *", "timezone": "Asia/Bangkok" }
    },
    {
      "broadcastId": "bcast_def",
      "name": "VIP Weekly Report",
      "templateId": "tmpl_vip_weekly",
      "templateType": "digest",
      "recipientCount": 5,
      "scheduledAt": "2026-07-21T09:00:00.000Z",
      "status": "scheduled",
      "recurrence": { "cron": "0 9 * * 1", "timezone": "Asia/Bangkok" }
    }
  ]
}

POST /v1/scheduler/broadcasts

สร้าง scheduled email broadcast

POST https://mail-api.pcampus.co/v1/scheduler/broadcasts
Authorization: Bearer <pip_api_key>
x-tenant-id: your-tenant-id
 
{
  "name": "Monthly Customer Digest — สิงหาคม",
  "templateId": "tmpl_monthly_summary",
  "recipients": {
    "type": "segment",
    "segmentId": "seg_active_customers"
  },
  "scheduledAt": "2026-08-01T08:00:00.000Z",
  "recurrence": {
    "cron": "0 8 1 * *",
    "timezone": "Asia/Bangkok"
  },
  "deliveryWindow": {
    "start": "07:00",
    "end": "20:00",
    "timezone": "Asia/Bangkok"
  }
}

recipients.type options: segment | list | ids

Response:

{
  "broadcastId": "bcast_ghi",
  "status": "scheduled",
  "scheduledAt": "2026-08-01T08:00:00.000Z",
  "estimatedRecipients": 1204
}

GET /v1/scheduler/broadcasts/:broadcastId

ดู broadcast detail พร้อม delivery stats (สำหรับ broadcast ที่ส่งแล้ว):

{
  "broadcastId": "bcast_abc",
  "status": "sent",
  "sentAt": "2026-07-18T08:00:05.000Z",
  "stats": {
    "total": 1204,
    "delivered": 1189,
    "opened": 623,
    "clicked": 201,
    "bounced": 15,
    "openRate": "52.4%",
    "clickRate": "16.9%"
  }
}

PATCH /v1/scheduler/broadcasts/:broadcastId

แก้ไข broadcast ที่ยัง scheduled — แก้ได้จนถึง 5 นาทีก่อน scheduledAt

DELETE /v1/scheduler/broadcasts/:broadcastId

ยกเลิก broadcast (status → cancelled)

Platform docs → · Notification API →

Mail API

Base URL: https://mail-api.pcampus.co


Send Email

POST /v1/mail/send

Send a transactional email immediately.

POST https://mail-api.pcampus.co/v1/mail/send
Authorization: Bearer <pip_api_key>
x-tenant-id: your-tenant-id
 
{
  "to": "somchai@example.com",
  "templateId": "tmpl_order_confirm",
  "variables": {
    "customerName": "สมชาย",
    "orderId": "ORD-001",
    "total": "฿850",
    "items": [
      { "name": "Amlodipine 5mg 30 เม็ด", "qty": 1, "price": "฿180" }
    ]
  },
  "from": {
    "name": "Pharmacy App",
    "email": "noreply@pharmacy-app.co.th"
  }
}

Response:

{
  "messageId": "msg_xxx",
  "status": "queued",
  "to": "somchai@example.com",
  "queuedAt": "2026-07-15T10:00:00.000Z"
}

POST /v1/mail/send-raw

Send an email without a template (raw HTML).

POST https://mail-api.pcampus.co/v1/mail/send-raw
Authorization: Bearer <pip_api_key>
 
{
  "to": ["somchai@example.com"],
  "subject": "ยืนยันคำสั่งซื้อ #ORD-001",
  "html": "<h1>ขอบคุณครับ</h1><p>คำสั่งซื้อของคุณได้รับแล้ว</p>",
  "from": { "name": "Pharmacy", "email": "noreply@pharmacy-app.co.th" }
}

Templates

GET /v1/templates

POST /v1/templates — HTML

Create a raw HTML template:

POST https://mail-api.pcampus.co/v1/templates
Authorization: Bearer <pip_api_key>
x-tenant-id: your-tenant-id
 
{
  "templateId": "tmpl_order_confirm",
  "name": "Order Confirmation",
  "type": "html",
  "subject": "ยืนยันคำสั่งซื้อ #{{orderId}}",
  "htmlBody": "<h1>สวัสดีครับ {{customerName}}</h1><p>คำสั่งซื้อ {{orderId}} ได้รับแล้วครับ</p>",
  "variables": ["customerName", "orderId", "total", "items"]
}

POST /v1/templates — Visual Block Builder

Create a block-based template (type: "block") — block JSON is rendered as responsive HTML at send time:

POST https://mail-api.pcampus.co/v1/templates
Authorization: Bearer <pip_api_key>
x-tenant-id: your-tenant-id
 
{
  "templateId": "tmpl_winback",
  "name": "Win-back Campaign",
  "type": "block",
  "subject": "คิดถึงคุณ {{customerName}} ครับ",
  "blocks": [
    {
      "type": "header",
      "logo": "https://cdn.pcampus.co/pharmacy/logo.png",
      "backgroundColor": "#2563eb",
      "brandName": "Pharmacy App"
    },
    {
      "type": "hero_image",
      "imageUrl": "https://cdn.pcampus.co/pharmacy/winback-banner.jpg",
      "linkUrl": "{{shopUrl}}",
      "altText": "กลับมาซื้อยากับเราได้เลย"
    },
    {
      "type": "text",
      "content": "สวัสดีครับ คุณ {{customerName}} ยา {{lastProduct}} ของคุณน่าจะใกล้หมดแล้วนะครับ",
      "fontSize": "16px"
    },
    {
      "type": "button",
      "label": "สั่งยาซ้ำเลยครับ",
      "url": "{{reorderUrl}}",
      "style": "filled",
      "color": "#2563eb"
    },
    { "type": "divider" },
    {
      "type": "footer",
      "unsubscribeText": "ไม่ต้องการรับอีเมล? {{unsubscribeLink}}",
      "copyright": "© 2026 Pharmacy App"
    }
  ],
  "variables": ["customerName", "lastProduct", "reorderUrl", "shopUrl", "unsubscribeLink"]
}

Block types: header | hero_image | text | button | product_card | divider | columns | social | footer

POST /v1/templates/:templateId/render

Preview a template — renders block JSON into HTML using test variables:

POST https://mail-api.pcampus.co/v1/templates/tmpl_winback/render
Authorization: Bearer <pip_api_key>
 
{
  "variables": {
    "customerName": "สมชาย",
    "lastProduct": "Amlodipine 5mg",
    "reorderUrl": "https://pharmacy-app.co.th/reorder/cust_001",
    "shopUrl": "https://pharmacy-app.co.th"
  }
}

Response:

{
  "html": "<html><!-- responsive email HTML via MJML --></html>",
  "subject": "คิดถึงคุณ สมชาย ครับ"
}

PATCH /v1/templates/:templateId

DELETE /v1/templates/:templateId


Delivery Status

GET /v1/mail/:messageId

GET https://mail-api.pcampus.co/v1/mail/msg_xxx
Authorization: Bearer <pip_api_key>

Response:

{
  "messageId": "msg_xxx",
  "to": "somchai@example.com",
  "subject": "ยืนยันคำสั่งซื้อ #ORD-001",
  "status": "delivered",
  "sentAt": "2026-07-15T10:00:00.000Z",
  "deliveredAt": "2026-07-15T10:00:05.000Z",
  "openedAt": "2026-07-15T10:15:00.000Z",
  "clickedAt": null,
  "bounced": false
}

Status values: queued | sent | delivered | opened | clicked | bounced | spam


Subscriber Lists

POST /v1/lists

Create a subscriber list for marketing email.

POST https://mail-api.pcampus.co/v1/lists
Authorization: Bearer <pip_api_key>
 
{
  "name": "ลูกค้า at-risk",
  "description": "ลูกค้าที่ไม่ซื้อเกิน 60 วัน"
}

POST /v1/lists/:listId/subscribers

Add subscribers.

POST https://mail-api.pcampus.co/v1/lists/lst_xxx/subscribers
Authorization: Bearer <pip_api_key>
 
{
  "subscribers": [
    { "email": "somchai@example.com", "name": "สมชาย" },
    { "email": "somsri@example.com", "name": "สมศรี" }
  ]
}

DELETE /v1/lists/:listId/subscribers/:email


Domain Authentication

GET /v1/domains

View domain authentication status.

GET https://mail-api.pcampus.co/v1/domains
Authorization: Bearer <pip_api_key>
x-tenant-id: your-tenant-id

Response:

{
  "domains": [
    {
      "domain": "pharmacy-app.co.th",
      "spf": "verified",
      "dkim": "verified",
      "dmarc": "pending",
      "verifiedAt": "2026-07-01T00:00:00.000Z"
    }
  ]
}

POST /v1/domains

POST https://mail-api.pcampus.co/v1/domains
Authorization: Bearer <pip_api_key>
 
{ "domain": "pharmacy-app.co.th" }

The response returns DNS records (SPF, DKIM, DMARC) that must be added to your DNS provider.


Digest Templates

POST /v1/digest/templates

Create a digest template (personalized or group):

POST https://mail-api.pcampus.co/v1/digest/templates
Authorization: Bearer <pip_api_key>
x-tenant-id: your-tenant-id
 
{
  "templateId": "tmpl_monthly_summary",
  "name": "Monthly Customer Digest",
  "type": "digest",
  "subject": "สรุปกิจกรรมของคุณ {{customerName}} — {{month}}",
  "digestConfig": {
    "dataSource": "customer_story",
    "personalized": true,
    "fields": [
      "totalSpend30d",
      "visitCount30d",
      "topProducts",
      "loyaltyPoints",
      "nextReward",
      "recommendations"
    ]
  },
  "blocks": [
    { "type": "header", "brandName": "Pharmacy App" },
    {
      "type": "stat_row",
      "stats": [
        { "label": "ยอดซื้อรวม", "value": "{{totalSpend30d}}", "unit": "บาท" },
        { "label": "จำนวนครั้ง", "value": "{{visitCount30d}}", "unit": "ครั้ง" },
        { "label": "คะแนนสะสม", "value": "{{loyaltyPoints}}", "unit": "แต้ม" }
      ]
    },
    { "type": "product_list", "title": "สินค้าที่ซื้อบ่อย", "items": "{{topProducts}}" },
    { "type": "footer" }
  ]
}

The digestConfig.fields specified are automatically pulled from each recipient's Customer Story — no need to pass variables at send time.

POST /v1/digest/templates/:templateId/preview

Preview the digest email for a specific customer:

POST https://mail-api.pcampus.co/v1/digest/templates/tmpl_monthly_summary/preview
Authorization: Bearer <pip_api_key>
 
{ "customerId": "cust_001" }

Response: Rendered HTML + subject for that customer.

GET /v1/digest/templates

PATCH /v1/digest/templates/:templateId

DELETE /v1/digest/templates/:templateId


Scheduler

GET /v1/scheduler/broadcasts

List scheduled email broadcasts.

GET https://mail-api.pcampus.co/v1/scheduler/broadcasts?status=scheduled&from=2026-07-01&to=2026-07-31
Authorization: Bearer <pip_api_key>
x-tenant-id: your-tenant-id

Response:

{
  "data": [
    {
      "broadcastId": "bcast_abc",
      "name": "Monthly Customer Digest",
      "templateId": "tmpl_monthly_summary",
      "templateType": "digest",
      "recipientCount": 1204,
      "scheduledAt": "2026-07-18T08:00:00.000Z",
      "status": "scheduled",
      "recurrence": { "cron": "0 8 1 * *", "timezone": "Asia/Bangkok" }
    },
    {
      "broadcastId": "bcast_def",
      "name": "VIP Weekly Report",
      "templateId": "tmpl_vip_weekly",
      "templateType": "digest",
      "recipientCount": 5,
      "scheduledAt": "2026-07-21T09:00:00.000Z",
      "status": "scheduled",
      "recurrence": { "cron": "0 9 * * 1", "timezone": "Asia/Bangkok" }
    }
  ]
}

POST /v1/scheduler/broadcasts

Create a scheduled email broadcast.

POST https://mail-api.pcampus.co/v1/scheduler/broadcasts
Authorization: Bearer <pip_api_key>
x-tenant-id: your-tenant-id
 
{
  "name": "Monthly Customer Digest — สิงหาคม",
  "templateId": "tmpl_monthly_summary",
  "recipients": {
    "type": "segment",
    "segmentId": "seg_active_customers"
  },
  "scheduledAt": "2026-08-01T08:00:00.000Z",
  "recurrence": {
    "cron": "0 8 1 * *",
    "timezone": "Asia/Bangkok"
  },
  "deliveryWindow": {
    "start": "07:00",
    "end": "20:00",
    "timezone": "Asia/Bangkok"
  }
}

recipients.type options: segment | list | ids

Response:

{
  "broadcastId": "bcast_ghi",
  "status": "scheduled",
  "scheduledAt": "2026-08-01T08:00:00.000Z",
  "estimatedRecipients": 1204
}

GET /v1/scheduler/broadcasts/:broadcastId

View broadcast detail with delivery stats (for broadcasts that have been sent):

{
  "broadcastId": "bcast_abc",
  "status": "sent",
  "sentAt": "2026-07-18T08:00:05.000Z",
  "stats": {
    "total": 1204,
    "delivered": 1189,
    "opened": 623,
    "clicked": 201,
    "bounced": 15,
    "openRate": "52.4%",
    "clickRate": "16.9%"
  }
}

PATCH /v1/scheduler/broadcasts/:broadcastId

Edit a scheduled broadcast — changes can be made up to 5 minutes before scheduledAt.

DELETE /v1/scheduler/broadcasts/:broadcastId

Cancel a broadcast (status → cancelled).

Platform docs → · Notification API →