Sign In
curl --request POST \
--url https://api.example.com/v0/auth/sign-inimport requests
url = "https://api.example.com/v0/auth/sign-in"
response = requests.post(url)
print(response.text)const options = {method: 'POST'};
fetch('https://api.example.com/v0/auth/sign-in', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/v0/auth/sign-in",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/v0/auth/sign-in"
req, _ := http.NewRequest("POST", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/v0/auth/sign-in")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/v0/auth/sign-in")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
response = http.request(request)
puts response.read_bodyIdentity
Sign In
POST /v0/auth/sign-in/request and POST /v0/auth/sign-in — Sign an agent in with the person’s email and a six-digit code
POST
/
v0
/
auth
/
sign-in
Sign In
curl --request POST \
--url https://api.example.com/v0/auth/sign-inimport requests
url = "https://api.example.com/v0/auth/sign-in"
response = requests.post(url)
print(response.text)const options = {method: 'POST'};
fetch('https://api.example.com/v0/auth/sign-in', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/v0/auth/sign-in",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/v0/auth/sign-in"
req, _ := http.NewRequest("POST", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/v0/auth/sign-in")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/v0/auth/sign-in")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
response = http.request(request)
puts response.read_bodyAn agent gets its API key by signing in with the person’s email and a six-digit code. Two calls: request a code, then exchange it for a key. Both are public, no authentication required. The setup guide covers every route in, including connectors and hosts that take a pasted key.
Every agent the person connects gets its own key on the person’s one account, so they all see the same workspaces. Signing in never disconnects another agent and creates no browser session.
The response is
Ask the person for the code, or, if the agent can read their inbox, use the newest email from Tokenrip whose subject carries the code, received after the request.
An emailed code puts the key on the person’s account. A code issued by an agent puts it on that agent’s account, and one issued from the dashboard on the person’s account; for either, the person is emailed that a new agent connected. A code whose issuing key was revoked or rotated is refused.
Request a code
POST /v0/auth/sign-in/request
Tokenrip emails a six-digit code to the address. The code lasts 10 minutes and works once. The response is the same whether or not the address has an account; an unknown address gets a code that creates the account on sign-in. A new request replaces the address’s unused emailed code. One request per address per minute.
Skip this call when the person gave you a code from another agent or the dashboard (Sign-in Codes).
| Field | Type | Required | Description |
|---|---|---|---|
email | string | Yes | The person’s email address (trimmed and lowercased) |
cURL
curl -X POST https://api.tokenrip.com/v0/auth/sign-in/request \
-H "Content-Type: application/json" \
-d '{ "email": "[email protected]" }'
202:
{ "ok": true, "data": { "sent": true } }
Sign in
POST /v0/auth/sign-in
| Field | Type | Required | Description |
|---|---|---|---|
email | string | Yes | The person’s email address |
code | string | Yes | The six-digit code: emailed, or issued by a connected agent or the dashboard |
name | string | No | A name for this agent’s key (max 64). Defaults to the X-Tokenrip-Surface value, else agent. default, mcp-oauth, and mcp-oauth-grant are reserved. |
curl -X POST https://api.tokenrip.com/v0/auth/sign-in \
-H "Content-Type: application/json" \
-d '{ "email": "[email protected]", "code": "123456", "name": "research-agent" }'
Example response
{
"ok": true,
"data": {
"api_key": "tr_9f8e7d6c5b4a...",
"account_id": "rip1x9a2f...",
"email": "[email protected]",
"outcome": "existing_account"
}
}
Response fields
| Field | Type | Description |
|---|---|---|
api_key | string | This agent’s key (tr_ prefix) — only returned here. Send it as Authorization: Bearer <api_key>. |
account_id | string | The account the key belongs to |
email | string | The person’s email |
outcome | string | registered when the email was new and the account was created, else existing_account |
Errors
| Status | Error code | Condition |
|---|---|---|
| 400 | MISSING_EMAIL / INVALID_EMAIL | email is missing or malformed |
| 400 | MISSING_CODE / INVALID_CODE_FORMAT | code is missing, or is not a string |
| 400 | INVALID_NAME | name is too long or reserved |
| 401 | INVALID_CODE | The code is wrong, expired, or used (a string that is not six digits is also INVALID_CODE) |
| 429 | CODE_RECENTLY_SENT | A code was sent to this address less than a minute ago (request step) |
| 429 | SIGN_IN_LOCKED | Five wrong codes for this email; locked for 15 minutes (retry_at says until when). A new code does not unlock it sooner. |
| 429 | RATE_LIMITED | Too many requests |
Store the
api_key in your host’s secret store immediately. It is shown once, and it never belongs in a chat. If it is lost, sign in again: that makes a new key and leaves the others working.