Rift Links
by saltyskip
README.md
<p align="center">
<img src="./.github/assets/banner.gif" alt="Rift" width="100%">
</p>
# Rift
**Deep links for humans and agents.** — [riftl.ink](https://riftl.ink)
Rift is a deep linking platform that creates smart, cross-platform links with structured context for AI agents. One link works across iOS, Android, and web — with built-in click tracking, attribution, webhooks, and machine-readable metadata.
## Why Rift
- **Cross-platform deep links** — one URL routes to the right destination on iOS, Android, or web
- **Agent-readable** — structured `agent_context` and JSON-LD so AI agents understand what a link does and can act on it ([`/llms.txt`](https://api.riftl.ink/llms.txt) for machine-readable API reference)
- **Real-time webhooks** — get notified on clicks, attributions, and conversions with HMAC-signed payloads
- **Conversion tracking** — attribute post-install events (signups, purchases, deposits) back to the link that drove them via backend webhooks
- **Smart landing pages** — split layout showing both a human CTA and machine-readable data panel
- **Deferred deep linking** — user clicks a link, installs the app, and lands on the right content
- **Custom domains** — use your own brand: `go.yourcompany.com/summer-sale`
- **x402 payments** — accept crypto payments for API access via the x402 protocol
## Architecture
```
server/ Rust + Axum API server (MongoDB, Sentry)
client/mobile/ Swift/Kotlin mobile SDK via UniFFI
sdk/web/ TypeScript web SDK (ESM/CJS/IIFE)
marketing/ Next.js documentation and marketing site
```
The server separates **domain logic** (`services/`) from **transport layers** (`api/` for HTTP, `mcp/` for MCP protocol). Both transports share the same services, repos, and models. `AppState` lives in `app.rs`.
## Quick Start
### Prerequisites
- Rust 1.75+
- Node.js 20+ (for web SDK builds)
- MongoDB (local or Atlas)
- Optional: Custom domain with DNS access (any provider)
### Pick a setup path
#### CLI path
Best if you want the guided onboarding flow.
```sh
curl -fsSL https://raw.githubusercontent.com/saltyskip/rift/main/client/cli/install.sh | sh
rift init
rift domains setup
rift doctor
```
The CLI handles account setup, stores your secret key locally, helps you verify your primary
and alternate domains, and tests connectivity.
#### Manual path
Best if you want to drive the API and DNS steps yourself.
### Setup
```sh
# Enable shared git hooks (auto-builds web SDK, checks mobile SDK)
git config core.hooksPath .githooks
```
### Run the server
```sh
cd server
cp ../.env.example .env
# Edit .env with your MongoDB URI
cargo run
```
The server starts on `http://localhost:3000`. MongoDB is optional — the server boots without it (auth, links, and webhooks will be disabled).
### Get an API key
```sh
curl -X POST http://localhost:3000/v1/auth/signup \
-H "Content-Type: application/json" \
-d '{"email": "you@example.com"}'
```
### Set up a custom domain
Follow the custom domain guide in `marketing/src/app/docs/domains/page.tsx` or the hosted docs at
`https://riftl.ink/docs/domains`. You will:
- create a primary branded domain
- add a CNAME pointing to the Rift server
- verify ownership with a TXT record
- optionally add an alternate domain for more reliable Open in App behavior
### Create a publishable key
After verifying your email and setting up a custom domain, create a publishable key for SDK use:
```sh
curl -X POST http://localhost:3000/v1/auth/publishable-keys \
-H "Authorization: Bearer rl_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"domain": "go.yourcompany.com"}'
```
### Create a link
```sh
curl -X POST http://localhost:3000/v1/links \
-H "Authorization: Bearer rl_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"web_url": "https://example.com",
"ios_deep_link": "myapp://product/123",
"agent_context": {
"action": "purchase",
"cta": "Buy Now",
"description": "Premium widget, 50% off today"
}
}'
```
### Resolve a link (agent)
```sh
curl http://localhost:3000/r/LINK_ID \
-H "Accept: application/json"
```
Response:
```json
{
"link_id": "LINK_ID",
"ios_deep_link": "myapp://product/123",
"web_url": "https://example.com",
"metadata": null,
"agent_context": {
"action": "purchase",
"cta": "Buy Now",
"description": "Premium widget, 50% off today"
},
"_rift_meta": {
"context": "This is a Rift deep link...",
"source": "tenant_asserted",
"status": "active",
"tenant_domain": "go.yourcompany.com",
"tenant_verified": true
}
}
```
## MCP Server (for Claude Code, Cursor, etc.)
Rift exposes an [MCP](https://modelcontextprotocol.io/) endpoint at `/mcp` using streamable HTTP transport. This lets AI coding tools manage deep links directly.
### Setup with Claude Code
Add a `.mcp.json` to your project root:
```json
{
"mcpServers": {
"rift": {
"type": "http",
"url": "http://localhost:3000/mcp",
"headers": {
"x-api-key": "rl_live_YOUR_API_KEY_HERE"
}
}
}
}
```
Claude will then have access to these tools: `links.create`, `links.bulk_create`, `links.get`, `links.list`, `links.update`, `links.delete`, `sources.create`, `sources.list`.
### Setup with other MCP clients
Any MCP client that supports streamable HTTP transport can connect to `http://localhost:3000/mcp`. Pass your API key via the `x-api-key` HTTP header or the `_meta.api_key` field during initialization.
## CI Checks
```sh
cd server
cargo fmt -- --check
cargo clippy -- -D warnings
cargo test
```
## Environment Variables
| Variable | Required | Purpose |
|----------|----------|---------|
| `HOST` / `PORT` | No | Server bind address and port (default `0.0.0.0:3000`) |
| `MONGO_URI` / `MONGO_DB` | No | MongoDB connection (server boots without it) |
| `SENTRY_DSN` | No | Error tracking |
| `RESEND_API_KEY` | No | Email verification via Resend |
| `RESEND_FROM_EMAIL` | No | Sender address for verification emails (default `Rift <noreply@updates.riftl.ink>`) |
| `PUBLIC_URL` | No | Base URL for links and verification emails |
| `FREE_DAILY_LIMIT` | No | Anonymous requests per IP per day (default 5) |
| `X402_ENABLED` | No | Enable x402 crypto payments (`true`/`false`) |
| `X402_RECIPIENT` | No | USDC recipient wallet address |
| `X402_PRICE` | No | Price per request in USDC (default `0.01`) |
| `X402_DESCRIPTION` | No | Resource description shown to payers |
| `X402_FACILITATOR_URL` | No | x402 facilitator URL (default `https://facilitator.x402.org`) |
| `CDP_API_KEY_ID` / `CDP_API_KEY_SECRET` | No | Coinbase Developer Platform keys for x402 |
| `PRIMARY_DOMAIN` | No | Primary domain for link resolution (default `riftl.ink`) |
See `.env.example` for the full list.
## License
The server (`server/`) is licensed under the [Business Source License 1.1](LICENSE). You can use, modify, and self-host it freely — you just can't use it to run a competing commercial deep linking service. The license converts to Apache 2.0 on 2030-03-25.
The SDKs (`sdk/`) are licensed under [Apache 2.0](sdk/LICENSE) — use them freely in your apps with no restrictions.
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessResponsive