Register, create an API key, then call /api/v1 from another website or app. The examples below use curl. The same JSON works from JavaScript fetch and the HamLink SDK.
HamLink API v1 lives at /api/v1. Send JSON. Every answer uses the same shape, so another website can check ok before it reads data.
Success
{
"ok": true,
"data": { }
}Failure
{
"ok": false,
"error": "Unauthorized.",
"code": "unauthorized"
}Sign in and open the API page to copy your key. It starts with hlk_. Send it on every private request:
Header
Authorization: Bearer hlk_your_key Content-Type: application/json
Browsers on other websites may call this API directly. CORS allows GET, POST, PATCH, PUT, and DELETE. The official client is the HamLink SDK.
This route needs no key. It returns the public card only: name, callsign, country, address, and volunteer status. It does not return email, messages, or device secrets.
Request
curl https://www.hamlink.info/api/v1/public/operators/K2ABC
Response
{
"ok": true,
"data": {
"callsign": "K2ABC",
"display_name": "Alex",
"country": "Kuwait",
"address": "k2abc@hamlink.radio",
"volunteer": {
"role": "gateway",
"country": "Kuwait",
"online": true
}
}
}Browser example
const res = await fetch("https://www.hamlink.info/api/v1/public/operators/K2ABC");
const body = await res.json();
if (!body.ok) throw new Error(body.error);
const op = body.data;
document.getElementById("hamlink").textContent =
op.display_name + " · " + op.callsign + " · " + (op.country || "Unknown");Unknown callsigns return 404 with code: "not_found". You can also look up k2abc@hamlink.radio in the same path.
Same fields as Settings → Account. Send only the fields you want to change.
Update profile
curl -X PATCH https://www.hamlink.info/api/v1/me \
-H "Authorization: Bearer hlk_your_key" \
-H "Content-Type: application/json" \
-d '{
"display_name": "Alex",
"country": "Kuwait",
"callsign": "K2ABC"
}'Add an address
curl -X POST https://www.hamlink.info/api/v1/addresses \
-H "Authorization: Bearer hlk_your_key" \
-H "Content-Type: application/json" \
-d '{ "address": "club" }'club becomes club@hamlink.radio. The primary address cannot be deleted. Remove an extra address with DELETE /api/v1/addresses/ADDRESS_ID.
Create
curl -X POST https://www.hamlink.info/api/v1/contacts \
-H "Authorization: Bearer hlk_your_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Relay Station",
"address": "g0xyz@hamlink.radio",
"callsign": "G0XYZ"
}'Response
{ "ok": true, "data": { "id": "CONTACT_ID" } }Update
curl -X PATCH https://www.hamlink.info/api/v1/contacts/CONTACT_ID \
-H "Authorization: Bearer hlk_your_key" \
-H "Content-Type: application/json" \
-d '{ "name": "Updated name" }'Delete
curl -X DELETE https://www.hamlink.info/api/v1/contacts/CONTACT_ID \ -H "Authorization: Bearer hlk_your_key"
List them with GET /api/v1/contacts.
Send
curl -X POST https://www.hamlink.info/api/v1/messages \
-H "Authorization: Bearer hlk_your_key" \
-H "Content-Type: application/json" \
-d '{
"to": "g0xyz@hamlink.radio",
"subject": "Net tonight",
"body": "I will be on the gateway at 19:00.",
"priority": "ROUTINE"
}'List inbox
curl "https://www.hamlink.info/api/v1/inbox?folder=Inbox" \ -H "Authorization: Bearer hlk_your_key"
Move to another folder, or star it
curl -X PATCH https://www.hamlink.info/api/v1/messages/MESSAGE_ID \
-H "Authorization: Bearer hlk_your_key" \
-H "Content-Type: application/json" \
-d '{ "folder": "Archive", "starred": true, "read": true }'Move to Trash
curl -X DELETE https://www.hamlink.info/api/v1/messages/MESSAGE_ID \ -H "Authorization: Bearer hlk_your_key"
Reply with POST /api/v1/messages/MESSAGE_ID/reply and { "body": "..." }. Delivery history is GET /api/v1/messages/MESSAGE_ID/events.
Creating a device is the same as Settings → Devices. The secret is returned once. Do not log it in a public website.
Register a device
curl -X POST https://www.hamlink.info/api/v1/devices \
-H "Authorization: Bearer hlk_your_key" \
-H "Content-Type: application/json" \
-d '{ "name": "Shack PC", "platform": "windows" }'Response
{
"ok": true,
"data": {
"id": "DEVICE_ID",
"name": "Shack PC",
"device_public_id": "HL-NODE-...",
"device_secret": "shown-once"
}
}Create a station
curl -X POST https://www.hamlink.info/api/v1/stations \
-H "Authorization: Bearer hlk_your_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Home station",
"callsign": "K2ABC",
"country_code": "KW",
"role": "PERSONAL",
"radio_available": true,
"internet_available": true
}'Update with PATCH /api/v1/stations/STATION_ID. Delete with DELETE /api/v1/stations/STATION_ID. role is PERSONAL, RELAY, or GATEWAY.
Save the regulatory profile
curl -X PUT https://www.hamlink.info/api/v1/regulatory \
-H "Authorization: Bearer hlk_your_key" \
-H "Content-Type: application/json" \
-d '{
"jurisdiction": "Kuwait",
"callsign": "K2ABC",
"license_class": "Full",
"allowed_bands": ["VHF", "UHF"],
"allowed_modes": ["AX.25"],
"gateway_permitted": true,
"relay_permitted": true
}'A gateway can be created only after gateway_permitted is true. Then POST /api/v1/gateways with { "region": "Kuwait", "mode": "VHF Packet" }. Turn it off with PATCH /api/v1/gateways/GATEWAY_ID and { "enabled": false }.
Each account may send 60 private requests per minute and 2000 per day. Public profile reads allow 30 per minute per visitor. Responses include X-RateLimit-Remaining and X-RateLimit-Remaining-Day.
Check what is left
curl https://www.hamlink.info/api/v1/limits \ -H "Authorization: Bearer hlk_your_key"
Too many requests
HTTP 429
Retry-After: 48
{
"ok": false,
"error": "Rate limit exceeded. Try again shortly.",
"code": "rate_limited"
}| Status | Code | Meaning |
|---|---|---|
| 401 | unauthorized | Missing or invalid key |
| 403 | forbidden | Not allowed, or the account is blocked |
| 404 | not_found | That record does not belong to this account |
| 409 | conflict | Address or contact already exists |
| 429 | rate_limited | Wait for Retry-After, then try again |
| Action | Method and path |
|---|---|
| Read or update profile | GET or PATCH /api/v1/me |
| Limits | GET /api/v1/limits |
| Public operator card | GET /api/v1/public/operators/:callsign |
| Addresses | GET POST /api/v1/addresses · DELETE /api/v1/addresses/:id |
| Inbox and messages | GET /api/v1/inbox · GET POST /api/v1/messages |
| One message | GET PATCH DELETE /api/v1/messages/:id |
| Read, reply, retry, ack | POST /api/v1/messages/:id/read|reply|retry|ack |
| Delivery events | GET /api/v1/messages/:id/events |
| Attachment | GET /api/v1/attachments/:id |
| Contacts | GET POST /api/v1/contacts · PATCH DELETE /api/v1/contacts/:id |
| Notifications | GET /api/v1/notifications · POST /api/v1/notifications/read |
| Route preview | POST /api/v1/route/preview |
| Bridge status | GET /api/v1/bridge/status |
| Devices | GET POST /api/v1/devices · PATCH DELETE /api/v1/devices/:id |
| Stations | GET POST /api/v1/stations · PATCH DELETE /api/v1/stations/:id |
| Gateways | GET POST /api/v1/gateways · PATCH DELETE /api/v1/gateways/:id |
| Regulatory profile | GET or PUT /api/v1/regulatory |
| Volunteer application | POST /api/v1/volunteers/apply · GET /api/v1/volunteers/me |
Examples use https://www.hamlink.info. Bridge radios still use /api/agent/*.