Get API Token
SyncGaze Mail · Developer API

One REST call to send, read & manage email.

Full programmatic access to your mailboxes over plain HTTPS: send messages, read folders, search, manage drafts and labels. No IMAP configuration, no SMTP handshakes, scoped tokens you control. Copy-paste examples in 14 languages.

JSON
Requests and responses
14
Language examples
REST
Bearer-token auth
3
Granular scopes

SyncGaze Mail REST API

The SyncGaze Mail API gives you full programmatic access to your mailboxes: send emails, read messages, manage folders, search, and more. One secure HTTPS call. No IMAP configuration. No SMTP handshakes.

Tokens are created in your webmail under Settings → API Access and scoped to exactly the permissions your application needs.

No SMTP setup. The API sends through the SyncGaze Mail Server for you, so your app needs no mail library or SMTP settings.

Base URL

Base URL
https://mail.syncgaze.in/api/v1/webmail/

All endpoints are relative to this base URL. Always use HTTPS.


Authentication

Include your API token in every request as a Bearer token in the Authorization header:

HTTP Header
Authorization: Bearer sg_YOUR_TOKEN

Token Scopes

Scope Access Description
imap:read Read List folders, read messages, search, view drafts & labels
imap:write Read + Write Move, flag, delete messages; create drafts; manage labels
smtp:send Send Send new emails and upload attachments
Tokens are created in your webmail under Settings → API Access. Revoke any token instantly from the same page.

Rate Limits

Your rate limits are activated automatically with your subscription. Exact quotas are returned in every response header, no need to hard-code them.

PlanRequests / minRequests / dayMax attachment
Starter605 00010 MB
Personal30050 00025 MB
Business1 000500 00050 MB
EnterpriseCustom: contact sales

Rate-limit headers are returned on every response:

Response Headers
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 297
X-RateLimit-Reset: 1746000000
On 429 Too Many Requests: back off and retry after the Retry-After header value (seconds).

Error Responses

StatusCodeMeaning
400bad_requestValidation error: check request body
401invalid_api_tokenToken missing, invalid, or expired
403insufficient_scopeToken lacks required scope
429rate_limitedToo many requests: slow down
500server_errorInternal error: retry with backoff
Error Shape
{
  "error": "insufficient_scope",
  "detail": "This token requires the smtp:send scope to send email."
}

When to use the API instead of SMTP

Both deliver mail through the same SyncGaze Mail Server. The API is simpler to call from your own code.

ApproachWhat your code does for each message
SMTP client
smtplib, nodemailer, PHPMailer
Connect, start TLS, EHLO, AUTH, MAIL FROM, RCPT TO, DATA, QUIT
SyncGaze REST APIOne HTTPS POST with a bearer token
  • No mail library and no SMTP settings in your app: any language that can make an HTTPS request can send.
  • Tokens are scoped, so a send-only integration cannot read the mailbox.
  • The same token also reads folders and messages, which SMTP cannot do.

Folders

MethodPathScopeDescription
GET folders/ imap:read List all IMAP folders
POST folders/ imap:write Create a new folder
DEL folders/{name}/ imap:write Delete a folder

Response: GET folders/

JSON
[
  { "name": "INBOX",    "delimiter": "/", "flags": ["\\HasNoChildren"] },
  { "name": "Sent",     "delimiter": "/", "flags": ["\\HasNoChildren"] },
  { "name": "Drafts",   "delimiter": "/", "flags": ["\\HasNoChildren"] },
  { "name": "Trash",    "delimiter": "/", "flags": ["\\HasNoChildren"] },
  { "name": "Spam",     "delimiter": "/", "flags": ["\\HasNoChildren"] }
]

Messages

MethodPathScopeDescription
GET messages/ imap:read List messages in a folder
GET messages/{uid}/ imap:read Get full message with body
PUT messages/{uid}/ imap:write Move / flag a message
DEL messages/{uid}/ imap:write Delete (move to Trash)

