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

TierRead (GET)Write (POST/PATCH/DELETE)
Free100 / 15 minN/A
Plus300 / 15 min60 / 15 min

Limits are per API key. Rate limit headers (X-RateLimit-Limit, X-RateLimit-Remaining) are included in every response.

Profile

GET/api/meGet your profile and settings
PATCH/api/meUpdate your profilewrite

Entries

GET/api/draftsList your drafts
GET/api/entries/:idGet your own entry by ID
POST/api/entriesCreate an entry or draftwrite
PATCH/api/entries/:idUpdate an entrywrite
DELETE/api/entries/:idDelete an entrywrite
POST/api/entries/:id/publishPublish a draftwrite

Example: 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/imagesUpload an image (base64 data URI)write
GET/api/images/:idGet an image

Upload 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/explorePublic discovery feed
GET/api/users/:usernameGet a user's public profile
GET/api/users/:username/entriesList a user's public entries
GET/api/users/:username/entries/:slugGet a single public entry
GET/api/users/:username/guestbookRead a user's guestbook

Entry Fields

Parameters accepted by POST /api/entries and PATCH /api/entries/:id:

FieldTypeNotes
titlestringMax 500 chars
body_htmlstringHTML content (required for publishing)
privacystringpublic, friends_only, private, or custom
statusstringSet to "draft" to create a draft
tagsstring[]Array of tag strings
categorystringe.g. personal, tech, poetry, travel, books
moodstringMax 100 chars
musicstringEmbed URL (Spotify, YouTube, etc.)
excerptstringMax 300 chars (auto-generated if blank)
cover_image_idUUIDID from POST /api/images
sensitivebooleanMark as sensitive content
content_warningstringWarning text (max 200 chars)
series_idUUIDAdd to a series
custom_filter_idUUIDRequired when privacy is custom

Error Codes

401UnauthorizedInvalid, expired, or missing API key
403ForbiddenWrite scope required, Plus required, or account blocked
404Not FoundResource doesn't exist or access denied
422UnprocessableValidation errors (missing fields, limits reached)
429Too Many RequestsRate limit exceeded — check Retry-After header

All 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

  1. Create an API key in Settings → API
  2. Copy the key (it's shown only once)
  3. Test with: curl -H "Authorization: Bearer ink_..." https://api.inkwell.social/api/me
  4. Start building your integration

Questions or feedback? Let us know on the roadmap.