Documentation

Build on the agent identity rail.

Eighteen endpoints, one SDK, docs your agent can read itself. Get a key, create a pairing, verify the agent. That’s the whole integration. Manage your app from the developer dashboard.

Quickstart

From zero to a verified agent in three calls. Everything below is live on https://muselovin.com right now.

1

Get an API key

Sign up in the browser, or call the endpoint directly. The key is shown once. Store it as ML_API_KEY.

bash
$ curl -X POST https://muselovin.com/api/v1/apps \
  -H 'Content-Type: application/json' \
  -d '{"email":"you@example.com","app_name":"DemoApp"}'

{ "api_key": "mlk_..." }
2

Create a pairing and show the sentence

Show the pairing_sentence to the human. They paste it into their agent’s chat. The agent knows exactly how to redeem. You poll until it does.

bash
$ curl -X POST https://muselovin.com/api/v1/pairings \
  -H "Authorization: Bearer mlk_..."

{
  "pairing_code": "K7X2QD",
  "pairing_sentence": "Pair me with DemoApp using code K7X2QD. (Agent: redeem by POSTing ...)",
  "poll_secret": "ps_..."
}
3

Verify the agent server-side

After redemption the agent holds an mla_ token. Verify it from your server before trusting any claim it makes.

bash
$ curl -X POST https://muselovin.com/api/v1/tokens/verify \
  -H "Authorization: Bearer mlk_..." \
  -H 'Content-Type: application/json' \
  -d '{"token":"mla_..."}'

{ "valid": true, "agent_id": "ag_9f2..." }

Sign in with Muse button

The drop-in login button. Your site opens the consent screen in a popup. The human approves and pastes one line into their agent’s chat. Your backend learns the verified agent identity the moment the agent redeems. Try it live at /demo/signin. That page plus /demo/api/mint and /demo/api/poll is the reference implementation.

1

Your backend mints a pairing

POST /api/v1/pairings with your mlk_ key, the scopes you need, and an optional payload (share URL + note) that lands in the agent’s inbox on sign-in. Keep the poll_secret server-side. The browser only ever sees the claim_url.

2

The button opens the consent popup

Open the claim_url in a popup from the click handler. Append &popup=1 for the compact consent dialog. Poll your backend until the pairing flips to redeemed.

button.js
async function signInWithMuse() {
  const popup = window.open('about:blank', 'muse-signin', 'width=460,height=700');
  const { claim_url, code } = await (await fetch('/api/mint-pairing', { method: 'POST' })).json();
  popup.location.href = claim_url;
  const timer = setInterval(async () => {
    const s = await (await fetch(`/api/signin-status?code=${code}`)).json();
    if (s.status === 'redeemed') {
      clearInterval(timer); popup.close();
      // bind your session to the verified identity:
      onSignedIn(s.agent_id, s.agent_name);
    }
  }, 2000);
}
3

Your backend polls and binds the session

GET /api/v1/pairings/:code with the x-poll-secret header returns pending, redeemed (with agent_id and agent_name), or expired. On redeemed, create your session against agent_id. That’s the stable identity, verified by the pairing the human approved.

Endpoint reference

The complete protocol. Worked examples for every endpoint live in llms-full.txt.

POST
/api/v1/apps

Self-serve signup. Submit an email and app name, get an mlk_ API key. Shown exactly once.

public · 3/hr per IP

POST
/api/v1/pairings

Create a pairing session. Returns a 6-character code, a poll secret, and the one-line pairing sentence. Accepts an optional payload { share, note }: a content handoff shown on the consent screen and delivered to the agent's pipe on redeem when the message scope was granted.

Bearer mlk_ key

GET
/api/v1/pairings/:code

Poll the session. Returns pending, then redeemed with the agent's ID and name.

x-poll-secret header

POST
/api/v1/pairings/:code/redeem

Called by the agent. Exchanges the code for an mla_ bearer token and a stable agent_id.

public · single use

GET
/api/v1/agents/me

Returns the calling agent's profile: agent_id, name, platform, creation date.

Bearer mla_ token

POST
/api/v1/tokens/verify

Server-side check. Submit an mla_ token, get back valid, agent_id, and app binding.

Bearer mlk_ key

POST
/api/v1/messages

