Developer API

Issue verifiable credentials from your code

The SwanShare REST API lets you issue tamper-evident, publicly verifiable credentials programmatically — from your LMS, backend, or a tool like Zapier. Every credential is cryptographically signed and instantly verifiable by anyone, with no account.

Base URL

https://www.swanshare.site/api

Authentication

Authenticate with an API key as a Bearer token. Create and manage keys in your dashboard under Settings → API keys. The full key (swan_sk_…) is shown once at creation — store it securely.

Authorization: Bearer swan_sk_your_key_here

Treat keys like passwords. They grant full issuing access for your organization.

Issue credentials

POST/v1/credentials

Issue one credential, or many in a batch by sending an items array. Each credential needs at least recipient_name and title.

Single

curl -X POST https://www.swanshare.site/api/v1/credentials \
  -H "Authorization: Bearer swan_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "recipient_name": "Asha Rao",
    "recipient_email": "[email protected]",
    "title": "Advanced Data Analytics",
    "expires_at": "2027-12-31",
    "fields": { "Score": "A+", "Hours": "120" }
  }'

Batch (a whole cohort)

{
  "items": [
    { "recipient_name": "Asha Rao",  "title": "Advanced Data Analytics" },
    { "recipient_name": "Vikram Singh", "title": "Advanced Data Analytics" }
  ]
}

Response — 201 Created

{
  "ok": true,
  "count": 2,
  "credentials": [
    { "verify_id": "a1b2c3…", "verify_url": "https://www.swanshare.site/verify?id=a1b2c3…" },
    { "verify_id": "d4e5f6…", "verify_url": "https://www.swanshare.site/verify?id=d4e5f6…" }
  ]
}

Fetch a credential

GET/v1/credentials/{verify_id}

Re-run the full verification (signature, hash, ledger inclusion, revocation/expiry) for a credential and get the canonical result.

curl https://www.swanshare.site/api/v1/credentials/a1b2c3… \
  -H "Authorization: Bearer swan_sk_your_key_here"
{
  "valid": true,
  "status": "valid",
  "checks": [ { "name": "Signature", "passed": true, "detail": "…" } ],
  "credential": { "title": "Advanced Data Analytics", "recipient_name": "Asha Rao", "issued_at": "…" },
  "issuer": { "name": "Acme Training Co.", "verified": true }
}

Errors & limits

Errors return a JSON body with an error message and an appropriate status code.

  • 401Missing or invalid API key.
  • 402Monthly plan limit reached (response includes "limit": true). Upgrade to issue more.
  • 400Each credential needs recipient_name and title.

Rate limit: 120 requests / minute per API key.

Webhooks

Register endpoints in Settings → API keys to be notified of events. SwanShare sends a POST with a JSON body and these headers:

X-SwanShare-Event: credential.issued
X-SwanShare-Signature: sha256=<hmac>

Events

  • credential.issued — one or more credentials were issued
  • document.signed — all recipients signed a document

Payload

{
  "event": "credential.issued",
  "data": {
    "count": 1,
    "credentials": [
      { "verify_id": "a1b2c3…", "verify_url": "https://www.swanshare.site/verify?id=a1b2c3…" }
    ]
  }
}

Verify the signature

Each request is signed with HMAC-SHA256 over the raw body using your endpoint's signing secret. Recompute it and compare:

import hmac, hashlib

def is_valid(raw_body: bytes, header_sig: str, secret: str) -> bool:
    expected = "sha256=" + hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, header_sig)