Inkwell API
Build integrations with your journal · Base URL: https://api.inkwell.social
Authentication
Authenticate requests using an API key in the Authorization header:
curl https://api.inkwell.social/api/me \ -H "Authorization: Bearer ink_your_key_here"
Create API keys in Settings → API. Keys start with ink_ and are shown once at creation. Store them securely.
Scopes
readAccess your own data and public data. Available to all users.writeCreate, update, and delete entries and images. Requires Plus subscription.Rate Limits
| Tier | Read (GET) | Write (POST/PATCH/DELETE) |
|---|---|---|
| Free | 100 / 15 min | N/A |
| Plus | 300 / 15 min | 60 / 15 min |
Limits are per API key. Rate limit headers (X-RateLimit-Limit, X-RateLimit-Remaining) are included in every response.
Profile
GET/api/me— Get your profile and settingsPATCH/api/me— Update your profilewriteEntries
GET/api/drafts— List your draftsGET/api/entries/:id— Get your own entry by IDPOST/api/entries— Create an entry or draftwritePATCH/api/entries/:id— Update an entrywriteDELETE/api/entries/:id— Delete an entrywritePOST/api/entries/:id/publish— Publish a draftwriteExample: Create an Entry
curl -X POST https://api.inkwell.social/api/entries \
-H "Authorization: Bearer ink_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"title": "My First API Post",
"body_html": "<p>Hello from the API!</p>",
"privacy": "public",
"tags": ["api", "automation"],
"category": "tech"
}'To create a draft instead, add "status": "draft" to the request body. Drafts can be published later with POST /api/entries/:id/publish.
Images
POST/api/images— Upload an image (base64 data URI)writeGET/api/images/:id— Get an imageUpload images as base64 data URIs ({"image": "data:image/png;base64,..."}). The response includes an id and url. Use the URL in your entry's body_html as an <img> src.
Public Endpoints
These endpoints work without authentication. Pass an API key to get personalized data (your stamps, bookmarks, relationship status).
GET/api/explore— Public discovery feedGET/api/users/:username— Get a user's public profileGET/api/users/:username/entries— List a user's public entriesGET/api/users/:username/entries/:slug— Get a single public entryGET/api/users/:username/guestbook— Read a user's guestbookEntry Fields
Parameters accepted by POST /api/entries and PATCH /api/entries/:id:
| Field | Type | Notes |
|---|---|---|
title | string | Max 500 chars |
body_html | string | HTML content (required for publishing) |
privacy | string | public, friends_only, private, or custom |
status | string | Set to "draft" to create a draft |
tags | string[] | Array of tag strings |
category | string | e.g. personal, tech, poetry, travel, books |
mood | string | Max 100 chars |
music | string | Embed URL (Spotify, YouTube, etc.) |
excerpt | string | Max 300 chars (auto-generated if blank) |
cover_image_id | UUID | ID from POST /api/images |
sensitive | boolean | Mark as sensitive content |
content_warning | string | Warning text (max 200 chars) |
series_id | UUID | Add to a series |
custom_filter_id | UUID | Required when privacy is custom |
Error Codes
401Unauthorized— Invalid, expired, or missing API key403Forbidden— Write scope required, Plus required, or account blocked404Not Found— Resource doesn't exist or access denied422Unprocessable— Validation errors (missing fields, limits reached)429Too Many Requests— Rate limit exceeded — check Retry-After headerAll error responses include a JSON body with an error string. Validation errors (422) include an errors object with field-level details.
Response Format
All successful responses return JSON with a data wrapper:
{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"title": "My Entry",
"body_html": "<p>Hello world</p>",
"slug": "my-entry",
"privacy": "public",
"status": "published",
"tags": ["hello"],
"category": "personal",
"word_count": 2,
"excerpt": "Hello world",
"published_at": "2026-02-28T12:00:00Z",
"author": {
"id": "...",
"username": "eve",
"display_name": "Eve"
}
}
}List endpoints include a pagination object with page, per_page, and total.
Getting Started
- Create an API key in Settings → API
- Copy the key (it's shown only once)
- Test with:
curl -H "Authorization: Bearer ink_..." https://api.inkwell.social/api/me - Start building your integration
Questions or feedback? Let us know on the roadmap.