rdyrct

Developer docs

The REST API and the MCP server: how to authenticate, and what each one can do. Both are free on every plan.

REST API

Every organization route under /api/orgs/:orgId answers to a scoped API key the same way it answers to a signed-in browser: create, read, update and delete links, read click analytics, manage domains and members.

Getting a key

While signed in, create one for an organization you own from API keys, or directly: POST /api/orgs/:orgId/api-keys with {"name": "..."}. The response carries the raw key once.

Revoke one with DELETE /api/orgs/:orgId/api-keys/:keyId. A revoked key's next request gets a 401 at once, wherever it is used.

Authenticating a request

GET /api/orgs/org_id/links
Authorization: Bearer rdyrct_live_...

The key resolves to your account, so the usual role check applies: reading needs at least viewer, most writes need member. Plan caps still apply underneath, the same way they do in the app.

MCP server

A hosted MCP endpoint, for an AI chatbot's connectors. It answers to OAuth, which is the way to use it: no key to copy or lose, and every current MCP client supports it.

Endpoint

https://rdyrct.com/api/mcp

One address, stateless: nothing to establish before calling a tool, nothing to carry between calls.

OAuth

rdyrct is a full OAuth 2.1 authorization server for this endpoint: point an MCP client at it and it discovers the flow itself from /.well-known/oauth-protected-resource/api/mcp. Signing in shows a consent screen naming the client and what it's asking for; revoke it any time from the API page's MCP tab.

Client identity is a URL (a Client ID Metadata Document), not a pre-registered id: current MCP clients handle this automatically. Or tell your agent to set it up for you:

Access requirements

Any rdyrct account works, on any plan. Sign in with OAuth or authenticate with an API key, no region or extra approval needed. A tool call can only see or change what the signed-in account has permission for: reading needs at least a viewer role on the organization, most writes need member. What a tool can do is capped by the org's plan limits (links, domains, and so on), the same limits that apply in the app itself.

Tools

ToolDoesMinimum role
create_linkShorten a URL, optionally with a chosen slug or custom domainmember
update_linkPoint an existing link (found by slug or destination) at a new destination or titlemember
delete_linkDelete a link, found by slug or destinationmember
list_linksSearch or list an org's links with click countsviewer
get_link_statsOne link's clicks, countries, referrers and devicesviewer
get_org_statsTotals, top links, and links with no clicks in 30 daysviewer
get_plan_usageThe org's link cap and how much of it is usedviewer
invite_memberInvite someone to the org by emailadmin
generate_qr_codeA plain QR code (PNG) for any URL, no org needednone

Every tool but generate_qr_code takes an optional org_id. Left out, it assumes your sole organization, and asks which one you mean if you belong to more than one.

Example prompts

Once connected, an assistant can act on these directly:

  • "Shorten this URL and tag it 'launch': https://example.com/blog/post"
  • "Make a QR code for our menu page"
  • "How many clicks has my 'launch' link gotten, by country?"
  • "What's my org's plan usage, links and domains?"
  • "Invite jane@company.com to my org as a member"

API key (alternative to OAuth)

For a client that takes a static bearer token instead of doing OAuth itself, use a scoped API key the same way the REST API does above:

URL: https://rdyrct.com/api/mcp
Header: Authorization: Bearer YOUR_API_KEY
POST /api/mcp
Authorization: Bearer rdyrct_live_...
Content-Type: application/json
Accept: application/json, text/event-stream
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "create_link",
    "arguments": { "destination": "https://example.com/blog/post" }
  }
}