{
  "openapi": "3.1.0",
  "info": {
    "title": "ZafeConnect messaging API",
    "version": "v1",
    "description": "The documented customer endpoints of the ZafeConnect messaging API (SMS, RCS, WhatsApp, email). Generated from the published developer documentation at https://www.zafeconnect.com/developers. Further endpoints exist (for example message history and resend, sender rules and validation, email domains and analytics); contact ZafeConnect for the complete reference. Example cost values are illustrative.",
    "contact": {
      "name": "ZafeConnect",
      "email": "info@zafeconnect.com",
      "url": "https://www.zafeconnect.com"
    },
    "termsOfService": "https://www.zafeconnect.com/terms"
  },
  "externalDocs": {
    "description": "ZafeConnect API documentation",
    "url": "https://www.zafeconnect.com/developers"
  },
  "servers": [
    {
      "url": "https://api.zafeconnect.com",
      "description": "Production. Live and test API keys select the environment."
    }
  ],
  "security": [
    {
      "ApiKey": []
    }
  ],
  "tags": [
    {
      "name": "Messages"
    },
    {
      "name": "Account"
    }
  ],
  "paths": {
    "/v1/messages/send": {
      "post": {
        "tags": [
          "Messages"
        ],
        "operationId": "sendMessage",
        "summary": "Send a single message via SMS, RCS, WhatsApp or email",
        "description": "Send a single message via SMS, RCS, WhatsApp or email. The sender must be an approved sender. See how SenderID registration works. The cost and currency fields reflect your account pricing; example values are illustrative.",
        "responses": {
          "201": {
            "description": "Created: Queued",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message_id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    },
                    "channel": {
                      "type": "string"
                    },
                    "to": {
                      "type": "string"
                    },
                    "cost": {
                      "type": "number"
                    },
                    "currency": {
                      "type": "string"
                    },
                    "created_at": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "message_id": "msg_01j2abc...",
                  "status": "queued",
                  "channel": "sms",
                  "to": "+4520123456",
                  "cost": 0,
                  "currency": "EUR",
                  "created_at": "2026-05-27T12:00:00Z"
                }
              }
            }
          },
          "400": {
            "description": "Bad request: Invalid params"
          },
          "401": {
            "description": "Unauthorized: Invalid API key"
          },
          "402": {
            "description": "Payment required: Insufficient balance"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendMessage"
              },
              "example": {
                "to": "+4520123456",
                "channel": "sms",
                "message": "Hello from ZafeConnect!",
                "sender": "MyBrand"
              }
            }
          }
        }
      }
    },
    "/v1/messages/bulk": {
      "post": {
        "tags": [
          "Messages"
        ],
        "operationId": "sendBulk",
        "summary": "Send up to 10,000 messages in one request",
        "description": "Send up to 10,000 messages in one request. Each is queued individually. Limited to 100 requests per minute.",
        "responses": {
          "201": {
            "description": "Created: Accepted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "batch_id": {
                      "type": "string"
                    },
                    "queued": {
                      "type": "number"
                    },
                    "failed": {
                      "type": "number"
                    },
                    "estimated_cost": {
                      "type": "number"
                    },
                    "currency": {
                      "type": "string"
                    },
                    "created_at": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "batch_id": "b_01j2...",
                  "queued": 2,
                  "failed": 0,
                  "estimated_cost": 0,
                  "currency": "EUR",
                  "created_at": "2026-05-27T12:00:00Z"
                }
              }
            }
          },
          "400": {
            "description": "Bad request: Invalid params"
          },
          "413": {
            "description": "Payload too large: Over 10,000 messages"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "messages"
                ],
                "properties": {
                  "messages": {
                    "type": "array",
                    "maxItems": 10000,
                    "items": {
                      "$ref": "#/components/schemas/SendMessage"
                    },
                    "description": "Array of message objects with the same fields as /send (max 10,000)"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/messages/{id}": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          },
          "description": "Message ID returned by /v1/messages/send or /v1/messages/bulk"
        }
      ],
      "get": {
        "tags": [
          "Messages"
        ],
        "operationId": "getMessage",
        "summary": "Get the current delivery status of a message by its ID",
        "description": "Get the current delivery status of a message by its ID.",
        "responses": {
          "200": {
            "description": "OK: OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message_id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    },
                    "channel": {
                      "type": "string"
                    },
                    "to": {
                      "type": "string"
                    },
                    "delivered_at": {
                      "type": "string"
                    },
                    "cost": {
                      "type": "number"
                    },
                    "currency": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "message_id": "msg_01j2abc...",
                  "status": "delivered",
                  "channel": "sms",
                  "to": "+4520123456",
                  "delivered_at": "2026-05-27T12:00:03Z",
                  "cost": 0,
                  "currency": "EUR"
                }
              }
            }
          },
          "404": {
            "description": "Not found: Not found"
          }
        }
      },
      "delete": {
        "tags": [
          "Messages"
        ],
        "operationId": "cancelMessage",
        "summary": "Cancel a scheduled message",
        "description": "Cancel a scheduled message. Only works while the status is scheduled.",
        "responses": {
          "200": {
            "description": "OK: Cancelled",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    },
                    "message_id": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "message": "Message cancelled",
                  "message_id": "msg_01j2abc..."
                }
              }
            }
          },
          "404": {
            "description": "Not found: Not found"
          },
          "409": {
            "description": "Conflict: Already sent"
          }
        }
      }
    },
    "/v1/account/balance": {
      "get": {
        "tags": [
          "Account"
        ],
        "operationId": "getBalance",
        "summary": "Get your current account balance, currency and plan",
        "description": "Get your current account balance, currency and plan.",
        "responses": {
          "200": {
            "description": "OK: OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "balance": {
                      "type": "number"
                    },
                    "currency": {
                      "type": "string"
                    },
                    "plan": {
                      "type": "string"
                    },
                    "updated_at": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "balance": 1240.5,
                  "currency": "EUR",
                  "plan": "business",
                  "updated_at": "2026-05-27T12:00:00Z"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized: Unauthorized"
          }
        }
      }
    },
    "/v1/account/pricing": {
      "get": {
        "tags": [
          "Account"
        ],
        "operationId": "getPricing",
        "summary": "Get your current prices per channel and country",
        "description": "Get your current prices per channel and country.",
        "responses": {
          "200": {
            "description": "OK: OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "pricing": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "channel": {
                            "type": "string"
                          },
                          "country": {
                            "type": "string"
                          },
                          "price": {
                            "type": "number"
                          },
                          "currency": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "pricing": [
                    {
                      "channel": "sms",
                      "country": "ALL",
                      "price": 0,
                      "currency": "EUR"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized: Unauthorized"
          }
        },
        "parameters": [
          {
            "name": "channel",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "sms",
                "rcs",
                "whatsapp",
                "email"
              ]
            },
            "description": "Filter: sms, rcs, whatsapp or email"
          }
        ]
      }
    },
    "/v1/account/usage": {
      "get": {
        "tags": [
          "Account"
        ],
        "operationId": "getUsage",
        "summary": "Message volume and spend for a date range, broken down by channel",
        "description": "Message volume and spend for a date range, broken down by channel.",
        "responses": {
          "200": {
            "description": "OK: OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "summary": {
                      "type": "object",
                      "properties": {
                        "total_messages": {
                          "type": "number"
                        },
                        "total_cost": {
                          "type": "number"
                        },
                        "currency": {
                          "type": "string"
                        }
                      }
                    },
                    "breakdown": {
                      "type": "object",
                      "properties": {
                        "sms": {
                          "type": "object",
                          "properties": {
                            "messages": {
                              "type": "number"
                            },
                            "cost": {
                              "type": "number"
                            }
                          }
                        },
                        "email": {
                          "type": "object",
                          "properties": {
                            "messages": {
                              "type": "number"
                            },
                            "cost": {
                              "type": "number"
                            }
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "summary": {
                    "total_messages": 4820,
                    "total_cost": 0,
                    "currency": "EUR"
                  },
                  "breakdown": {
                    "sms": {
                      "messages": 4200,
                      "cost": 0
                    },
                    "email": {
                      "messages": 620,
                      "cost": 0
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized: Unauthorized"
          }
        },
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Start date, YYYY-MM-DD (default: 30 days ago)"
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "End date, YYYY-MM-DD (default: today)"
          }
        ]
      }
    }
  },
  "webhooks": {
    "messageStatus": {
      "post": {
        "summary": "Delivery status change",
        "description": "ZafeConnect sends a POST to your webhook URL when a message status changes. Set the URL in your API Keys settings. Each request carries three headers: X-ZafeConnect-Event, X-ZafeConnect-Timestamp and X-ZafeConnect-Signature. Return any 2xx status to acknowledge. ZafeConnect retries up to 5 times if your endpoint does not acknowledge. The signature is the hex HMAC-SHA256 of the string {timestamp}.{raw_request_body}, using your webhook signing secret. Compute it over the exact bytes received and compare it to the header.",
        "parameters": [
          {
            "name": "X-ZafeConnect-Event",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "Event name, for example message.delivered"
          },
          {
            "name": "X-ZafeConnect-Timestamp",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "Timestamp used in the signature"
          },
          {
            "name": "X-ZafeConnect-Signature",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "Hex HMAC-SHA256 of \"{timestamp}.{raw_request_body}\" with your webhook signing secret"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "event",
                  "message_id",
                  "status"
                ],
                "properties": {
                  "event": {
                    "type": "string",
                    "description": "message.delivered, message.failed, message.opened or message.clicked"
                  },
                  "message_id": {
                    "type": "string",
                    "description": "The message ID"
                  },
                  "status": {
                    "type": "string",
                    "description": "delivered, failed, opened or clicked"
                  },
                  "delivered_at": {
                    "type": "string",
                    "format": "date-time",
                    "description": "Delivery timestamp"
                  },
                  "error_code": {
                    "type": "string",
                    "description": "Error code, when the message failed"
                  }
                }
              },
              "example": {
                "event": "message.delivered",
                "message_id": "msg_01j2abc...",
                "status": "delivered",
                "channel": "sms",
                "to": "+4520123456",
                "delivered_at": "2026-05-27T12:00:03Z"
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Acknowledged. ZafeConnect retries up to 5 times if the endpoint does not acknowledge."
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "Send your API key in the X-API-Key header on every request. Create and manage keys in your ZafeConnect account under API Keys. Keys come in live and test environments."
      }
    },
    "schemas": {
      "SendMessage": {
        "type": "object",
        "required": [
          "to",
          "message"
        ],
        "anyOf": [
          {
            "required": [
              "channel"
            ]
          },
          {
            "required": [
              "channels"
            ]
          }
        ],
        "properties": {
          "to": {
            "type": "string",
            "description": "Recipient phone number (E.164) or email address"
          },
          "channel": {
            "type": "string",
            "description": "Primary channel: sms, rcs, whatsapp or email (or use channels[])"
          },
          "channels": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Channels in priority order; the first is primary, the rest are fallbacks"
          },
          "message": {
            "type": "string",
            "description": "Plain-text body. Used as-is on SMS; text fallback on HTML channels"
          },
          "htmlmessage": {
            "type": "string",
            "description": "HTML body (email only); ignored on SMS and WhatsApp"
          },
          "sender": {
            "type": "string",
            "description": "Sender ID. Must be an approved sender. The 11-character alphanumeric limit applies to SMS only"
          },
          "subject": {
            "type": "string",
            "description": "Email subject (email channel only)"
          },
          "fallback": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Backup channels tried if the primary fails, for example [\"sms\",\"email\"]"
          },
          "scheduled_at": {
            "type": "string",
            "format": "date-time",
            "description": "Send time. No offset means UTC. A trailing Z or an explicit offset both work"
          }
        },
        "description": "Provide either channel or channels[]. The sender must be an approved sender; the 11-character alphanumeric limit applies to SMS only."
      }
    }
  },
  "x-limits": {
    "Send rate": "1,000 requests per minute per key",
    "Bulk": "Up to 10,000 messages per request, 100 requests per minute",
    "Format": "JSON, UTF-8",
    "Authentication": "X-API-Key header"
  }
}
