Developers
Public API
Build your own dashboard, exports, and automations on top of your diary data.
Requirements
- Plan: Advanced plan is required for Public API access.
- API key: Create and revoke keys from app settings (Settings > API Keys).
- Base URL:
https://api.deariary.com/api/v1
Authentication
All requests must include Authorization: Bearer deariary_sk_... . Keys are scoped, and requests without required scope return 403.
Authorization: Bearer deariary_sk_...
Available scopes
| Scope | Description |
|---|---|
entries:list | List diary entries |
entries:read | Read a single diary entry by date |
tags:read | List tags with usage counts |
Rate limits and headers
- 120 requests per minute per API key.
- Headers:
X-RateLimit-Limit,X-RateLimit-Remaining,X-RateLimit-Reset,Retry-After - Response header:
X-Request-Id - CORS:
Access-Control-Allow-Origin: *
Error format
Errors are returned as application/problem+json. Public API auth/rate-limit errors and validation errors are normalized into Problem Details responses. application/problem+json
Error response example
{
"type": "https://developer.deariary.com/errors/missing-api-key",
"title": "Unauthorized",
"status": 401,
"detail": "MISSING_API_KEY"
}Error response example
{
"type": "https://developer.deariary.com/errors/rate-limit-exceeded",
"title": "Too Many Requests",
"status": 429,
"detail": "Rate limit of 120 requests per minute exceeded. Retry after 24 seconds."
}Common errors
| Status | Type | Cause |
|---|---|---|
| 400 | bad-request | Invalid query/path parameter |
| 401 | missing-api-key | Authorization header missing |
| 401 | invalid-api-key | API key is invalid or revoked |
| 403 | public-api-requires-the-advanced-plan | Account is not on Advanced plan |
| 403 | insufficient-scope | Key does not include required scope |
| 404 | entry-not-found | No entry exists for the requested date |
| 429 | rate-limit-exceeded | Too many requests |
Endpoints
GET /api/v1/entries
Returns a paginated list of entries. Required scope: entries:list
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
from | string | 30 days ago | Start date (inclusive, YYYY-MM-DD) |
to | string | today | End date (inclusive, YYYY-MM-DD) |
tag | string | - | Filter by tag slug |
limit | integer | 20 | Entries to return (1 to 100) |
offset | integer | 0 | Entries to skip |
Response fields
| Field | Type | Description |
|---|---|---|
data | Entry[] | Array of entries |
data[].date | string | Date in YYYY-MM-DD |
data[].title | string | null | Entry title |
data[].content | string | null | Entry summary content |
data[].tags | string[] | Tag slugs |
data[].generatedAt | string | ISO-8601 timestamp |
pagination.total | integer | Total matched entries |
pagination.limit | integer | Returned limit |
pagination.offset | integer | Returned offset |
Sample request
curl -H "Authorization: Bearer deariary_sk_xxx" \
"https://api.deariary.com/api/v1/entries?from=2026-02-01&to=2026-02-28&tag=deep-work&limit=2&offset=0"Success response example
{
"data": [
{
"date": "2026-02-24",
"title": "A productive Monday",
"content": "# A productive Monday\n\nToday I worked on...",
"tags": ["coding", "deep-work"],
"generatedAt": "2026-02-25T03:00:00.000Z"
}
],
"pagination": {
"total": 42,
"limit": 10,
"offset": 0
}
}GET /api/v1/entries/:date
Returns one entry by date. Required scope: entries:read
Response fields
| Field | Type | Description |
|---|---|---|
date | string | Entry date (YYYY-MM-DD) |
title | string | null | Entry title extracted from markdown |
content | string | null | Full markdown content |
tags | string[] | Tag slugs |
sources | string[] | Included data sources |
generatedAt | string | ISO-8601 generation timestamp |
wordCount | integer | Word count of content |
Sample request
curl -H "Authorization: Bearer deariary_sk_xxx" \
"https://api.deariary.com/api/v1/entries/2026-02-24"Success response example
{
"date": "2026-02-24",
"title": "A productive Monday",
"content": "# A productive Monday\n\nToday I worked on...",
"tags": ["coding", "deep-work"],
"sources": ["github", "calendar", "slack"],
"generatedAt": "2026-02-25T03:00:00.000Z",
"wordCount": 438
}Error response example
{
"type": "https://developer.deariary.com/errors/entry-not-found",
"title": "Not Found",
"status": 404,
"detail": "ENTRY_NOT_FOUND"
}GET /api/v1/tags
Returns tags with usage counts. Required scope: tags:read
Response fields
| Field | Type | Description |
|---|---|---|
slug | string | Tag identifier |
displayName | string | Human readable tag name |
entryCount | integer | Number of entries with this tag |
Sample request
curl -H "Authorization: Bearer deariary_sk_xxx" \
"https://api.deariary.com/api/v1/tags"Success response example
{
"data": [
{
"slug": "deep-work",
"displayName": "Deep Work",
"entryCount": 18
},
{
"slug": "running",
"displayName": "Running",
"entryCount": 9
}
]
}Incoming webhook
Advanced plan supports incoming webhook ingestion. You can send custom payloads from your own tools (Zapier, IFTTT, scripts, shortcuts), and deariary interprets them with LLM context in the next diary generation.
- Endpoint: POST /webhooks/ingest
- Auth: Authorization header with Bearer whk_...
- Payload size: up to 100KB per request
- Any JSON object or array is accepted (no fixed schema)
- Examples: mood logs, reading history, workout records, custom events
- Webhook tokens are managed in Integrations > Webhook > Settings
Sample request
curl -X POST "https://api.deariary.com/webhooks/ingest" \
-H "Authorization: Bearer whk_xxx" \
-H "Content-Type: application/json" \
-d '{
"timestamp": "2026-02-24T09:30:00Z",
"source": "mood-tracker",
"payload": {
"mood": "great",
"score": 8,
"note": "Focused 3h block"
}
}'Success response example
{
"received": true
}Error response example
{
"type": "https://developer.deariary.com/errors/invalid-webhook-token",
"title": "Unauthorized",
"status": 401,
"detail": "INVALID_WEBHOOK_TOKEN"
}