---
title: via API
description: 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](/sharing/share-notes).

## Base URL

```plaintext
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:

```http
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:

```json
{
  "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:

```bash
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:

```bash
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:

```bash
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:

```bash
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-Summary` for a short description.
- `X-Expires-At` with an ISO 8601 date.
- `X-Show-Properties` as `true` or `false`.

The response contains the publication ID and public URL:

```json
{
  "cuid": "abc123",
  "url": "https://share.octarine.app/s/abc123"
}
```

### Publish JSON

Use JSON when you want to set structured fields:

```bash
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

```bash
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

```bash
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:

```bash
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:

```bash
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

```bash
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:

```bash
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:

```json
{
  "settings": {},
  "storage": {
    "image_bytes_used": 12582912,
    "image_limit_bytes": 1000000000
  }
}
```

## Use An API Client

In Postman, Bruno, Insomnia, Yaak, or another API caller:

1. Create an environment variable named `base_url` with `https://share.octarine.app`.
2. Send `POST {{base_url}}/api/auth/publish` with the JSON authentication body.
3. Save the returned `token` as a secret environment variable.
4. Set request authorization to **Bearer Token** using that variable.
5. 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:

```plaintext
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:

```json
{
  "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](/sharing/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.
