{
  "openapi": "3.1.0",
  "info": {
    "title": "Sendar public email API",
    "version": "1.0.0",
    "description": "Core transactional email API. Dashboard-only operations are intentionally excluded. Use a server-side API key. Provider acceptance is not proof of inbox delivery."
  },
  "servers": [
    {
      "url": "https://sendar.app/api"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "paths": {
    "/emails": {
      "get": {
        "operationId": "listEmails",
        "tags": [
          "emails"
        ],
        "summary": "List sent emails",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Email logs",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/EmailLog"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request or content; inspect error.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid or revoked credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Permission, sending-domain or plan feature restriction.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Quota or request rate limit.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Server failure; sending outcome may be uncertain.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "502": {
            "description": "Provider failure; inspect history before retrying.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary failure; sending outcome may be uncertain.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "sendEmail",
        "tags": [
          "emails"
        ],
        "summary": "Send an email",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EmailInput"
              },
              "examples": {
                "welcome": {
                  "summary": "Inline welcome email",
                  "value": {
                    "from": "Sendar demo <demo@example.com>",
                    "to": [
                      "recipient@example.net"
                    ],
                    "subject": "Welcome aboard",
                    "text": "Your account is ready. Sign in to get started."
                  }
                },
                "template": {
                  "summary": "Saved template (replace with your own template ID and variables)",
                  "value": {
                    "from": "demo@example.com",
                    "to": [
                      "recipient@example.net"
                    ],
                    "templateId": 123,
                    "variables": {
                      "name": "Ada"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Message record; may be sent or scheduled. Inspect status; acceptance does not prove delivery.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmailLog"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request or content; inspect error.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid or revoked credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Permission, sending-domain or plan feature restriction.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Different request for the same key, or pending/uncertain outcome. Inspect message history; do not retry with a new key."
          },
          "429": {
            "description": "Quota or request rate limit.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Server failure; sending outcome may be uncertain.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "502": {
            "description": "Provider failure; inspect history before retrying.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary failure; sending outcome may be uncertain.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "description": "Single-email REST requests support up to five attachments with 1.3 MiB total decoded content. Scheduled sending is available on Growth and above, up to 30 days ahead. Batch requests contain 1–100 items and have no documented idempotency guarantee. Use Idempotency-Key on POST /emails: 16–128 letters, digits, underscores, colons or hyphens. Reuse the exact key and payload for the same event. A 409 or timeout may mean an uncertain outcome: inspect history instead of generating another key.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Recommended for API-key sends. Required for agent sending. Reuse the exact payload and key for the same message; never rotate a key to work around an uncertain result.",
            "schema": {
              "type": "string",
              "pattern": "^[-A-Za-z0-9_:]{16,128}$"
            }
          }
        ]
      }
    },
    "/emails/{id}": {
      "get": {
        "operationId": "getEmail",
        "tags": [
          "emails"
        ],
        "summary": "Get an email log",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Email log",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmailDetail"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request or content; inspect error.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid or revoked credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Permission, sending-domain or plan feature restriction.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Quota or request rate limit.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Server failure; sending outcome may be uncertain.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "502": {
            "description": "Provider failure; inspect history before retrying.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary failure; sending outcome may be uncertain.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/emails/{id}/events": {
      "get": {
        "operationId": "listEmailEvents",
        "tags": [
          "emails"
        ],
        "summary": "List open/click events recorded for an email",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Events, newest first",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/EmailEvent"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request or content; inspect error.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid or revoked credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Permission, sending-domain or plan feature restriction.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Email not found"
          },
          "429": {
            "description": "Quota or request rate limit.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Server failure; sending outcome may be uncertain.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "502": {
            "description": "Provider failure; inspect history before retrying.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary failure; sending outcome may be uncertain.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/emails/batch": {
      "post": {
        "operationId": "sendBatchEmails",
        "tags": [
          "emails"
        ],
        "summary": "Send up to 100 emails in one request",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "minItems": 1,
                "maxItems": 100,
                "items": {
                  "$ref": "#/components/schemas/BatchEmailItem"
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Emails accepted and queued for delivery",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BatchSendResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request or content; inspect error.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid or revoked credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Permission, sending-domain or plan feature restriction.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Quota or request rate limit.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Server failure; sending outcome may be uncertain.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "502": {
            "description": "Provider failure; inspect history before retrying.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary failure; sending outcome may be uncertain.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "description": "JSON array of 1–100 items. No documented idempotency support. Do not retry uncertain batch sends automatically."
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Private Sendar API key; create it in the dashboard."
      }
    },
    "schemas": {
      "EmailLog": {
        "type": "object",
        "required": [
          "id",
          "providerEmailId",
          "fromAddress",
          "toAddresses",
          "subject",
          "status",
          "errorMessage",
          "scheduledAt",
          "trackOpens",
          "trackClicks",
          "openedAt",
          "clickedAt",
          "openCount",
          "clickCount",
          "createdAt",
          "updatedAt"
        ],
        "properties": {
          "id": {
            "type": "integer"
          },
          "providerEmailId": {
            "type": [
              "string",
              "null"
            ]
          },
          "scheduledAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "fromAddress": {
            "type": "string"
          },
          "toAddresses": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "subject": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "errorMessage": {
            "type": [
              "string",
              "null"
            ]
          },
          "trackOpens": {
            "type": "boolean"
          },
          "trackClicks": {
            "type": "boolean"
          },
          "openedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "First recorded open (null until one happens)."
          },
          "clickedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "First recorded click (null until one happens)."
          },
          "openCount": {
            "type": "integer"
          },
          "clickCount": {
            "type": "integer"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "EmailInput": {
        "type": "object",
        "required": [
          "from",
          "to"
        ],
        "properties": {
          "from": {
            "type": "string",
            "minLength": 1
          },
          "to": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "string"
            },
            "maxItems": 50
          },
          "subject": {
            "type": "string",
            "minLength": 1,
            "description": "Required unless templateId is set."
          },
          "html": {
            "type": [
              "string",
              "null"
            ]
          },
          "text": {
            "type": [
              "string",
              "null"
            ]
          },
          "templateId": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Send using a saved template. When set, subject, html, and text must be omitted — the template supplies them, with {{variable}} placeholders resolved from the variables object."
          },
          "variables": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {
              "type": "string"
            },
            "description": "Values for the template's placeholders. Checked strictly — a missing or unknown key fails the request. Only valid together with templateId."
          },
          "trackOpens": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Record when recipients open this email (adds an invisible tracking pixel to the HTML body). Omit to use the account default. Only applies to emails with an html body."
          },
          "trackClicks": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Record when recipients click links in this email (links are rewritten through a tracking redirect). Omit to use the account default. Only applies to emails with an html body."
          },
          "scheduledAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Growth and above. Up to 30 days in the future. A past timestamp sends immediately."
          },
          "attachments": {
            "type": "array",
            "maxItems": 5,
            "items": {
              "$ref": "#/components/schemas/AttachmentInput"
            },
            "description": "Up to five files; 1.3 MiB combined decoded bytes."
          }
        },
        "description": "Supply subject and nonempty html and/or text, OR templateId with variables. Template mode forbids inline subject/html/text. Variables require templateId. Sender must belong to an authorized verified domain."
      },
      "AttachmentInput": {
        "type": "object",
        "required": [
          "filename",
          "content"
        ],
        "properties": {
          "filename": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255
          },
          "content": {
            "type": "string",
            "minLength": 1,
            "description": "File content encoded as base64."
          },
          "contentType": {
            "type": "string"
          }
        }
      },
      "EmailDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/EmailLog"
          },
          {
            "type": "object",
            "required": [
              "html",
              "bodyText"
            ],
            "properties": {
              "html": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "bodyText": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          }
        ]
      },
      "EmailEvent": {
        "type": "object",
        "required": [
          "id",
          "type",
          "url",
          "occurredAt"
        ],
        "properties": {
          "id": {
            "type": "integer"
          },
          "type": {
            "type": "string",
            "enum": [
              "open",
              "click"
            ]
          },
          "url": {
            "type": [
              "string",
              "null"
            ],
            "description": "Destination URL — click events only."
          },
          "occurredAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "BatchEmailItem": {
        "type": "object",
        "required": [
          "from",
          "to"
        ],
        "properties": {
          "from": {
            "type": "string",
            "minLength": 1
          },
          "to": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "string"
            },
            "maxItems": 50
          },
          "subject": {
            "type": "string",
            "minLength": 1,
            "description": "Required unless templateId is set."
          },
          "html": {
            "type": [
              "string",
              "null"
            ]
          },
          "text": {
            "type": [
              "string",
              "null"
            ]
          },
          "templateId": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Send this item using a saved template. When set, subject, html, and text must be omitted."
          },
          "variables": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {
              "type": "string"
            },
            "description": "Values for the template's placeholders. Checked strictly. Only valid together with templateId."
          },
          "trackOpens": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Record opens for this item. Omit to use the account default."
          },
          "trackClicks": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Record link clicks for this item. Omit to use the account default."
          }
        },
        "description": "Supply subject and nonempty html and/or text, OR templateId with variables. Template mode forbids inline subject/html/text. Variables require templateId. Sender must belong to an authorized verified domain."
      },
      "BatchSendResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EmailLog"
            }
          }
        }
      }
    }
  }
}