Send a message to one of your paired agents. That is the channel back. Requires the message scope on the agent's grant, else 403. Body: { agent_id, body } (4000 chars max).

Bearer mlk_… key

GET
/api/v1/messages

The agent fetches its pending messages. Unacked messages stay pending. A lost response never loses a message.

Bearer mla_… token

POST
/api/v1/messages/ack

The agent confirms receipt. Body: { ids }. At-least-once delivery.

Bearer mla_… token

POST
/api/v1/admin/apps

Bootstrap endpoint for key issuance outside self-serve.

x-admin-secret header

GET
/api/v1/admin/apps

List every app with usage stats (pairings, connected agents, messages).

x-admin-secret header

POST
/api/v1/admin/apps/:id/verify

Set the verified flag that drives the “Verified developer” badge. Body: { verified: true | false }.

x-admin-secret header

POST
/api/v1/admin/apps/:id/revoke

Revoke an app: kills its API key, every agent token, and pending pairings. Idempotent.

x-admin-secret header

GET
/api/v1/developer/app

Your app's own record and usage. What the dashboard shows. Also the way to check you're verified.

Bearer <redacted> key

POST
/api/v1/developer/app/rotate-key

Issue a fresh API key. The old key dies immediately; the new one is shown exactly once.

Bearer <redacted> key

POST
/api/v1/developer/app/revoke

Permanently revoke your own app. Body must be { confirm: “REVOKE” }. Cannot be undone.

Bearer <redacted> key

GET
/api/v1/developer/agents

Your paired agents: id, name, platform, and whether each one granted the message scope. Powers the dashboard's pipe tester.

Bearer <redacted> key

GET
/api/v1/developer/messages

Your app's recent messages, newest first. Query ?limit= (default 20, max 100). Each message shows pending or acknowledged. Pipe status at a glance.

Bearer <redacted> key

Scopes & consent

Pairing is never a blank check. Every pairing carries an explicit grant the human approves on the consent screen before pasting the pairing sentence.

identity. Always granted.

The app can verify the agent’s identity. Every pairing includes it.

message. Opt-in.

The app can message the agent after pairing. That’s the pipe back. Without it, POST /api/v1/messages is a 403.

Declare at signup

Declare the scopes you want in the signup body (scopes, default ["identity"]). Each pairing can request a subset. Ask for an unregistered scope and you get a 400.

Verified developers

The consent screen shows whether we’ve verified the developer. Unverified apps pair fine. The human sees the badge before approving.

Authentication

Two credential types. Both bearer tokens. Both stored as hashes. We never keep a raw secret.

mlk_. App keys.

Issued at signup. Authenticates your app for creating pairings and verifying tokens. Keep it server-side.

mla_. Agent tokens.

Minted at redeem, scoped to one agent and one app. One-year sliding lifetime; re-pairing revokes the previous token.

ps_. Poll secrets.

Returned with each pairing. Sent as x-poll-secret so only your app can watch its own pairing sessions.

Limits & guarantees

The rails we hold during the beta.

Codes

6 characters, 10-minute TTL, single use. 5 pairings per hour per IP.

Tokens

One year, sliding. Old tokens die on re-pair and on explicit revocation.

Identity

Stable agent_id per agent, per app. Same agent, same ID, every time.

Messages

Apps reach only agents that granted them the message scope. 4000 chars per message, 120 sends per hour per app. At-least-once delivery with explicit acks.

Operations

Data doesn’t pile up. A daily job enforces retention: acknowledged messages go 30 days after acknowledgement, unacknowledged 30 days after sending, pairings 90 days after creation. The full schedule is in the privacy policy.

GET
/api/cron/cleanup

Runs the retention sweep immediately and returns the counts deleted. Intended for the daily scheduled job. Same retention rules as the dashboard’s messages list.

x-admin-secret header

Node SDK

Zero dependencies. Pairing, polling, verification, types. On npm as @muselovin/sdk.

node
$ npm install @muselovin/sdk

import { MuseLovin } from "@muselovin/sdk";
const ml = new MuseLovin({ apiKey: process.env.ML_API_KEY! });

const { code, sentence } = await ml.createPairing();
const agent = await ml.waitForRedeem(code);
const { valid } = await ml.verifyToken(agent.token);

Get building.

Keys are free during the beta and take under a minute. Questions? Talk to us.