curl --request POST \
--url https://api.ekiden.fi/api/v1/access/activate \
--header 'Content-Type: application/json' \
--data '
{
"code": "<string>",
"public_key": "<string>",
"signature": "<string>",
"signed_at": 123,
"nonce": "<string>",
"party_id": "<string>"
}
'import requests
url = "https://api.ekiden.fi/api/v1/access/activate"
payload = {
"code": "<string>",
"public_key": "<string>",
"signature": "<string>",
"signed_at": 123,
"nonce": "<string>",
"party_id": "<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>',
public_key: '<string>',
signature: '<string>',
signed_at: 123,
nonce: '<string>',
party_id: '<string>'
})
};
fetch('https://api.ekiden.fi/api/v1/access/activate', 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.ekiden.fi/api/v1/access/activate",
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>',
'public_key' => '<string>',
'signature' => '<string>',
'signed_at' => 123,
'nonce' => '<string>',
'party_id' => '<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 := "https://api.ekiden.fi/api/v1/access/activate"
payload := strings.NewReader("{\n \"code\": \"<string>\",\n \"public_key\": \"<string>\",\n \"signature\": \"<string>\",\n \"signed_at\": 123,\n \"nonce\": \"<string>\",\n \"party_id\": \"<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("https://api.ekiden.fi/api/v1/access/activate")
.header("Content-Type", "application/json")
.body("{\n \"code\": \"<string>\",\n \"public_key\": \"<string>\",\n \"signature\": \"<string>\",\n \"signed_at\": 123,\n \"nonce\": \"<string>\",\n \"party_id\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.ekiden.fi/api/v1/access/activate")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"code\": \"<string>\",\n \"public_key\": \"<string>\",\n \"signature\": \"<string>\",\n \"signed_at\": 123,\n \"nonce\": \"<string>\",\n \"party_id\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"activated": true,
"badge": true,
"multiplier_bps": 1
}Activate a closed-launch access code
curl --request POST \
--url https://api.ekiden.fi/api/v1/access/activate \
--header 'Content-Type: application/json' \
--data '
{
"code": "<string>",
"public_key": "<string>",
"signature": "<string>",
"signed_at": 123,
"nonce": "<string>",
"party_id": "<string>"
}
'import requests
url = "https://api.ekiden.fi/api/v1/access/activate"
payload = {
"code": "<string>",
"public_key": "<string>",
"signature": "<string>",
"signed_at": 123,
"nonce": "<string>",
"party_id": "<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>',
public_key: '<string>',
signature: '<string>',
signed_at: 123,
nonce: '<string>',
party_id: '<string>'
})
};
fetch('https://api.ekiden.fi/api/v1/access/activate', 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.ekiden.fi/api/v1/access/activate",
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>',
'public_key' => '<string>',
'signature' => '<string>',
'signed_at' => 123,
'nonce' => '<string>',
'party_id' => '<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 := "https://api.ekiden.fi/api/v1/access/activate"
payload := strings.NewReader("{\n \"code\": \"<string>\",\n \"public_key\": \"<string>\",\n \"signature\": \"<string>\",\n \"signed_at\": 123,\n \"nonce\": \"<string>\",\n \"party_id\": \"<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("https://api.ekiden.fi/api/v1/access/activate")
.header("Content-Type", "application/json")
.body("{\n \"code\": \"<string>\",\n \"public_key\": \"<string>\",\n \"signature\": \"<string>\",\n \"signed_at\": 123,\n \"nonce\": \"<string>\",\n \"party_id\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.ekiden.fi/api/v1/access/activate")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"code\": \"<string>\",\n \"public_key\": \"<string>\",\n \"signature\": \"<string>\",\n \"signed_at\": 123,\n \"nonce\": \"<string>\",\n \"party_id\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"activated": true,
"badge": true,
"multiplier_bps": 1
}Body
Public Stage 1 activation request (spec ยง4). The caller is NOT yet
whitelisted. The wallet signs a canonical message that binds the code hash,
its root address, and signed_at:
ekiden-stage1-activate:{sha256(normalized code)}:{root_address}:{signed_at}
using the same wallet-signature scheme JWT login uses. The root address is
derived from public_key (never trusted from the client), exactly as
/authorize does.
Plaintext access code. Normalized (trim + uppercase) and hashed server-side; the plaintext is never persisted (S1-D5).
Wallet public key, same encoding as /authorize's public_key.
Wallet signature over the canonical activation message.
Unix seconds at which the message was signed. Must be within the configured signature window of server time.
Replay nonce bound into the Canton activation message. REQUIRED on the Canton rail, ignored on Aptos.
Canton party id (<hint>::<fingerprint>). REQUIRED on the Canton rail,
ignored on Aptos.
Canton has no address derivable from the public key alone, so the wallet
signs for its party and the server derives the root from that party โ
the same identity /authorize uses. The party's ::<fingerprint> suffix
commits to the public key, so a caller cannot claim someone else's party.