{
  "openapi": "3.1.0",
  "info": {
    "title": "SMS Philippines SMS Campaign API",
    "version": "1.0.0",
    "description": "Schedule one-time or recurring SMS campaigns to a contact group, check progress, and cancel them. A campaign is one or more messages published together under one campaign.id. All times are Asia/Manila (UTC+8) wall-clock.",
    "contact": { "url": "https://smsphilippines.com/developers" }
  },
  "externalDocs": { "url": "https://smsphilippines.com/developers" },
  "servers": [{ "url": "https://api.sms-campaign.smsphilippines.com" }],
  "security": [{ "bearerAuth": [] }],
  "paths": {
    "/publish": {
      "post": {
        "operationId": "publishCampaign",
        "summary": "Schedule, pause, stop or delete a campaign",
        "description": "Set campaign.status to active to schedule (one-time with scheduled_at, or recurring daily, weekly or monthly). Set it to unpublish (pause), stop or delete and post the same campaign.id with the message ids to cancel. Publish again with status active to resume. sender_name is validated on publish and again before each send.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["campaign", "messages"],
                "properties": {
                  "campaign": {
                    "type": "object",
                    "required": ["id", "status"],
                    "properties": {
                      "id": { "type": "string", "format": "uuid" },
                      "status": { "type": "string", "enum": ["active", "unpublish", "stop", "delete"] },
                      "sender_name": { "type": "string" },
                      "contact_group_id": { "type": "string", "format": "uuid" }
                    }
                  },
                  "messages": { "type": "array", "items": { "$ref": "#/components/schemas/CampaignMessage" } }
                }
              },
              "examples": {
                "oneTime": {
                  "summary": "One-time campaign",
                  "value": {
                    "campaign": {
                      "id": "c1a2b3c4-d5e6-4f70-8a9b-0c1d2e3f4a5b",
                      "status": "active",
                      "sender_name": "ZENGLOBAL",
                      "contact_group_id": "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed"
                    },
                    "messages": [
                      {
                        "id": "8f14e45f-ceea-4d3e-9d0d-1c2e3f4a5b6c",
                        "step": 1,
                        "message": "Hi! Don't miss our sale this weekend.",
                        "is_recurring": false,
                        "scheduled_at": "2026-09-20 09:00:00"
                      }
                    ]
                  }
                },
                "weekly": {
                  "summary": "Recurring weekly campaign",
                  "value": {
                    "campaign": {
                      "id": "c1a2b3c4-d5e6-4f70-8a9b-0c1d2e3f4a5b",
                      "status": "active",
                      "sender_name": "ZENGLOBAL",
                      "contact_group_id": "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed"
                    },
                    "messages": [
                      {
                        "id": "8f14e45f-ceea-4d3e-9d0d-1c2e3f4a5b6c",
                        "step": 1,
                        "message": "Weekly reminder: we're open until 9pm every Friday!",
                        "is_recurring": true,
                        "recurrence_frequency": "weekly",
                        "recurrence_days": [5],
                        "recurrence_time": "09:00",
                        "recurrence_start": "2026-09-20",
                        "recurrence_end": "2026-12-31"
                      }
                    ]
                  }
                },
                "pause": {
                  "summary": "Pause a campaign",
                  "value": {
                    "campaign": { "id": "c1a2b3c4-d5e6-4f70-8a9b-0c1d2e3f4a5b", "status": "unpublish" },
                    "messages": [{ "id": "8f14e45f-ceea-4d3e-9d0d-1c2e3f4a5b6c" }]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Campaign updated.",
            "content": {
              "application/json": {
                "example": {
                  "success": true,
                  "action": "active",
                  "sender_name": "ZENGLOBAL",
                  "messages": [{ "id": "8f14e45f-ceea-4d3e-9d0d-1c2e3f4a5b6c", "status": "scheduled", "next_run": "2026-09-20 09:00:00" }]
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/campaign-status": {
      "get": {
        "operationId": "getCampaignStatus",
        "summary": "Get campaign status",
        "description": "Read-only view of every message in a campaign, scoped to your account. Provide campaign_id, message_id, or both. All timestamps are PHT wall-clock.",
        "parameters": [
          { "name": "campaign_id", "in": "query", "schema": { "type": "string", "format": "uuid" } },
          { "name": "message_id", "in": "query", "schema": { "type": "string", "format": "uuid" } },
          {
            "name": "status",
            "in": "query",
            "description": "Repeatable filter, e.g. ?status=sent&status=failed.",
            "schema": { "type": "array", "items": { "type": "string" } },
            "style": "form",
            "explode": true
          }
        ],
        "responses": {
          "200": {
            "description": "Campaign status.",
            "content": {
              "application/json": {
                "example": {
                  "success": true,
                  "campaign_id": "c1a2b3c4-d5e6-4f70-8a9b-0c1d2e3f4a5b",
                  "timezone": "Asia/Manila (UTC+8)",
                  "summary": { "total": 2, "by_status": { "scheduled": 1, "sent": 1 }, "next_run": "2026-09-27 09:00:00", "truncated": false },
                  "messages": [
                    {
                      "message_id": "8f14e45f-ceea-4d3e-9d0d-1c2e3f4a5b6c",
                      "campaign_id": "c1a2b3c4-d5e6-4f70-8a9b-0c1d2e3f4a5b",
                      "step": 1,
                      "status": "sent",
                      "next_run": "2026-09-27 09:00:00",
                      "last_run": "2026-09-20 09:00:03"
                    }
                  ]
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/terminate-campaign": {
      "post": {
        "operationId": "terminateCampaign",
        "summary": "Terminate an entire campaign",
        "description": "Cancels every message in the campaign in one call. Calling again on an already-terminated campaign returns count: 0 rather than an error.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["campaign_id"],
                "properties": { "campaign_id": { "type": "string", "format": "uuid" } }
              },
              "example": { "campaign_id": "c1a2b3c4-d5e6-4f70-8a9b-0c1d2e3f4a5b" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Campaign terminated.",
            "content": {
              "application/json": {
                "example": { "success": true, "count": 1, "campaign_id": "c1a2b3c4-d5e6-4f70-8a9b-0c1d2e3f4a5b" }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": { "type": "http", "scheme": "bearer", "description": "Your API key from the SMS Philippines dashboard." }
    },
    "schemas": {
      "CampaignMessage": {
        "type": "object",
        "required": ["id"],
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "step": { "type": "integer" },
          "message": { "type": "string" },
          "is_recurring": { "type": "boolean" },
          "scheduled_at": { "type": "string", "description": "Future PHT wall-clock timestamp, YYYY-MM-DD HH:MM:SS." },
          "recurrence_frequency": { "type": "string", "enum": ["daily", "weekly", "monthly"] },
          "recurrence_days": { "type": "array", "items": { "type": "integer", "minimum": 0, "maximum": 6 }, "description": "Weekly only. 0 = Sunday to 6 = Saturday." },
          "recurrence_day_of_month": { "type": "integer", "minimum": 1, "maximum": 31, "description": "Monthly only." },
          "recurrence_time": { "type": "string", "description": "24-hour HH:MM PHT." },
          "recurrence_start": { "type": "string", "format": "date" },
          "recurrence_end": { "type": "string", "format": "date", "description": "Optional. Omit to recur indefinitely." }
        }
      }
    },
    "responses": {
      "BadRequest": { "description": "Missing or invalid fields, e.g. MISSING_SENDER_NAME, SENDER_NAME_NOT_FOUND." },
      "Unauthorized": { "description": "Missing or invalid API key (MISSING_AUTH)." },
      "NotFound": { "description": "The campaign was not found on your account." }
    }
  }
}