Query Parameters: GET messages/

ParamTypeDescription
folderstringFolder name (default: INBOX)
limitintMax messages to return (default: 25)
offsetintPagination offset
unreadboolFilter to unread messages only

Send Email

One HTTPS request. Your message is handed to the SyncGaze Mail Server, with no SMTP connection from your app.
MethodPathScopeResponse
POST send/ smtp:send 201 Created

Request Body

JSON
{
  "to":      [{ "email": "recipient@example.com", "name": "Jane Doe" }],
  "cc":      [],
  "bcc":     [],
  "subject": "Hello from the API",
  "body":    "<p>HTML or plain text body here.</p>",
  "reply_to": "you@yourdomain.com",
  "attachments": []
}

Successful Response

JSON: 201
{ "status": "sent", "message_id": "<abc123@mail.syncgaze.in>" }

Drafts

MethodPathScopeDescription
GETdrafts/imap:readList drafts
POSTdrafts/imap:writeSave a draft
PUTdrafts/{id}/imap:writeUpdate a draft
DELdrafts/{id}/imap:writeDelete a draft

Labels

MethodPathScopeDescription
GETlabels/imap:readList all labels
POSTlabels/imap:writeCreate a label
POSTmessages/{uid}/labels/imap:writeApply label to message

Attachments

MethodPathScopeDescription
POSTattachments/smtp:sendUpload a file (returns upload_id)
GETmessages/{uid}/attachments/{id}/imap:readDownload an attachment
Use the upload_id returned by the upload endpoint in the attachments array when calling POST send/.

API Token Management

MethodPathDescription
GETtokens/List your tokens (no secret returned)
POSTtokens/Create a new token
DELtokens/{id}/Revoke a token
The raw token value is only shown once at creation time. Store it securely: it cannot be retrieved again.

14 Language Examples

Each example shows: list folders, list INBOX messages, and send an email.

python
import requests

API_URL = "https://mail.syncgaze.in/api/v1/webmail"
TOKEN   = "sg_YOUR_TOKEN"
headers = {"Authorization": f"Bearer {TOKEN}"}

# List folders
folders = requests.get(f"{API_URL}/folders/", headers=headers)
print(folders.json())

# List INBOX messages
messages = requests.get(
    f"{API_URL}/messages/",
    headers=headers,
    params={"folder": "INBOX", "limit": 20}
)
print(messages.json())

# Send an email
resp = requests.post(
    f"{API_URL}/send/",
    headers={**headers, "Content-Type": "application/json"},
    json={
        "to": [{"email": "recipient@example.com"}],
        "subject": "Hello from Python",
        "body": "<p>Sent via SyncGaze API</p>",
    },
)
print(resp.status_code, resp.json())
javascript
const API_URL = "https://mail.syncgaze.in/api/v1/webmail";
const TOKEN   = "sg_YOUR_TOKEN";
const headers = { Authorization: `Bearer ${TOKEN}` };

// List folders
const folders = await fetch(`${API_URL}/folders/`, { headers });
console.log(await folders.json());

// List INBOX messages
const msgs = await fetch(
  `${API_URL}/messages/?folder=INBOX&limit=20`, { headers }
);
console.log(await msgs.json());

// Send an email
const res = await fetch(`${API_URL}/send/`, {
  method: "POST",
  headers: { ...headers, "Content-Type": "application/json" },
  body: JSON.stringify({
    to:      [{ email: "recipient@example.com" }],
    subject: "Hello from JS",
    body:    "<p>Sent via SyncGaze API</p>",
  }),
});
console.log(res.status, await res.json());
shell
# List folders
curl -H "Authorization: Bearer sg_YOUR_TOKEN" \
     https://mail.syncgaze.in/api/v1/webmail/folders/

# List INBOX messages
curl -H "Authorization: Bearer sg_YOUR_TOKEN" \
     "https://mail.syncgaze.in/api/v1/webmail/messages/?folder=INBOX&limit=20"

