Mint an API key with a wallet signature — no browser, no key needed (agents start here)
curl --request POST \
--url https://api.hashlock.markets/v1/keys \
--header 'Content-Type: application/json' \
--data '
{
"rail": "evm",
"address": "0xYourAddress",
"message": "Hashlock Markets — create an API key.\n\nAddress: 0xYourAddress\nKey name: my-agent\nScopes: read, taker, maker\nNonce: <GET /v1/keys/nonce>\nIssued At: 2026-09-30T12:00:00Z",
"signature": "0x…"
}
'import requests
url = "https://api.hashlock.markets/v1/keys"
payload = {
"rail": "evm",
"address": "0xYourAddress",
"message": "Hashlock Markets — create an API key.
Address: 0xYourAddress
Key name: my-agent
Scopes: read, taker, maker
Nonce: <GET /v1/keys/nonce>
Issued At: 2026-09-30T12:00:00Z",
"signature": "0x…"
}
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({
rail: 'evm',
address: '0xYourAddress',
message: 'Hashlock Markets — create an API key.\n\nAddress: 0xYourAddress\nKey name: my-agent\nScopes: read, taker, maker\nNonce: <GET /v1/keys/nonce>\nIssued At: 2026-09-30T12:00:00Z',
signature: '0x…'
})
};
fetch('https://api.hashlock.markets/v1/keys', 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.hashlock.markets/v1/keys",
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([
'rail' => 'evm',
'address' => '0xYourAddress',
'message' => 'Hashlock Markets — create an API key.
Address: 0xYourAddress
Key name: my-agent
Scopes: read, taker, maker
Nonce: <GET /v1/keys/nonce>
Issued At: 2026-09-30T12:00:00Z',
'signature' => '0x…'
]),
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.hashlock.markets/v1/keys"
payload := strings.NewReader("{\n \"rail\": \"evm\",\n \"address\": \"0xYourAddress\",\n \"message\": \"Hashlock Markets — create an API key.\\n\\nAddress: 0xYourAddress\\nKey name: my-agent\\nScopes: read, taker, maker\\nNonce: <GET /v1/keys/nonce>\\nIssued At: 2026-09-30T12:00:00Z\",\n \"signature\": \"0x…\"\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.hashlock.markets/v1/keys")
.header("Content-Type", "application/json")
.body("{\n \"rail\": \"evm\",\n \"address\": \"0xYourAddress\",\n \"message\": \"Hashlock Markets — create an API key.\\n\\nAddress: 0xYourAddress\\nKey name: my-agent\\nScopes: read, taker, maker\\nNonce: <GET /v1/keys/nonce>\\nIssued At: 2026-09-30T12:00:00Z\",\n \"signature\": \"0x…\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.hashlock.markets/v1/keys")
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 \"rail\": \"evm\",\n \"address\": \"0xYourAddress\",\n \"message\": \"Hashlock Markets — create an API key.\\n\\nAddress: 0xYourAddress\\nKey name: my-agent\\nScopes: read, taker, maker\\nNonce: <GET /v1/keys/nonce>\\nIssued At: 2026-09-30T12:00:00Z\",\n \"signature\": \"0x…\"\n}"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"key": "<string>",
"prefix": "<string>",
"scopes": [
"<string>"
],
"name": "<string>",
"expiresAt": "2023-11-07T05:31:56Z"
}{
"error": "<string>"
}Account and keys
Mint an API key with a wallet signature — no browser, no key needed (agents start here)
Sign, with the wallet, a message that says `create an API key`, names the address and carries a nonce from `GET /v1/keys/nonce`. Optional lines `Key name: <name>` and `Scopes: read, taker` (default all three) decide the key — they are read from the signed text only. The key belongs to the account that wallet SIGNS IN to (created on first use); a wallet proved onto another account does not reach it. An account with only a wallet holds ONE live key: a new signed mint replaces the previous one (also the way to recover a lost or leaked key). An account signed up at /developers with email, Google or Telegram holds up to 10. All keys of an account share one rate budget. It expires after 90 days (`expiresAt`; mint a new one to renew), an account holds at most 10 live keys, the owner is told (in Telegram, when linked) of every new one in Telegram, and the plaintext key is returned once. Signing rules per rail are those of POST /v1/wallets/<chain>.
POST
/
v1
/
keys
Mint an API key with a wallet signature — no browser, no key needed (agents start here)
curl --request POST \
--url https://api.hashlock.markets/v1/keys \
--header 'Content-Type: application/json' \
--data '
{
"rail": "evm",
"address": "0xYourAddress",
"message": "Hashlock Markets — create an API key.\n\nAddress: 0xYourAddress\nKey name: my-agent\nScopes: read, taker, maker\nNonce: <GET /v1/keys/nonce>\nIssued At: 2026-09-30T12:00:00Z",
"signature": "0x…"
}
'import requests
url = "https://api.hashlock.markets/v1/keys"
payload = {
"rail": "evm",
"address": "0xYourAddress",
"message": "Hashlock Markets — create an API key.
Address: 0xYourAddress
Key name: my-agent
Scopes: read, taker, maker
Nonce: <GET /v1/keys/nonce>
Issued At: 2026-09-30T12:00:00Z",
"signature": "0x…"
}
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({
rail: 'evm',
address: '0xYourAddress',
message: 'Hashlock Markets — create an API key.\n\nAddress: 0xYourAddress\nKey name: my-agent\nScopes: read, taker, maker\nNonce: <GET /v1/keys/nonce>\nIssued At: 2026-09-30T12:00:00Z',
signature: '0x…'
})
};
fetch('https://api.hashlock.markets/v1/keys', 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.hashlock.markets/v1/keys",
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([
'rail' => 'evm',
'address' => '0xYourAddress',
'message' => 'Hashlock Markets — create an API key.
Address: 0xYourAddress
Key name: my-agent
Scopes: read, taker, maker
Nonce: <GET /v1/keys/nonce>
Issued At: 2026-09-30T12:00:00Z',
'signature' => '0x…'
]),
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.hashlock.markets/v1/keys"
payload := strings.NewReader("{\n \"rail\": \"evm\",\n \"address\": \"0xYourAddress\",\n \"message\": \"Hashlock Markets — create an API key.\\n\\nAddress: 0xYourAddress\\nKey name: my-agent\\nScopes: read, taker, maker\\nNonce: <GET /v1/keys/nonce>\\nIssued At: 2026-09-30T12:00:00Z\",\n \"signature\": \"0x…\"\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.hashlock.markets/v1/keys")
.header("Content-Type", "application/json")
.body("{\n \"rail\": \"evm\",\n \"address\": \"0xYourAddress\",\n \"message\": \"Hashlock Markets — create an API key.\\n\\nAddress: 0xYourAddress\\nKey name: my-agent\\nScopes: read, taker, maker\\nNonce: <GET /v1/keys/nonce>\\nIssued At: 2026-09-30T12:00:00Z\",\n \"signature\": \"0x…\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.hashlock.markets/v1/keys")
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 \"rail\": \"evm\",\n \"address\": \"0xYourAddress\",\n \"message\": \"Hashlock Markets — create an API key.\\n\\nAddress: 0xYourAddress\\nKey name: my-agent\\nScopes: read, taker, maker\\nNonce: <GET /v1/keys/nonce>\\nIssued At: 2026-09-30T12:00:00Z\",\n \"signature\": \"0x…\"\n}"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"key": "<string>",
"prefix": "<string>",
"scopes": [
"<string>"
],
"name": "<string>",
"expiresAt": "2023-11-07T05:31:56Z"
}{
"error": "<string>"
}