DaySurface
REST API

Overview

REST API overview, base URL, and quick start

The REST API exposes the same Gmail, PDF, and webhook tools your assistant gets over MCP as authenticated HTTP endpoints - one shared service registry behind all three transports, so behavior never drifts between them.

Reach for it when the caller is your own code rather than an agent: a cron job that triages overnight mail, a backend that files attachments, a script that drafts on your behalf.

Base URL

https://api.daysurface.com

The API shares one process with the MCP server, so the same deployment also answers MCP traffic at mcp.daysurface.com/mcp; api.daysurface.com is the canonical vanity host for REST. (daysurface.com is the product site, a separate service.)

Every example in these docs uses that host. Running the server yourself? Swap in your own deployment, or http://localhost:8000 when it is running locally via daysurface-serve.

Quick Example

Rank the ten threads that most need attention:

curl -X POST https://api.daysurface.com/api/v1/services/gmail_curate_inbox \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{"limit": 10}'

Every tool follows the same shape - POST /api/v1/services/{tool_name} with the tool's input model as the body. The generated OpenAPI document lives at /openapi.json.

Discovery

The root path describes the deployment to whoever - or whatever - lands on it. No authentication required.

curl https://mcp.daysurface.com/
{
  "title": "DaySurface",
  "protocol": "mcp",
  "instructions": "This host serves the Model Context Protocol at https://mcp.daysurface.com/mcp ...",
  "mcp": {
    "url": "https://mcp.daysurface.com/mcp",
    "transport": "streamable-http",
    "authentication": { "required": true, "schemes": ["oauth2", "api_key"] },
    "tools": ["gmail_list_inbox", "gmail_compose", "..."]
  },
  "endpoints": { "mcp": "...", "health": "...", "server_card": "..." }
}

Browsers (Accept: text/html) get a small landing page with the same content.

Unknown paths return a 404 carrying the same endpoints map plus a did_you_mean hint, so a client probing a legacy transport path - /sse, /messages - is told where the endpoint actually lives:

{
  "error": {
    "code": "not_found",
    "message": "No handler for GET /sse. Did you mean https://mcp.daysurface.com/mcp?",
    "details": { "path": "/sse", "did_you_mean": "https://mcp.daysurface.com/mcp" },
    "request_id": "eee3ed63ac4b4651ab3911c47a21603e"
  },
  "endpoints": {
    "mcp": "https://mcp.daysurface.com/mcp",
    "health": "https://mcp.daysurface.com/health",
    "server_card": "https://mcp.daysurface.com/.well-known/mcp/server-card.json"
  }
}

endpoints sits beside error, carrying the same entries as the discovery response above. did_you_mean is present only when a known alias matches.

Health Check

No authentication required.

curl https://api.daysurface.com/health
{
  "status": "ok",
  "version": "0.1.1",
  "commit": "a1b2c3d",
  "timestamp": "2025-01-15T10:30:00+00:00",
  "components": {
    "api": { "status": "ok" },
    "database": { "status": "ok" },
    "redis": { "status": "not_configured" },
    "stripe": { "status": "ok" }
  }
}

Status is "ok" when all components are healthy, "degraded" if any have errors.

Next Steps

目次