[docs]
It's just one HTTP call.Send an event. Watch it land.
Everything you need is on this page. No SDK required, no code required either: your AI builder can do all of this from one prompt.
[Anatomy of a log]
This JSON becomes this card.
A log is one tiny package of JSON. Three fields are required, the rest are seasoning.
Payment received
● revenuejust nowrichard@piedpiper.com paid $19
notify: true also sends a push notification to your phone.
Hover the JSON, or the card, to see what maps where
project[Required]Which workspace this belongs to. Your workspace ID, copied once from Setup.
e.g. "wsp_4f2k…"
channel[Required]Which shelf of your feed this lands on. revenue, signups, failures. You invent them just by using them.
e.g. "revenue"
event[Required]The headline. Short, human, emoji up front so you can read the feed at a glance.
e.g. "💰 Payment received"
description[Optional]One sentence of detail under the headline. The who and how much.
e.g. "richard@piedpiper.com paid $19"
icon[Optional]One emoji that becomes the face of the event in the feed. Skipped? We use the one in your title.
e.g. "💰"
notify[Optional]Set true and your phone buzzes. Save it for events you would get out of bed for.
e.g. true
tags[Optional]Little labeled chips on the card. Amounts, plans, ids. Searchable forever.
e.g. {"plan": "Pro", "amount": "$19"}
user_id[Optional]Who did it. Send an email or id and every event builds that customer's timeline.
e.g. "richard@piedpiper.com"
timestamp[Optional]When it happened, in Unix seconds. Skip it and we stamp it on arrival.
e.g. 1735123456
keywords[Optional]Extra search words that do not show on the card but make it findable.
e.g. ["stripe", "checkout"]
parser[Optional]How the description is rendered. MARKDOWN by default, TEXT if you want it raw.
e.g. "MARKDOWN"
[Click any log]
And it opens up.
Every event in the feed is clickable. Inside, the description renders Markdown, and any media URL you send becomes a real preview. Not just text: proof.
{
"channel": "renders",
"event": "🎬 Video rendered",
"description": "**24s clip** for [gwen](mailto:gwen@web.app),
ready to publish.",
"tags": {
"video": "https://cdn.yourapp.com/render-42.mp4",
"duration": "24s",
"preset": "vertical-1080p"
}
}Video rendered
just now24s clip for gwen, ready to publish.
MarkdownDescriptions render bold, links, and lists by default. Write a readable sentence, not a code dump.
MediaAny image, video, or audio URL in your tags embeds automatically, lazy-loaded. Generated a thumbnail, a render, a voice note? Preview it right in the feed.
ButtonsAttach an action link with buttonData: "Open order", "View in admin". One click from the event to the fix.
Media is detected by URL: png, jpg, gif, webp for images · mp4, webm, mov for video · mp3, wav, m4a for audio.
[Quick start]
Live in three steps.
- [01]
Create a workspace
Sign up, name your workspace, done. Unlimited events, 7-day history, no card.
- [02]
Grab your key
Your Project ID and API key live in Workspace → Settings → API (click Reveal to show the key). Each key is scoped to a single workspace. Authenticate every request with it:
Authorization: <your-api-key>Keep it server-side. Never ship it to the browser.
- [03]
Send your first event
[curl]curl -X POST https://api.logs.so/v2/log \ -H "Content-Type: application/json" \ -H "Authorization: your-api-key-here" \ -d '{ "project": "my-project", "channel": "api-logs", "event": "User Registration", "description": "New user registered successfully", "tags": {"user": "123"}, "notify": false, "timestamp": 1735123456 }'Open your feed. It's already there.
[API reference]
One endpoint.
https://api.logs.so/v2/logAuthorization: <your-api-key>
| Field | Type | Required | Description |
|---|---|---|---|
| project | string | yes | Your workspace/project ID |
| channel | string | yes | Channel name for the log |
| event | string | yes | Event title |
| description | string | no | Event description |
| icon | string | no | Single emoji character |
| notify | boolean | no | Send notification (default: false) |
| tags | object | no | Custom tags (object) |
| parser | string | no | Parser type [MARKDOWN, TEXT] |
| user_id | string | no | User ID |
| timestamp | number | no | Unix timestamp (seconds) |
| keywords | array | no | Keywords for search (array) |
export interface CreateLogParams {
project: string,
channel: string,
event: string,
description?: string,
icon?: string,
notify?: boolean,
tags?: Record<string, any>,
parser?: string,
user_id?: string,
timestamp?: number, // Unix timestamp (seconds)
keywords?: string[],
}
export interface CreateLogRemoteParams extends CreateLogParams {
apiKey: string;
apiUrl?: string;
}[Examples]
Pick your flavor.
curl -X POST https://api.logs.so/v2/log \
-H "Content-Type: application/json" \
-H "Authorization: your-api-key-here" \
-d '{
"project": "my-project",
"channel": "api-logs",
"event": "User Registration",
"description": "New user registered successfully",
"tags": {"user": "123"},
"notify": false,
"timestamp": 1735123456
}'[Connect your agent]
Your agent can read the feed.
Hook an MCP client to your feed and ask things like:
[compare]
Compare, check a cron, trace a webhook
If a channel should have moved and did not, these pages map the same silence idea onto a status page, an event feed, a cron ping, an overdue check, or a Stripe webhook that returned 200 while payment never processed.
Rather not write any of this?
Paste one prompt into your AI builder and it wires everything up.