# Send an email
curl -X POST \
     -H "Authorization: Bearer sg_YOUR_TOKEN" \
     -H "Content-Type: application/json" \
     -d '{"to":[{"email":"recipient@example.com"}],"subject":"Hello","body":"<p>Hi!</p>"}' \
     https://mail.syncgaze.in/api/v1/webmail/send/
php
<?php
// composer require guzzlehttp/guzzle
use GuzzleHttp\Client;

$API = "https://mail.syncgaze.in/api/v1/webmail";
$client = new Client([
    'headers' => ['Authorization' => "Bearer sg_YOUR_TOKEN"],
]);

// List folders
$folders = $client->get("$API/folders/");
var_dump(json_decode($folders->getBody(), true));

// List INBOX messages
$msgs = $client->get("$API/messages/", [
    'query' => ['folder' => 'INBOX', 'limit' => 20],
]);

// Send an email
$res = $client->post("$API/send/", [
    'json' => [
        'to'      => [['email' => 'recipient@example.com']],
        'subject' => 'Hello from PHP',
        'body'    => '<p>Sent via SyncGaze API</p>',
    ],
]);
echo $res->getStatusCode(); // 201
go
package main

import (
    "bytes"; "encoding/json"; "fmt"
    "io";    "net/http"
)

const (
    api   = "https://mail.syncgaze.in/api/v1/webmail"
    token = "sg_YOUR_TOKEN"
)

func apiGet(path string) []byte {
    req, _ := http.NewRequest("GET", api+path, nil)
    req.Header.Set("Authorization", "Bearer "+token)
    resp, _ := http.DefaultClient.Do(req)
    body, _ := io.ReadAll(resp.Body)
    return body
}

func main() {
    fmt.Println(string(apiGet("/folders/")))
    fmt.Println(string(apiGet("/messages/?folder=INBOX&limit=20")))

    // Send an email
    payload, _ := json.Marshal(map[string]any{
        "to":      []map[string]string{{"email": "recipient@example.com"}},
        "subject": "Hello from Go",
        "body":    "<p>Sent via SyncGaze API</p>",
    })
    req, _ := http.NewRequest("POST", api+"/send/", bytes.NewBuffer(payload))
    req.Header.Set("Authorization", "Bearer "+token)
    req.Header.Set("Content-Type", "application/json")
    resp, _ := http.DefaultClient.Do(req)
    fmt.Println(resp.StatusCode)
}
ruby
require 'net/http'
require 'json'; require 'uri'

API = "https://mail.syncgaze.in/api/v1/webmail"
TOKEN = "sg_YOUR_TOKEN"

def api_get(path)
  uri = URI("#{API}#{path}")
  req = Net::HTTP::Get.new(uri)
  req['Authorization'] = "Bearer #{TOKEN}"
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true
  JSON.parse(http.request(req).body)
end

p api_get('/folders/')
p api_get('/messages/?folder=INBOX&limit=20')

# Send an email
uri = URI("#{API}/send/")
req = Net::HTTP::Post.new(uri)
req['Authorization'] = "Bearer #{TOKEN}"
req['Content-Type']  = 'application/json'
req.body = { to: [{ email: 'recipient@example.com' }],
             subject: 'Hello from Ruby',
             body: '<p>Hi!</p>' }.to_json
http = Net::HTTP.new(uri.host, uri.port); http.use_ssl = true
p http.request(req).code
java
// Java 11+, no external dependencies
import java.net.URI; import java.net.http.*;

var client = HttpClient.newHttpClient();
var api    = "https://mail.syncgaze.in/api/v1/webmail";
var token  = "sg_YOUR_TOKEN";

// List folders
var req = HttpRequest.newBuilder()
    .uri(URI.create(api + "/folders/"))
    .header("Authorization", "Bearer " + token)
    .GET().build();
System.out.println(client.send(req, HttpResponse.BodyHandlers.ofString()).body());

