via API
Publish and manage shared Octarine notes from a terminal, API client, or local agent.
The Share API powers Octarine's public note publishing. You can use it to read a public note, publish or update a note, list your publications, manage sharing settings, and unpublish content.
The API is currently a preview. Public reads are ready to use. Authenticated access requires credentials from an active Octarine Pro device.
To publish from the Octarine desktop interface instead, see From the App.
Base URL
https://share.octarine.app
All request and response bodies use UTF-8. JSON responses use application/json.
Public And Authenticated Requests
Public note pages, note data, images, and social preview images do not require authentication. Publishing and account-level operations require a short-lived bearer token.
An authenticated token can publish, update, list, and unpublish notes for your sharing account. Treat it like a password.
A published note is public, not private or access-controlled. Anyone with its URL can read the note data. Setting show_properties to false also removes stored properties from the public JSON response, but the title, body, summary, timestamps, and any enabled author name remain public.
Authentication
Request a session token with an Octarine Pro license key and the activation ID of the device using that license:
POST /api/auth/publish
Content-Type: application/json
{
"license_key": "YOUR-LICENSE-KEY",
"instance_id": "YOUR-DEVICE-ACTIVATION-ID"
}
A successful response includes a bearer token and its expiry:
{
"token": "eyJ...",
"expires_at": "2026-07-29T14:00:00.000Z",
"user_cuid": "user-id",
"user": {
"name": "Your name",
"email": "you@example.com"
}
}
Tokens expire after two hours. There is no refresh endpoint; request another token when needed.
You can copy both your license key and device activation ID from Settings -> Pro.
Do not give a license key or device activation ID to a hosted agent, shared API workspace, checked-in script, or chat prompt. Authenticate locally and pass only the short-lived token through a secret environment variable.
Use The API From A Terminal
The examples below use curl.
Set the base URL and credentials in the current terminal session:
export OCTARINE_API="https://share.octarine.app"
export OCTARINE_LICENSE_KEY="YOUR-LICENSE-KEY"
export OCTARINE_INSTANCE_ID="YOUR-DEVICE-ACTIVATION-ID"
Request a token:
curl --fail-with-body --silent --show-error \
"$OCTARINE_API/api/auth/publish" \
-H "Content-Type: application/json" \
--data "{\"license_key\":\"$OCTARINE_LICENSE_KEY\",\"instance_id\":\"$OCTARINE_INSTANCE_ID\"}"
Copy the token value from the response into the current terminal session:
export OCTARINE_TOKEN="TOKEN-FROM-RESPONSE"
Reuse that token until it is close to expiry. Do not authenticate before every API call.
Publish A Markdown File
Raw Markdown is the simplest format for terminal use:
curl --fail-with-body --silent --show-error \
"$OCTARINE_API/api/publish" \
-X POST \
-H "Authorization: Bearer $OCTARINE_TOKEN" \
-H "Content-Type: text/markdown" \
--data-binary @note.md
Leading YAML frontmatter is parsed as note properties and removed from the stored body. You can also send:
X-Summaryfor a short description.X-Expires-Atwith an ISO 8601 date.X-Show-Propertiesastrueorfalse.
The response contains the publication ID and public URL:
{
"cuid": "abc123",
"url": "https://share.octarine.app/s/abc123"
}
Publish JSON
Use JSON when you want to set structured fields:
curl --fail-with-body --silent --show-error \
"$OCTARINE_API/api/publish" \
-X POST \
-H "Authorization: Bearer $OCTARINE_TOKEN" \
-H "Content-Type: application/json" \
--data '{
"content": "# Project update\n\nWhat changed this week",
"title": "Project update",
"summary": "What changed this week",
"show_properties": true,
"properties": {
"status": "published",
"tags": ["project", "weekly"]
}
}'
Read A Public Note
curl --fail-with-body --silent --show-error \
"$OCTARINE_API/api/notes/abc123"
Public note responses include the Markdown content, title, summary, author when enabled, appearance settings, and publication timestamps. When showProperties is true, properties contains the stored properties. When it is false, properties is an empty object.
List Your Publications
curl --fail-with-body --silent --show-error \
"$OCTARINE_API/api/user/notes?limit=50" \
-H "Authorization: Bearer $OCTARINE_TOKEN"
The list includes active and expired publications, newest first. Unpublished notes are omitted. limit defaults to 50 and accepts 1 through 100. When next_cursor is not null, pass it unchanged as the cursor query parameter to read the next page:
curl --get --fail-with-body --silent --show-error \
"$OCTARINE_API/api/user/notes" \
-H "Authorization: Bearer $OCTARINE_TOKEN" \
--data-urlencode "limit=50" \
--data-urlencode "cursor=$NEXT_CURSOR"
Update A Publication
Updating a note creates a version snapshot before applying the changes:
curl --fail-with-body --silent --show-error \
"$OCTARINE_API/api/notes/abc123" \
-X PATCH \
-H "Authorization: Bearer $OCTARINE_TOKEN" \
-H "Content-Type: application/json" \
--data '{
"content": "# Updated note\n\nUpdated from the terminal",
"summary": "Updated from the terminal"
}'
Only include fields you want to change. A JSON null clears optional fields such as title, summary, properties, or expires_at.
Unpublish A Note
curl --fail-with-body --silent --show-error \
"$OCTARINE_API/api/unshare" \
-X POST \
-H "Authorization: Bearer $OCTARINE_TOKEN" \
-H "Content-Type: application/json" \
--data '{"cuid":"abc123"}'
Unpublishing removes public access and schedules images uploaded with that publication for deletion. It does not delete the source Markdown file in your Octarine workspace.
Upload Images
Image publishing uses multipart/form-data. Write image references in the Markdown as [[diagram.png]], then attach each file using its exact filename as the form field name:
curl --fail-with-body --silent --show-error \
"$OCTARINE_API/api/publish" \
-X POST \
-H "Authorization: Bearer $OCTARINE_TOKEN" \
-F "content=<note-with-images.md" \
-F "title=Illustrated note" \
-F "diagram.png=@diagram.png;type=image/png"
The service validates the file extension, declared media type, and image signature before upload, then replaces the wikilink with a public image URL. PNG, JPEG, GIF, and WebP images are supported. Each image can be up to 5 MiB, and each account has 1 GB (1,000,000,000 bytes) of image storage.
Uploaded image URLs are public while the publication is active. Expiry blocks new note and image API reads, but the image bytes continue to use storage until you unpublish the note. Content that a reader already downloaded or cached cannot be recalled.
GET /api/user/settings reports current image usage:
{
"settings": {},
"storage": {
"image_bytes_used": 12582912,
"image_limit_bytes": 1000000000
}
}
Use An API Client
In Postman, Bruno, Insomnia, Yaak, or another API caller:
- Create an environment variable named
base_urlwithhttps://share.octarine.app. - Send
POST {{base_url}}/api/auth/publishwith the JSON authentication body. - Save the returned
tokenas a secret environment variable. - Set request authorization to Bearer Token using that variable.
- Send JSON, raw Markdown, or multipart bodies as described above.
Keep personal environments private. Shared collections should contain variable names and example values, never a real license key, activation ID, or token.
Use The API With An Agent
Prefer a local agent that can read secrets from environment variables. Give it the base URL, a short-lived token, the endpoint allowlist it needs, and clear approval rules.
A safe instruction looks like this:
Use https://share.octarine.app.
Read the bearer token from OCTARINE_TOKEN and never print it.
You may read, list, publish, and update notes.
Ask before calling /api/unshare or changing sharing settings.
Do not retry POST or PATCH automatically.
On 429, honor Retry-After or use exponential backoff with jitter.
POST /api/publish is not idempotent: retrying it can create a duplicate publication. PATCH creates version history, so blind retries can also create unwanted snapshots. Agents should show the target publication ID before updates and require confirmation before unpublishing.
Endpoint Reference
| Method | Path | Auth | Purpose |
|---|---|---|---|
POST | /api/auth/publish | License credentials | Create a two-hour session token |
POST | /api/publish | Bearer token | Publish a note |
GET | /api/notes/:cuid | Public | Read a published note |
PATCH | /api/notes/:cuid | Bearer token | Update an owned publication |
GET | /api/notes/:cuid/versions | Bearer token | List recent version metadata |
GET | /api/notes/:cuid/versions/:version | Bearer token | Read one version |
POST | /api/unshare | Bearer token | Unpublish a note |
GET | /api/user/notes | Bearer token | List your publications |
GET | /api/user/settings | Bearer token | Read sharing settings and image-storage usage |
PUT | /api/user/settings | Bearer token | Replace sharing settings |
PATCH | /api/user/settings | Bearer token | Update name or appearance fields |
GET | /api/images/:userCuid/:noteCuid/:filename | Public | Read an uploaded image |
GET | /api/og/:cuid.png | Public | Read the social preview image |
GET | /s/:cuid | Public | Open the published note page |
Common Errors
All API errors use a machine-readable error field:
{
"error": "unauthorized"
}
| Status | Meaning |
|---|---|
400 | Invalid body, field, property data, or version |
401 | Missing, invalid, or expired credentials |
404 | Publication or version not found, not owned, expired, or unpublished |
405 | Method not allowed |
413 | Request, stored note, or image is too large, or the image-storage quota is exhausted |
429 | Temporarily rate limited; retry later |
For storage, traffic, automation, and fair-use guidance, see Limits & Fair Use.
Quick Answers
Is the Share API public?
Public note reads are available without authentication. Authenticated publishing is a preview and currently requires an Octarine Pro license key plus a device activation ID.
How long does an API token last?
Two hours. Request a new token after it expires and reuse a valid token instead of authenticating before every call.
Can I give the API to an AI agent?
Yes, preferably to a local agent using a short-lived token from a secret environment variable. Do not put your license key or activation ID in a hosted agent prompt.