Hosted Issuer API
The API an institution calls to have Tamga's hosted issuer offer, sell or revoke credentials.
- Real network
https://issuer.tamga.network/{slug}/api/v1- Sandbox (test network)
https://issuer.sandbox.tamga.network/{slug}/api/v1- Authentication
- Bearer
- Definition
- OpenAPI 3.1 file · Guide
Run by the Tamga Network operator (ADR-0016, ADR-0020). The dependency-free Node client is @tamga-network/issuer/client.
Offers. Two kinds:
- Identity-bound (recommended; ADR-0020): send
bind. No PIN. The person opens the link in the wallet and presents their Tamga identity attestation; the credential is issued only if the presented national identification number and date of birth match. Only a keyed hash of these keys is stored. Valid 7 days, single use. You send the link to the person through your own channel (email, student portal); Tamga never receives contact details. - Pre-authorized with PIN (fallback for people without an identity attestation): the response carries
tx_code. Never send the PIN through the same channel as the link.
Credential data is not sent with the offer: the hosted issuer reads it from your source endpoint at issuance time (see the institution source endpoint).
Errors use RFC 9457 problem details (title, status). Each key has a per-minute limit (429 with Retry-After).
Endpoints
| Endpoint | Description |
|---|---|
POST /offers | Offer a credential |
GET /tickets | List sold tickets |
POST /tickets | Sell a ticket |
POST /revocations | Revoke, suspend or reinstate a credential |
Authentication
Bearer
Authorization: Bearer tmg_<slug>_… — a scoped API key issued per institution in the Institution Console, valid 90 days, rotated by issuing a new key. Keep it on your server only.
Offers
Offer a credential to a person in your records.
Offer a credential
/offersScope offers:write. The person must exist in your source endpoint.
Authentication Bearer
Request body
application/json
| Field | Type | Description |
|---|---|---|
subject_id required | string | Your opaque subject reference (SubjectRecord.id in your source endpoint). |
vct required | string | Credential type; must be authorised for your institution in the trust list. |
klass | string | PIN delivery for pre-authorized offers; ignored when bind is present. One of: on-screen · out-of-band |
bind | object | Makes the offer identity-bound (ADR-0020). Only a keyed hash is stored. |
bind.personal_administrative_number required | string | |
bind.birth_date required | string (date) |
Responses
| Status | Description |
|---|---|
| 200 | Offer created. |
| 400 | RFC 9457 problem details. Returns Problem |
| 401 | Missing, expired or wrong-scope API key. Returns Problem |
| 404 | The subject is not in your source. |
| 429 | Per-key limit exceeded. Wait Retry-After seconds. Returns Problem Headers: Retry-After |
| 503 | Your source endpoint was not reachable. |
Example
curl -X POST "https://issuer.tamga.network/your-institution/api/v1/offers" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"subject_id":"stu_8c41f2","vct":"urn:tamga:edu:DiplomaCredential:1","bind":{"personal_administrative_number":"10000000146","birth_date":"2001-04-17"}}'{
"offer_id": "off_3kQ9xV",
"expires_at": 1791504000,
"offer_uri": "https://issuer.tamga.network/your-institution/offers/off_3kQ9xV",
"deep_link": "openid-credential-offer://?credential_offer_uri=https%3A%2F%2Fissuer.tamga.network%2Fyour-institution%2Foffers%2Foff_3kQ9xV",
"offer": {
"credential_issuer": "https://issuer.tamga.network/your-institution",
"credential_configuration_ids": [
"urn:tamga:edu:DiplomaCredential:1"
],
"grants": {
"authorization_code": {
"issuer_state": "off_3kQ9xV"
}
}
},
"identity_bound": true
}Tickets
Sell event tickets as credentials.
List sold tickets
/ticketsScope tickets:read.
Authentication Bearer
Responses
| Status | Description |
|---|---|
| 200 | Tickets. |
| 401 | Missing, expired or wrong-scope API key. Returns Problem |
| 429 | Per-key limit exceeded. Wait Retry-After seconds. Returns Problem Headers: Retry-After |
Example
curl "https://issuer.tamga.network/your-institution/api/v1/tickets" \
-H "Authorization: Bearer $API_KEY"{
"tickets": [
{}
]
}Sell a ticket
/ticketsScope tickets:write. Records the sale and offers the ticket credential; the offer carries no personal data.
Authentication Bearer
Request body
application/json
| Field | Type | Description |
|---|---|---|
event_id required | string | |
ticket_class required | string | |
seat | string | |
klass | string | One of: on-screen · out-of-band |
Responses
| Status | Description |
|---|---|
| 200 | Ticket sold. |
| 400 | RFC 9457 problem details. Returns Problem |
| 401 | Missing, expired or wrong-scope API key. Returns Problem |
| 404 | RFC 9457 problem details. Returns Problem |
| 429 | Per-key limit exceeded. Wait Retry-After seconds. Returns Problem Headers: Retry-After |
Example
curl -X POST "https://issuer.tamga.network/your-institution/api/v1/tickets" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"event_id":"evt_2026_konser","ticket_class":"standard","seat":"B-14"}'{
"ticket_id": "…",
"ticket_no": "…",
"event": {
"id": "…",
"name": "…",
"start": "…",
"venue": "…"
},
"offer": {
"offer_id": "…",
"tx_code": "…",
"expires_at": 0,
"offer_uri": "…",
"deep_link": "…"
}
}Revocations
Change the status of an issued credential.
Revoke, suspend or reinstate a credential
/revocationsScope revocations:write. Takes effect at the next fixed-interval status list publication. A revoked credential stays revoked; only a suspended one can be reinstated.
Authentication Bearer
Request body
application/json
| Field | Type | Description |
|---|---|---|
credential_id required | string | |
action | string | One of: revoke · suspend · reinstate (default revoke) |
reason | string | Kept in your audit log; never published. |
Responses
| Status | Description |
|---|---|
| 200 | Accepted. |
| 400 | RFC 9457 problem details. Returns Problem |
| 401 | Missing, expired or wrong-scope API key. Returns Problem |
| 404 | RFC 9457 problem details. Returns Problem |
| 429 | Per-key limit exceeded. Wait Retry-After seconds. Returns Problem Headers: Retry-After |
Example
curl -X POST "https://issuer.tamga.network/your-institution/api/v1/revocations" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"credential_id":"crd_5Hn2Lw","action":"suspend","reason":"disciplinary review"}'{
"ok": true,
"effective_after_next_publish": true,
"interval_sec": 3600
}Objects
Problem
| Field | Type | Description |
|---|---|---|
type | string | |
title | string | |
status | integer |
Import the machine-readable definition into any OpenAPI tool to generate a client or send test requests: tamga-issuer-api.openapi.yaml.