// Send an email
var body = """
    {"to":[{"email":"recipient@example.com"}],
     "subject":"Hello from Java",
     "body":"<p>Sent via SyncGaze API</p>"}
    """;
var send = HttpRequest.newBuilder()
    .uri(URI.create(api + "/send/"))
    .header("Authorization", "Bearer " + token)
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString(body)).build();
System.out.println(client.send(send, HttpResponse.BodyHandlers.ofString()).statusCode());
csharp
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;

var api   = "https://mail.syncgaze.in/api/v1/webmail";
var http  = new HttpClient();
http.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", "sg_YOUR_TOKEN");

// List folders
Console.WriteLine(await http.GetStringAsync($"{api}/folders/"));

// List INBOX messages
Console.WriteLine(await http.GetStringAsync(
    $"{api}/messages/?folder=INBOX&limit=20"));

// Send an email
var payload = """
    {"to":[{"email":"recipient@example.com"}],
     "subject":"Hello from C#",
     "body":"<p>Sent via SyncGaze API</p>"}
    """;
var resp = await http.PostAsync($"{api}/send/",
    new StringContent(payload, Encoding.UTF8, "application/json"));
Console.WriteLine((int)resp.StatusCode);
rust
// Cargo.toml:  reqwest = { version = "0.12", features = ["json","blocking"] }
//              serde_json = "1"
use reqwest::blocking::Client;
use serde_json::json;

fn main() -> Result<(), reqwest::Error> {
    let api    = "https://mail.syncgaze.in/api/v1/webmail";
    let token  = "sg_YOUR_TOKEN";
    let client = Client::new();
    let auth   = format!("Bearer {token}");

    // List folders
    let folders = client.get(format!("{api}/folders/"))
        .header("Authorization", &auth).send()?.text()?;
    println!("{folders}");

    // Send an email
    let r = client.post(format!("{api}/send/"))
        .header("Authorization", &auth)
        .json(&json!({
            "to":      [{ "email": "recipient@example.com" }],
            "subject": "Hello from Rust",
            "body":    "<p>Sent via SyncGaze API</p>",
        })).send()?;
    println!("{}", r.status());
    Ok(())
}
swift
import Foundation

let api   = "https://mail.syncgaze.in/api/v1/webmail"
let token = "sg_YOUR_TOKEN"

func sg(_ path: String, method: String = "GET", body: Data? = nil) async throws -> Data {
    var req = URLRequest(url: URL(string: api + path)!)
    req.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
    req.httpMethod = method
    if let b = body {
        req.httpBody = b
        req.setValue("application/json", forHTTPHeaderField: "Content-Type")
    }
    let (data, _) = try await URLSession.shared.data(for: req)
    return data
}

// List folders
let folders = try await sg("/folders/")
print(String(data: folders, encoding: .utf8)!)

// Send an email
let payload = try! JSONSerialization.data(withJSONObject: [
    "to": [["email": "recipient@example.com"]],
    "subject": "Hello from Swift",
    "body": "<p>Sent via SyncGaze API</p>",
])
let result = try await sg("/send/", method: "POST", body: payload)
print(String(data: result, encoding: .utf8)!)
kotlin
// build.gradle: implementation("com.squareup.okhttp3:okhttp:4.12.0")
import okhttp3.*; import okhttp3.MediaType.Companion.toMediaType

val api    = "https://mail.syncgaze.in/api/v1/webmail"
val token  = "sg_YOUR_TOKEN"
val client = OkHttpClient()
val JSON   = "application/json".toMediaType()

// List folders
val req = Request.Builder()
    .url("$api/folders/")
    .header("Authorization", "Bearer $token")
    .build()
client.newCall(req).execute().use { println(it.body!!.string()) }

// Send an email
val body = RequestBody.create(JSON, """
    {"to":[{"email":"recipient@example.com"}],
     "subject":"Hello from Kotlin",
     "body":"<p>Sent via SyncGaze API</p>"}
""")
val send = Request.Builder()
    .url("$api/send/")
    .header("Authorization", "Bearer $token")
    .post(body).build()
