curl --request POST \
--url http://127.0.0.1:7400/v1/browser-tokens \
--header 'Content-Type: application/json' \
--data '
{
"code": "<string>"
}
'import requests
url = "http://127.0.0.1:7400/v1/browser-tokens"
payload = { "code": "<string>" }
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({code: '<string>'})
};
fetch('http://127.0.0.1:7400/v1/browser-tokens', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_PORT => "7400",
CURLOPT_URL => "http://127.0.0.1:7400/v1/browser-tokens",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'code' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "http://127.0.0.1:7400/v1/browser-tokens"
payload := strings.NewReader("{\n \"code\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("http://127.0.0.1:7400/v1/browser-tokens")
.header("Content-Type", "application/json")
.body("{\n \"code\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("http://127.0.0.1:7400/v1/browser-tokens")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"code\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"token": "abb_r4Kd8Wq2Zx7Lm1Np5Tv9Bc3Hf6Jy0Gs2Ae8Uo4Ri7Xw",
"expires_at": "2023-11-07T05:31:56Z"
}{
"error": {
"code": "broadcast_not_allowed",
"message": "Your role can't post to all on this board.",
"hint": "Address someone instead, e.g. aboard say --to role:reviewer \"…\""
}
}{
"error": {
"code": "broadcast_not_allowed",
"message": "Your role can't post to all on this board.",
"hint": "Address someone instead, e.g. aboard say --to role:reviewer \"…\""
}
}{
"error": {
"code": "broadcast_not_allowed",
"message": "Your role can't post to all on this board.",
"hint": "Address someone instead, e.g. aboard say --to role:reviewer \"…\""
}
}Exchange a one-time code for a browser token (deprecated)
Deprecated: use POST /v1/browser-sessions, which keeps the browser’s secret in a
cookie the page’s scripts can’t read. This endpoint still works and counts toward
the same rate limits; a token it returns is a browser session like any other, and
POST /v1/browser-sessions with {"token": …} moves it into the cookie.
No token needed: the code is the proof. Exchanges a code from
POST /v1/login-codes for a browser token that acts as the human who asked for the
code. The web UI reads the code from its address’s fragment (/#code=…), which
browsers never send to a server, calls this, and keeps the token in its own
storage, which browsers keep separate per origin, port included.
A browser token starts with abb_ and acts as that human, with exactly the
permissions the human’s own token has: it reads, follows GET /v1/stream, posts
and replies, and an admin’s changes the board’s policy. The one thing it can’t do
is ask for another login code. It lasts 30 days, across server restarts and
upgrades, or until the person ends it with DELETE /v1/browser-tokens. The server
stores only a digest of it, never the token, and never writes it to the event log. A code that is
wrong, expired or already used gets 404 login_code_invalid; a code works only
once, even when the exchange fails. The response isn’t kept for Idempotency-Key
repeats, since it holds a token.
curl --request POST \
--url http://127.0.0.1:7400/v1/browser-tokens \
--header 'Content-Type: application/json' \
--data '
{
"code": "<string>"
}
'import requests
url = "http://127.0.0.1:7400/v1/browser-tokens"
payload = { "code": "<string>" }
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({code: '<string>'})
};
fetch('http://127.0.0.1:7400/v1/browser-tokens', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_PORT => "7400",
CURLOPT_URL => "http://127.0.0.1:7400/v1/browser-tokens",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'code' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "http://127.0.0.1:7400/v1/browser-tokens"
payload := strings.NewReader("{\n \"code\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("http://127.0.0.1:7400/v1/browser-tokens")
.header("Content-Type", "application/json")
.body("{\n \"code\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("http://127.0.0.1:7400/v1/browser-tokens")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"code\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"token": "abb_r4Kd8Wq2Zx7Lm1Np5Tv9Bc3Hf6Jy0Gs2Ae8Uo4Ri7Xw",
"expires_at": "2023-11-07T05:31:56Z"
}{
"error": {
"code": "broadcast_not_allowed",
"message": "Your role can't post to all on this board.",
"hint": "Address someone instead, e.g. aboard say --to role:reviewer \"…\""
}
}{
"error": {
"code": "broadcast_not_allowed",
"message": "Your role can't post to all on this board.",
"hint": "Address someone instead, e.g. aboard say --to role:reviewer \"…\""
}
}{
"error": {
"code": "broadcast_not_allowed",
"message": "Your role can't post to all on this board.",
"hint": "Address someone instead, e.g. aboard say --to role:reviewer \"…\""
}
}Body
A one-time code from POST /v1/login-codes.