eQSL Public API
Use these methods from your own website or logging program. Every protected request needs your API key in the HTTP header. Parameters go in the URL path, the query string after ?, or the JSON body — each method below says exactly where.
Base URLhttps://www.eqsl.info/api/v1
Key locationHTTP header — never inside the URL
Header nameAuthorization: Bearer eqsl_live_YOUR_KEY
Methods31 endpoints documented below
Limit120 requests per minute per key
Where to put the API key
- Sign in at https://www.eqsl.info and open Dashboard → API Keys.
- Create a key and copy the full secret. It starts with eqsl_live_ and is shown once.
- On every request, add this header (replace the placeholder with your real key):
Authorization: Bearer eqsl_live_YOUR_KEY
Do not put the key in the URL, query string, or page source that visitors can see. Call the API from your server and keep the key in an environment variable. Required scope is listed on each method. Available scopes: profile:read, profile:write, qso:read, qso:write, qsl:read, qsl:write, awards:read, analytics:read, certificates:read, certificates:write, webhooks:read, webhooks:write.
JavaScript fetch example — the key is only in headers:
const res = await fetch("https://www.eqsl.info/api/v1/me", {
headers: {
"Authorization": "Bearer " + process.env.EQSL_API_KEY,
"Accept": "application/json"
}
});
const json = await res.json();
// Your details are in json.data
// If something failed, read json.error.code and json.error.messageWhere parameters go
- Path — part of the URL itself. Example:
https://www.eqsl.info/api/v1/profiles/W1AW (callsign is W1AW). - Query — after a question mark, used to filter what you fetch. Example:
https://www.eqsl.info/api/v1/qsos?band=20m&per_page=10 - Body — JSON sent with POST or PATCH, with header
Content-Type: application/json. This is where you write the details you want to save.
Successful JSON looks like:
{
"data": { },
"error": null,
"meta": { "request_id": "req_...", "page": 1, "per_page": 50, "total": 1 }
}Errors: 401 unauthorized (key missing or wrong), 403 forbidden (key missing that scope), 404 not found, 422 validation_error (bad parameter), 429 rate_limited.
Profiles
Read and update the operator account that owns the API key.
GET
Get your profile
scope profile:readReturns the profile of the operator who owns this API key: callsign, display name, grid, country, and bio.
Details you receive: data.id, data.callsign, data.display_name, data.grid, data.country, data.bio, data.created_at
Complete URL
https://www.eqsl.info/api/v1/mePattern: https://www.eqsl.info/api/v1/me
Where to write the key
HTTP header only: Authorization: Bearer eqsl_live_YOUR_KEY
No path, query, or body parameters. Call the complete URL with the key header.
How to fetch it
curl -H "Authorization: Bearer eqsl_live_YOUR_KEY" \
"https://www.eqsl.info/api/v1/me"
PATCH
Update your profile
scope profile:writeChanges fields on your own profile. Send only the fields you want to change. Callsign is stored in uppercase.
Details you receive: The updated profile (same fields as GET /me).
Complete URL
https://www.eqsl.info/api/v1/mePattern: https://www.eqsl.info/api/v1/me
Where to write the key
HTTP header only: Authorization: Bearer eqsl_live_YOUR_KEY
Where to write each parameter
| Name | Write it in | Required | Example | What it controls |
|---|
| callsign | Body | No | ASIM2 | Your station callsign. |
| display_name | Body | No | Asim | Name shown on the site. |
| grid | Body | No | ML64 | Maidenhead grid square. |
| country | Body | No | Pakistan | Country name. |
| bio | Body | No | HF operator | Short biography. |
How to fetch it
curl -X PATCH -H "Authorization: Bearer eqsl_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"display_name":"Asim","grid":"ML64","country":"Pakistan"}' \
"https://www.eqsl.info/api/v1/me"GET
Look up a public profile
scope profile:readLooks up another operator by callsign. Returns only public fields. Does not return email or private account data.
Details you receive: data.callsign, data.display_name, data.grid, data.country, data.bio
Complete URL
https://www.eqsl.info/api/v1/profiles/W1AWPattern: https://www.eqsl.info/api/v1/profiles/{callsign}
Where to write the key
HTTP header only: Authorization: Bearer eqsl_live_YOUR_KEY
Where to write each parameter
| Name | Write it in | Required | Example | What it controls |
|---|
| callsign | Path | Yes | W1AW | The callsign to look up. Write it in the URL, not in the body. |
How to fetch it
curl -H "Authorization: Bearer eqsl_live_YOUR_KEY" \
"https://www.eqsl.info/api/v1/profiles/W1AW"
QSO logbook
Create, list, update, and delete contacts in the key owner's logbook.
GET
List your QSOs
scope qso:readReturns your logged contacts, newest first. Use query parameters after ? to filter which contacts you receive. Pagination is in meta.page, meta.per_page, and meta.total.
Details you receive: Each QSO: id, callsign, qso_date, qso_time, freq, band, mode, rst_sent, rst_rcvd, grid, entity, notes, status, matched_qso_id
Complete URL
https://www.eqsl.info/api/v1/qsos?per_page=10&page=1&band=20mPattern: https://www.eqsl.info/api/v1/qsos?per_page=10&page=1&band=20m
Where to write the key
HTTP header only: Authorization: Bearer eqsl_live_YOUR_KEY
Where to write each parameter
| Name | Write it in | Required | Example | What it controls |
|---|
| page | Query | No | 1 | Page number. Starts at 1. |
| per_page | Query | No | 10 | How many QSOs to return (1–200). Default 50. |
| callsign | Query | No | W1AW | Only QSOs with this callsign. |
| band | Query | No | 20m | Only this band. |
| mode | Query | No | FT8 | Only this mode. |
| status | Query | No | CONFIRMED | PENDING, CONFIRMED, or UNCONF. |
| since | Query | No | 2026-01-01 | QSOs on or after this date (YYYY-MM-DD). |
| until | Query | No | 2026-12-31 | QSOs on or before this date. |
How to fetch it
curl -H "Authorization: Bearer eqsl_live_YOUR_KEY" \
"https://www.eqsl.info/api/v1/qsos?per_page=10&page=1&band=20m"
POST
Log a new QSO
scope qso:writeAdds one contact to your logbook. After save, the server tries to match it and refreshes awards. Status starts as PENDING.
Details you receive: The created QSO, including its id. Use that id for update, delete, or match.
Complete URL
https://www.eqsl.info/api/v1/qsosPattern: https://www.eqsl.info/api/v1/qsos
Where to write the key
HTTP header only: Authorization: Bearer eqsl_live_YOUR_KEY
Where to write each parameter
| Name | Write it in | Required | Example | What it controls |
|---|
| callsign | Body | Yes | W1AW | Station you worked. |
| qso_date | Body | Yes | 2026-09-22 | Date in YYYY-MM-DD. |
| qso_time | Body | No | 14:30 | UTC time. HH:MM or HH:MM:SS. |
| band | Body | No | 20m | Band, for example 40m, 20m, 2m. |
| mode | Body | No | SSB | Mode, for example SSB, CW, FT8. |
| freq | Body | No | 14.074 | Frequency in MHz. |
| rst_sent | Body | No | 59 | Report you sent. |
| rst_rcvd | Body | No | 59 | Report you received. |
| grid | Body | No | FN31 | Their grid square. |
| entity | Body | No | United States | DXCC entity or country. |
| notes | Body | No | POTA | Free-text notes. |
How to fetch it
curl -X POST -H "Authorization: Bearer eqsl_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"callsign":"W1AW","qso_date":"2026-09-22","qso_time":"14:30","band":"20m","mode":"SSB"}' \
"https://www.eqsl.info/api/v1/qsos"GET
Get one QSO
scope qso:readReturns a single contact that belongs to you. The id comes from the list or create response.
Details you receive: One QSO object (same fields as list).
Complete URL
https://www.eqsl.info/api/v1/qsos/00000000-0000-0000-0000-000000000001Pattern: https://www.eqsl.info/api/v1/qsos/{id}
Where to write the key
HTTP header only: Authorization: Bearer eqsl_live_YOUR_KEY
Where to write each parameter
| Name | Write it in | Required | Example | What it controls |
|---|
| id | Path | Yes | 00000000-0000-0000-0000-000000000001 | QSO UUID. Replace {id} in the URL with this value. |
How to fetch it
curl -H "Authorization: Bearer eqsl_live_YOUR_KEY" \
"https://www.eqsl.info/api/v1/qsos/00000000-0000-0000-0000-000000000001"
PATCH
Update a QSO
scope qso:writeChanges one or more fields on a contact you own. Send only the fields to change in the JSON body.
Details you receive: The updated QSO.
Complete URL
https://www.eqsl.info/api/v1/qsos/00000000-0000-0000-0000-000000000001Pattern: https://www.eqsl.info/api/v1/qsos/{id}
Where to write the key
HTTP header only: Authorization: Bearer eqsl_live_YOUR_KEY
Where to write each parameter
| Name | Write it in | Required | Example | What it controls |
|---|
| id | Path | Yes | 00000000-0000-0000-0000-000000000001 | Which QSO to update. |
| notes | Body | No | Confirmed | Any QSO field from create may be sent. |
| band | Body | No | 40m | Example of a field you can change. |
How to fetch it
curl -X PATCH -H "Authorization: Bearer eqsl_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"notes":"Updated from my website"}' \
"https://www.eqsl.info/api/v1/qsos/00000000-0000-0000-0000-000000000001"DELETE
Delete a QSO
scope qso:writeRemoves one contact from your logbook and refreshes award progress. There is no request body.
Details you receive: data.id and data.deleted = true
Complete URL
https://www.eqsl.info/api/v1/qsos/00000000-0000-0000-0000-000000000001Pattern: https://www.eqsl.info/api/v1/qsos/{id}
Where to write the key
HTTP header only: Authorization: Bearer eqsl_live_YOUR_KEY
Where to write each parameter
| Name | Write it in | Required | Example | What it controls |
|---|
| id | Path | Yes | 00000000-0000-0000-0000-000000000001 | Which QSO to delete. |
How to fetch it
curl -X DELETE -H "Authorization: Bearer eqsl_live_YOUR_KEY" \
"https://www.eqsl.info/api/v1/qsos/00000000-0000-0000-0000-000000000001"
POST
Upload many QSOs
scope qso:writeCreates up to 1000 contacts in one request. Invalid rows are skipped and listed in results. Valid rows are inserted.
Details you receive: data.inserted, data.failed, data.results (per row), data.qsos
Complete URL
https://www.eqsl.info/api/v1/qsos/bulkPattern: https://www.eqsl.info/api/v1/qsos/bulk
Where to write the key
HTTP header only: Authorization: Bearer eqsl_live_YOUR_KEY
Where to write each parameter
| Name | Write it in | Required | Example | What it controls |
|---|
| qsos | Body | Yes | [{"callsign":"W1AW","qso_date":"2026-09-22"}] | Array of QSO objects. Same fields as a single create. |
How to fetch it
curl -X POST -H "Authorization: Bearer eqsl_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"qsos":[{"callsign":"W1AW","qso_date":"2026-09-22","band":"20m","mode":"SSB"}]}' \
"https://www.eqsl.info/api/v1/qsos/bulk"POST
Match and confirm a QSO
scope qso:writeTries to confirm this contact against the other station's log. A match needs the same callsign pair, same band, same mode, and times within 30 minutes. No JSON body is required.
Details you receive: data.matched, data.confirmed, data.newly_confirmed, data.qso
Complete URL
https://www.eqsl.info/api/v1/qsos/00000000-0000-0000-0000-000000000001/matchPattern: https://www.eqsl.info/api/v1/qsos/{id}/match
Where to write the key
HTTP header only: Authorization: Bearer eqsl_live_YOUR_KEY
Where to write each parameter
| Name | Write it in | Required | Example | What it controls |
|---|
| id | Path | Yes | 00000000-0000-0000-0000-000000000001 | The QSO to match. |
How to fetch it
curl -X POST -H "Authorization: Bearer eqsl_live_YOUR_KEY" \
"https://www.eqsl.info/api/v1/qsos/00000000-0000-0000-0000-000000000001/match"
ADIF import and export
Move a whole log in or out using ADIF text.
POST
Import an ADIF file
scope qso:writeParses ADIF and inserts QSOs. Duplicates (same call, date, band, mode, and minute) are skipped unless you set mode=merge in the query string.
Details you receive: data.parsed, data.imported, data.skipped_duplicates, data.invalid
Complete URL
https://www.eqsl.info/api/v1/adif/import?mode=skipPattern: https://www.eqsl.info/api/v1/adif/import?mode=skip
Where to write the key
HTTP header only: Authorization: Bearer eqsl_live_YOUR_KEY
Where to write each parameter
| Name | Write it in | Required | Example | What it controls |
|---|
| mode | Query | No | skip | skip (default) ignores duplicates. merge inserts them anyway. |
| adif | Body | Yes | <call:4>W1AW ... | Raw ADIF text inside JSON: { "adif": "..." }. Or send the file as text/plain with no JSON wrapper. |
How to fetch it
curl -X POST -H "Authorization: Bearer eqsl_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"adif":"<ADIF_VER:5>3.1.4 <EOH>\n<CALL:4>W1AW <QSO_DATE:8>20260922 <BAND:3>20M <MODE:3>SSB <EOR>"}' \
"https://www.eqsl.info/api/v1/adif/import?mode=skip"GET
Download your log as ADIF
scope qso:readReturns your log as an ADIF text file (not JSON). Optional query filters limit which QSOs are included.
Details you receive: A .adi file (Content-Type: text/plain).
Complete URL
https://www.eqsl.info/api/v1/adif/export?band=20m&since=2026-01-01Pattern: https://www.eqsl.info/api/v1/adif/export?band=20m&since=2026-01-01
Where to write the key
HTTP header only: Authorization: Bearer eqsl_live_YOUR_KEY
Where to write each parameter
| Name | Write it in | Required | Example | What it controls |
|---|
| band | Query | No | 20m | Export only this band. |
| mode | Query | No | FT8 | Export only this mode. |
| since | Query | No | 2026-01-01 | Start date. |
| until | Query | No | 2026-12-31 | End date. |
How to fetch it
curl -H "Authorization: Bearer eqsl_live_YOUR_KEY" \
"https://www.eqsl.info/api/v1/adif/export?band=20m&since=2026-01-01"
eQSL cards
Send electronic QSL cards and read cards you sent or received.
GET
List eQSL cards
scope qsl:readLists cards. direction=sent shows cards you sent. direction=received shows cards addressed to you.
Details you receive: Each card: id, from_user_id, to_callsign, to_user_id, qso_id, message, status, created_at
Complete URL
https://www.eqsl.info/api/v1/qsl?direction=received&per_page=20Pattern: https://www.eqsl.info/api/v1/qsl?direction=received&per_page=20
Where to write the key
HTTP header only: Authorization: Bearer eqsl_live_YOUR_KEY
Where to write each parameter
| Name | Write it in | Required | Example | What it controls |
|---|
| direction | Query | No | sent | sent (default) or received. |
| status | Query | No | SENT | PENDING, SENT, RECEIVED, or ARCHIVED. |
| page | Query | No | 1 | Page number. |
| per_page | Query | No | 20 | Cards per page. |
How to fetch it
curl -H "Authorization: Bearer eqsl_live_YOUR_KEY" \
"https://www.eqsl.info/api/v1/qsl?direction=received&per_page=20"
POST
Send an eQSL
scope qsl:writeSends a card to a callsign. If that callsign has an account, they are linked automatically. Status is set to SENT.
Details you receive: The created card.
Complete URL
https://www.eqsl.info/api/v1/qslPattern: https://www.eqsl.info/api/v1/qsl
Where to write the key
HTTP header only: Authorization: Bearer eqsl_live_YOUR_KEY
Where to write each parameter
| Name | Write it in | Required | Example | What it controls |
|---|
| to_callsign | Body | Yes | W1AW | Who receives the card. |
| qso_id | Body | No | 00000000-0000-0000-0000-000000000001 | Optional QSO this card confirms. Must be yours. |
| message | Body | No | 73 | Short message on the card. |
How to fetch it
curl -X POST -H "Authorization: Bearer eqsl_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"to_callsign":"W1AW","message":"Thanks for the QSO"}' \
"https://www.eqsl.info/api/v1/qsl"PATCH
Change eQSL status
scope qsl:writeUpdates a card you sent or received. Setting status to RECEIVED notifies the sender (webhook qsl.received).
Details you receive: The updated card.
Complete URL
https://www.eqsl.info/api/v1/qsl/00000000-0000-0000-0000-000000000001Pattern: https://www.eqsl.info/api/v1/qsl/{id}
Where to write the key
HTTP header only: Authorization: Bearer eqsl_live_YOUR_KEY
Where to write each parameter
| Name | Write it in | Required | Example | What it controls |
|---|
| id | Path | Yes | 00000000-0000-0000-0000-000000000001 | Card id from the list. |
| status | Body | Yes | RECEIVED | One of PENDING, SENT, RECEIVED, ARCHIVED. |
How to fetch it
curl -X PATCH -H "Authorization: Bearer eqsl_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"status":"RECEIVED"}' \
"https://www.eqsl.info/api/v1/qsl/00000000-0000-0000-0000-000000000001"Analytics
Totals calculated from the key owner's logbook. No request body.
GET
Logbook summary
scope analytics:readOne overview of the whole log: how many QSOs, how many confirmed, unique callsigns, entities, bands, and modes, plus first and last QSO dates.
Details you receive: total_qsos, confirmed, pending, unconfirmed, unique_callsigns, unique_entities, unique_bands, unique_modes, first_qso, last_qso
Complete URL
https://www.eqsl.info/api/v1/analytics/summaryPattern: https://www.eqsl.info/api/v1/analytics/summary
Where to write the key
HTTP header only: Authorization: Bearer eqsl_live_YOUR_KEY
No path, query, or body parameters. Call the complete URL with the key header.
How to fetch it
curl -H "Authorization: Bearer eqsl_live_YOUR_KEY" \
"https://www.eqsl.info/api/v1/analytics/summary"
GET
DXCC / entities
scope analytics:readGroups your QSOs by entity (country / DXCC name stored on each QSO).
Details you receive: total_entities and entities[] with key, count, confirmed
Complete URL
https://www.eqsl.info/api/v1/analytics/dxccPattern: https://www.eqsl.info/api/v1/analytics/dxcc
Where to write the key
HTTP header only: Authorization: Bearer eqsl_live_YOUR_KEY
No path, query, or body parameters. Call the complete URL with the key header.
How to fetch it
curl -H "Authorization: Bearer eqsl_live_YOUR_KEY" \
"https://www.eqsl.info/api/v1/analytics/dxcc"
GET
QSOs by band
scope analytics:readCounts contacts per band.
Details you receive: bands[] with key, count, confirmed
Complete URL
https://www.eqsl.info/api/v1/analytics/bandsPattern: https://www.eqsl.info/api/v1/analytics/bands
Where to write the key
HTTP header only: Authorization: Bearer eqsl_live_YOUR_KEY
No path, query, or body parameters. Call the complete URL with the key header.
How to fetch it
curl -H "Authorization: Bearer eqsl_live_YOUR_KEY" \
"https://www.eqsl.info/api/v1/analytics/bands"
GET
QSOs by mode
scope analytics:readCounts contacts per mode.
Details you receive: modes[] with key, count, confirmed
Complete URL
https://www.eqsl.info/api/v1/analytics/modesPattern: https://www.eqsl.info/api/v1/analytics/modes
Where to write the key
HTTP header only: Authorization: Bearer eqsl_live_YOUR_KEY
No path, query, or body parameters. Call the complete URL with the key header.
How to fetch it
curl -H "Authorization: Bearer eqsl_live_YOUR_KEY" \
"https://www.eqsl.info/api/v1/analytics/modes"
GET
QSOs by country
scope analytics:readCounts contacts per country/entity, same grouping as DXCC.
Details you receive: total_countries and countries[] with key, count, confirmed
Complete URL
https://www.eqsl.info/api/v1/analytics/countriesPattern: https://www.eqsl.info/api/v1/analytics/countries
Where to write the key
HTTP header only: Authorization: Bearer eqsl_live_YOUR_KEY
No path, query, or body parameters. Call the complete URL with the key header.
How to fetch it
curl -H "Authorization: Bearer eqsl_live_YOUR_KEY" \
"https://www.eqsl.info/api/v1/analytics/countries"
GET
Activity over time
scope analytics:readCounts QSOs grouped by day, month, or year. Choose the grouping with the interval query parameter.
Details you receive: interval and trends[] with period, count, confirmed
Complete URL
https://www.eqsl.info/api/v1/analytics/trends?interval=monthPattern: https://www.eqsl.info/api/v1/analytics/trends?interval=month
Where to write the key
HTTP header only: Authorization: Bearer eqsl_live_YOUR_KEY
Where to write each parameter
| Name | Write it in | Required | Example | What it controls |
|---|
| interval | Query | No | month | day, month (default), or year. This chooses how dates are grouped. |
How to fetch it
curl -H "Authorization: Bearer eqsl_live_YOUR_KEY" \
"https://www.eqsl.info/api/v1/analytics/trends?interval=month"
Awards
Award rules and your progress toward them.
GET
List award definitions
scope awards:readReturns every award the platform offers (name, category, required count, rules). This is the catalog, not your personal progress.
Details you receive: Array of award definitions.
Complete URL
https://www.eqsl.info/api/v1/awardsPattern: https://www.eqsl.info/api/v1/awards
Where to write the key
HTTP header only: Authorization: Bearer eqsl_live_YOUR_KEY
No path, query, or body parameters. Call the complete URL with the key header.
How to fetch it
curl -H "Authorization: Bearer eqsl_live_YOUR_KEY" \
"https://www.eqsl.info/api/v1/awards"
GET
Your award progress
scope awards:readRecalculates progress, then returns how far you are on each award and whether you are eligible (status COMPLETE).
Details you receive: earned, in_progress, and awards[] with progress, percent, status, eligible
Complete URL
https://www.eqsl.info/api/v1/awards/progressPattern: https://www.eqsl.info/api/v1/awards/progress
Where to write the key
HTTP header only: Authorization: Bearer eqsl_live_YOUR_KEY
No path, query, or body parameters. Call the complete URL with the key header.
How to fetch it
curl -H "Authorization: Bearer eqsl_live_YOUR_KEY" \
"https://www.eqsl.info/api/v1/awards/progress"
POST
Recalculate awards
scope awards:readRecomputes award progress from your log. If an award newly reaches COMPLETE, an award.earned webhook is sent. No JSON body is required.
Details you receive: refreshed: true and newly_earned award ids
Complete URL
https://www.eqsl.info/api/v1/awards/refreshPattern: https://www.eqsl.info/api/v1/awards/refresh
Where to write the key
HTTP header only: Authorization: Bearer eqsl_live_YOUR_KEY
No path, query, or body parameters. Call the complete URL with the key header.
How to fetch it
curl -X POST -H "Authorization: Bearer eqsl_live_YOUR_KEY" \
"https://www.eqsl.info/api/v1/awards/refresh"
Certificates
Issue a certificate for a completed award, or check that a certificate is real.
GET
List your certificates
scope certificates:readReturns certificates already issued to the key owner.
Details you receive: id, serial, verification_code, award_id, award_name, callsign, issued_at, revoked
Complete URL
https://www.eqsl.info/api/v1/certificatesPattern: https://www.eqsl.info/api/v1/certificates
Where to write the key
HTTP header only: Authorization: Bearer eqsl_live_YOUR_KEY
No path, query, or body parameters. Call the complete URL with the key header.
How to fetch it
curl -H "Authorization: Bearer eqsl_live_YOUR_KEY" \
"https://www.eqsl.info/api/v1/certificates"
POST
Issue a certificate
scope certificates:writeCreates a certificate only when that award status is COMPLETE for you. If one already exists and is not revoked, the existing certificate is returned.
Details you receive: serial, verification_code, award_name, callsign, issued_at
Complete URL
https://www.eqsl.info/api/v1/certificatesPattern: https://www.eqsl.info/api/v1/certificates
Where to write the key
HTTP header only: Authorization: Bearer eqsl_live_YOUR_KEY
Where to write each parameter
| Name | Write it in | Required | Example | What it controls |
|---|
| award_id | Body | Yes | 00000000-0000-0000-0000-000000000001 | Award id from GET /awards or /awards/progress. |
How to fetch it
curl -X POST -H "Authorization: Bearer eqsl_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"award_id":"00000000-0000-0000-0000-000000000001"}' \
"https://www.eqsl.info/api/v1/certificates"GET
Verify a certificate
scope publicPublic check. Anyone can call this without an API key. Put the verification code in the URL path.
Details you receive: valid, serial, award_name, callsign, issued_at — or valid false if missing or revoked
Complete URL
https://www.eqsl.info/api/v1/certificates/verify/AbCdEf123456Pattern: https://www.eqsl.info/api/v1/certificates/verify/{code}
Where to write the key
No API key. This method is public. Do not send the Authorization header.
Where to write each parameter
| Name | Write it in | Required | Example | What it controls |
|---|
| code | Path | Yes | AbCdEf123456 | verification_code from the certificate. Write it in the URL. |
How to fetch it
curl "https://www.eqsl.info/api/v1/certificates/verify/AbCdEf123456"
Webhooks
Ask eQSL to POST an event to your website when something happens.
GET
List webhooks
scope webhooks:readReturns webhook URLs registered on this account, including the signing secret.
Details you receive: id, url, secret, events, active, created_at
Complete URL
https://www.eqsl.info/api/v1/webhooksPattern: https://www.eqsl.info/api/v1/webhooks
Where to write the key
HTTP header only: Authorization: Bearer eqsl_live_YOUR_KEY
No path, query, or body parameters. Call the complete URL with the key header.
How to fetch it
curl -H "Authorization: Bearer eqsl_live_YOUR_KEY" \
"https://www.eqsl.info/api/v1/webhooks"
POST
Create a webhook
scope webhooks:writeSubscribes an https URL to one or more events. eQSL generates a secret and signs each delivery with header X-Eqsl-Signature.
Details you receive: The webhook, including secret (store it to verify signatures).
Complete URL
https://www.eqsl.info/api/v1/webhooksPattern: https://www.eqsl.info/api/v1/webhooks
Where to write the key
HTTP header only: Authorization: Bearer eqsl_live_YOUR_KEY
Where to write each parameter
| Name | Write it in | Required | Example | What it controls |
|---|
| url | Body | Yes | https://your-site.com/eqsl-hook | Your server URL that will receive POST requests. |
| events | Body | Yes | ["qso.confirmed"] | One or more of: qsl.received, qso.confirmed, award.earned. |
How to fetch it
curl -X POST -H "Authorization: Bearer eqsl_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://your-site.com/eqsl-hook","events":["qso.confirmed","qsl.received","award.earned"]}' \
"https://www.eqsl.info/api/v1/webhooks"DELETE
Delete a webhook
scope webhooks:writeStops deliveries to that URL. No request body.
Details you receive: data.id and data.deleted = true
Complete URL
https://www.eqsl.info/api/v1/webhooks/00000000-0000-0000-0000-000000000001Pattern: https://www.eqsl.info/api/v1/webhooks/{id}
Where to write the key
HTTP header only: Authorization: Bearer eqsl_live_YOUR_KEY
Where to write each parameter
| Name | Write it in | Required | Example | What it controls |
|---|
| id | Path | Yes | 00000000-0000-0000-0000-000000000001 | Webhook id from the list. |
How to fetch it
curl -X DELETE -H "Authorization: Bearer eqsl_live_YOUR_KEY" \
"https://www.eqsl.info/api/v1/webhooks/00000000-0000-0000-0000-000000000001"
POST
Send a test event
scope webhooks:writePosts a sample qso.confirmed payload to your webhook URL so you can confirm your server receives it. No JSON body.
Details you receive: delivered, status_code, error
Complete URL
https://www.eqsl.info/api/v1/webhooks/00000000-0000-0000-0000-000000000001/testPattern: https://www.eqsl.info/api/v1/webhooks/{id}/test
Where to write the key
HTTP header only: Authorization: Bearer eqsl_live_YOUR_KEY
Where to write each parameter
| Name | Write it in | Required | Example | What it controls |
|---|
| id | Path | Yes | 00000000-0000-0000-0000-000000000001 | Webhook to test. |
How to fetch it
curl -X POST -H "Authorization: Bearer eqsl_live_YOUR_KEY" \
"https://www.eqsl.info/api/v1/webhooks/00000000-0000-0000-0000-000000000001/test"
Call the API from another website
Put the key on your server. Your public webpage should call your own backend, and that backend calls eQSL.
// Your server (Node). Key stays in the environment, not in the browser.
const r = await fetch("https://www.eqsl.info/api/v1/qsos?per_page=10&band=20m", {
headers: { Authorization: "Bearer " + process.env.EQSL_API_KEY }
});
const { data, error, meta } = await r.json();# Python
import os, requests
r = requests.get(
"https://www.eqsl.info/api/v1/analytics/summary",
headers={"Authorization": "Bearer " + os.environ["EQSL_API_KEY"]},
)
print(r.json()["data"])eQSL.info Public API · https://www.eqsl.info/api/v1 · 31 methods