client.newCall(send).execute().use { println(it.code) }
typescript
// npm install axios
import axios, { AxiosError } from "axios";

const API_URL = "https://mail.syncgaze.in/api/v1/webmail";
const TOKEN   = "sg_YOUR_TOKEN";

interface Folder  { name: string; flags: string[] }
interface Message { uid: number; subject: string; from: string; date: string }

const client = axios.create({
  baseURL: API_URL,
  headers: { Authorization: `Bearer ${TOKEN}` },
});

// List folders
const { data: folders } = await client.get<Folder[]>("/folders/");
console.log(folders);

// List INBOX messages
const { data: messages } = await client.get<Message[]>(
  "/messages/",
  { params: { folder: "INBOX", limit: 20 } }
);
console.log(messages);

// Send an email
try {
  const { data, status } = await client.post("/send/", {
    to:      [{ email: "recipient@example.com" }],
    subject: "Hello from TypeScript",
    body:    "<p>Sent via SyncGaze API</p>",
  });
  console.log(status, data);
} catch (err) {
  const e = err as AxiosError;
  console.error(e.response?.status, e.response?.data);
}
fastapi
# pip install fastapi aiohttp uvicorn
import aiohttp
from fastapi import FastAPI, HTTPException
from fastapi.responses import JSONResponse

app = FastAPI()

API_URL = "https://mail.syncgaze.in/api/v1/webmail"
TOKEN   = "sg_YOUR_TOKEN"
HEADERS = {"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"}


@app.get("/list-folders")
async def list_folders():
    async with aiohttp.ClientSession() as session:
        try:
            async with session.get(f"{API_URL}/folders/", headers=HEADERS) as resp:
                if resp.status != 200:
                    raise HTTPException(status_code=resp.status, detail=await resp.text())
                return await resp.json()
        except aiohttp.ClientError as exc:
            raise HTTPException(status_code=503, detail=str(exc))


@app.post("/send-email", status_code=201)
async def send_email():
    # Send an email
    payload = {
        "to":      [{"email": "recipient@example.com"}],
        "subject": "Hello from FastAPI",
        "body":    "<p>Sent via SyncGaze API</p>",
    }
    async with aiohttp.ClientSession() as session:
        try:
            async with session.post(
                f"{API_URL}/send/", headers=HEADERS, json=payload
            ) as resp:
                data = await resp.json()
                if resp.status not in (200, 201):
                    raise HTTPException(status_code=resp.status, detail=data)
                return JSONResponse(content=data, status_code=201)
        except aiohttp.ClientError as exc:
            raise HTTPException(status_code=503, detail=str(exc))
dart
// pubspec.yaml:  http: ^1.2.0
import 'dart:convert';
import 'package:http/http.dart' as http;

const apiUrl = 'https://mail.syncgaze.in/api/v1/webmail';
const token  = 'sg_YOUR_TOKEN';
final headers = {
  'Authorization': 'Bearer $token',
  'Content-Type':  'application/json',
};

Future<void> main() async {
  // List folders
  try {
    final res = await http.get(
      Uri.parse('$apiUrl/folders/'), headers: headers);
    print(jsonDecode(res.body));
  } catch (e) { print('Error: $e'); }

  // List INBOX messages
  try {
    final res = await http.get(
      Uri.parse('$apiUrl/messages/?folder=INBOX&limit=20'),
      headers: headers,
    );
    print(jsonDecode(res.body));
  } catch (e) { print('Error: $e'); }

  // Send an email
  try {
    final res = await http.post(
      Uri.parse('$apiUrl/send/'),
      headers: headers,
      body: jsonEncode({
        'to':      [{ 'email': 'recipient@example.com' }],
        'subject': 'Hello from Dart',
        'body':    '<p>Sent via SyncGaze API</p>',
      }),
    );
    print('${res.statusCode}: ${res.body}');
  } catch (e) { print('Error: $e'); }
}