Vulcan/ Docs/ API

API

The Vulcan API lets your own website, bot or scripts read the same member data the Member Dashboard shows: who is in your server, whether they verified, the wallets they linked, and the roles they hold. Use it to gate a holder portal, build an allowlist, or sync members into your own tools.

The API is read-only and part of the Pro and Enterprise plans. Each key reads one server.

Create a key

  1. Open API under Support in the dashboard sidebar.
  2. Name the key after what will use it, for example Holder portal, and choose Create key.
  3. Copy the key straight away. Vulcan keeps only a fingerprint of it, so it cannot be shown again. If you lose it, revoke it and create another.

Only the server owner and people with Administrator or Manage Roles on Discord can create or revoke keys. Team members can see the list.

A server can have up to 5 keys at once, so you can give each integration its own and rotate one without downtime: create the new key, switch your code over, then revoke the old one.

Treat a key like a password. Anyone holding it can read every member's linked wallets. Keep it on a server you control. Never put it in a website's front-end code, a public repository or a Discord message.

If the server drops below Pro, its keys stop working until it is back on Pro. They are not deleted.

Making requests

Every request is a GET to https://api.vulcan.xyz/v1/ with the key as a bearer token:

curl https://api.vulcan.xyz/v1/server/ \
  -H "Authorization: Bearer YOUR_KEY"

Responses are JSON. Discord IDs are longer than JavaScript can hold exactly as numbers, so every ID is a string. Times are ISO 8601 in UTC.

Endpoints

GET /server/

The server the key belongs to. The quickest way to check a key works.

{
  "id": "923315187519737866",
  "name": "Example Club",
  "plan": "pro",
  "members_synced_at": "2026-10-13T04:12:09+00:00"
}

members_synced_at is when Vulcan last pulled your member list and roles from Discord. It is null before the first pull and while a pull is running.

GET /members/

Members of your server, a page at a time, in Discord ID order.

Parameter
verified true for members who linked a wallet to this server, false for those who have not. Leave it out for everyone.
role A Discord role ID: only members holding that role.
limit Members per page, 1 to 500. Default 100.
cursor The next_cursor from the previous page.
{
  "members": [
    {
      "discord_id": "112233445566778899",
      "name": "Ada",
      "username": "ada.eth",
      "in_server": true,
      "verified": true,
      "roles": [{"id": "998877665544332211", "name": "Holder"}],
      "wallets": ["0x1234…abcd"],
      "joined_server_at": "2025-03-02T18:40:11+00:00",
      "first_vulcan_role_at": "2025-03-02T18:44:52+00:00"
    }
  ],
  "next_cursor": "112233445566778899"
}

Keep requesting with cursor set to next_cursor until it is null.

  • in_server is false for a verified member who has left your server, once Vulcan's next pull of your member list from Discord notices. With verified=true they are still listed; otherwise only current members are.
  • roles is null if Discord has not yet told Vulcan this member's roles.
  • wallets lists only the wallets the member linked to your server, not wallets they linked elsewhere.
  • first_vulcan_role_at is when Vulcan first gave them a role in your server.

GET /members/{discord_id}/

One member, in the same shape, under "member". 404 if they are neither in your server nor verified in it.

GET /wallets/{address}/

Who in your server linked this wallet:

{"wallet": "0x1234…abcd", "member": {"discord_id": "112233445566778899", …}}

404 if no member linked that wallet to your server, even if it is linked to another server.

GET /roles/

Every role in your server, highest first, with how many members hold it:

{
  "roles": [
    {
      "id": "998877665544332211",
      "name": "Holder",
      "position": 12,
      "members": 1840,
      "verified_members": 1802,
      "granted_by_vulcan": true
    }
  ]
}

granted_by_vulcan is true when one of your verification rules grants the role. The counts are the ones on your dashboard's member overview and can be up to an hour old.

How fresh the data is

The API reads what Vulcan already knows. It never checks a wallet's holdings or asks Discord while you wait. Vulcan updates roles within minutes of a transfer and re-checks on your plan's schedule. Member lists and role counts come from Discord pulls and the bot's live events.

Limits

Each server can make up to 60 requests a minute and 10,000 a day, shared across all its keys. Every request made with a valid key on a Pro server gets X-RateLimit-Limit and X-RateLimit-Remaining headers. Over the limit you get 429 with a Retry-After header in seconds.

Errors

Errors return a status code and a body like:

{"error": {"code": "invalid_key", "message": "…"}}
Status code Meaning
400 invalid_parameter A query parameter is not valid.
401 invalid_key The key is missing, mistyped or revoked.
403 plan_required The server is not on Pro or Enterprise.
404 not_found No such member or wallet in this server.
429 rate_limited Over the limit. Wait Retry-After seconds.