# MiniURL REST API

Base URL: https://workers.miniurl.com/api/v1

MiniURL's REST API supports OAuth-scoped Agent access, guest-first link creation, and registered account management.

## Authentication

- Guest token: POST /api/v1/guest/token returns a gt_ token for short-lived no-signup usage.
- OAuth Agent token: use a short-lived scoped at_ token issued by OAuth 2.1 + PKCE for production machine access.
- Legacy API key: registered accounts use mk_ keys for compatibility only; never expose a long-lived mk_ key to an Agent model.

Use tokens as:

```http
Authorization: Bearer gt_xxx
Authorization: Bearer mk_xxx
Authorization: Bearer at_xxx
```

Registered API keys are limited to 30 requests/minute on Free and 120 requests/minute on Pro. Read `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and `X-RateLimit-Reset` on responses. On HTTP 429, honor `Retry-After` before retrying.

## Preferred Agent Flow

1. POST /api/v1/guest/token
2. POST /api/v1/shorten
3. GET /api/v1/account/status to inspect remaining quota
4. For production machine access, discover OAuth metadata and complete OAuth 2.1 + PKCE to receive a scoped at_ token
5. Keep guest registration/verification as a human account bootstrap flow; do not relay the returned mk_ key to a model

## Endpoints

- POST /api/v1/guest/token - Create a temporary guest token
- POST /api/v1/guest/register - Send a verification code to the user email
- POST /api/v1/guest/verify - Verify the code and create a permanent account
- GET /api/v1/account/status - Get account type, quota, and features
- POST /api/v1/account/upgrade - Create a short checkout URL for upgrading to Pro
- POST /api/v1/alias/check - Check whether an alias is available
- POST /api/v1/shorten - Create a short link
- POST /api/v1/links/bulk - Create multiple links in one request
- GET /api/v1/links - List registered-user links
- GET /api/v1/links/{alias} - Get one link
- PATCH /api/v1/links/{alias} - Update one link
- DELETE /api/v1/links/{alias} - Delete one link
- GET /api/v1/links/{alias}/stats - Get link analytics
- GET /api/v1/domains - List available domains for a registered user
- GET /api/v1/tags - List account tags
- POST /api/v1/tags - Create a tag
- DELETE /api/v1/tags/{tagId} - Delete a tag
- GET /api/v1/links/{alias}/tags - List tags assigned to a link
- POST /api/v1/links/{alias}/tags - Assign a tag to a link
- DELETE /api/v1/links/{alias}/tags/{tagId} - Remove a tag from a link
- POST /api/analytics/link-conversion - Track a conversion attributed to a Pro link click
- GET /api/analytics/link-conversion/pixel - Track a signed conversion with a 1x1 GIF
- GET /.well-known/oauth-protected-resource - Discover the OAuth authorization server for MCP
- GET /.well-known/oauth-authorization-server - Discover OAuth endpoints
- POST /oauth/register - Register a public OAuth client
- POST /oauth/token - Exchange an authorization code or refresh token
- POST /oauth/revoke - Revoke an OAuth token
- GET /api/v1/agents - List Agent identities
- POST /api/v1/agents - Create an Agent identity
- PATCH /api/v1/agents/{agentId} - Update Agent scopes and policy
- POST /api/v1/agents/{agentId}/tokens - Issue a short-lived Agent token
- POST /api/v1/agents/{agentId}/kill - Emergency revoke an Agent and its tokens
- GET /api/v1/agents/{agentId}/audit - Read Agent tool-call audit events
- GET /api/v1/agent/approvals - List pending human approvals
- POST /api/v1/agent/approvals/{approvalId}/{decision} - Approve or reject a pending Agent operation
- GET /api/v1/oauth/request/{requestId} - Read the human-facing OAuth consent request
- POST /api/v1/oauth/approve - Approve an OAuth consent request

## Pro Conversion Attribution

Every active Pro redirect appends two temporary attribution parameters to the destination URL:

- `mu_click`: the click identifier
- `mu_sig`: an HMAC signature proving that the click was issued by MiniURL

Capture and persist both values on the landing page. The attribution window is 30 days and uses the last MiniURL click associated with the event. MiniURL snapshots `utm_source`, `utm_medium`, `utm_campaign`, `utm_term`, and `utm_content` when the click happens, so later destination URL changes do not rewrite historical campaign attribution.

For a server-to-server conversion, use the API key belonging to the short-link account:

```bash
curl -X POST https://workers.miniurl.com/api/analytics/link-conversion \
  -H "Authorization: Bearer mk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "clickId": "CLICK_ID_FROM_MU_CLICK",
    "conversionType": "purchase",
    "value": 49.99,
    "currency": "USD",
    "externalOrderId": "ORDER_1001",
    "eventId": "purchase_ORDER_1001"
  }'
```

For browser or pixel calls, omit the API key and send `clickSignature` (or `mu_sig`) with the captured signature. Never expose an `mk_` API key in browser code.

Validation and retry rules:

- `eventId` is required unless `externalOrderId` is present.
- `purchase`, `sale`, and `refund` require `externalOrderId`.
- `value` must be non-negative and requires a three-letter ISO 4217 `currency`.
- Send refunds as a positive `value` with `conversionType: "refund"`; the dashboard subtracts them from revenue.
- A safe retry returns HTTP 200 with `duplicate: true` and the original `conversionId`; a new event returns HTTP 201.
- The JSON endpoint reports validation or delivery errors. The pixel always returns an image and should only be used when response confirmation is unavailable.

## Important Response Field

Always inspect meta in API responses. It can include usage, notices, limitations, and upgrade hints that should be relayed to the user.

Use Idempotency-Key on create, bulk create, update, delete, and upgrade mutations. Reusing a key with the same payload replays the original result; an in-flight duplicate returns retryable IDEMPOTENCY_IN_PROGRESS. Prefer cursor/next_cursor pagination over offset. OAuth Agent tokens can send dry_run=true to preview a redirect create/update without side effects. Link/tag deletion, domain changes, and billing require human approval by default.

Aliases are unique per domain. miniurl.com aliases require 4-64 characters; verified custom-domain aliases allow 1-64 characters. GET, PATCH, and DELETE for /links/{alias} accept a domain query parameter that defaults to miniurl.com. Free accounts include one custom domain, and links created through every interface expire after 30 days by default.

Full OpenAPI spec: https://miniurl.com/openapi.json
