Kupo
The Kupo chain-index HTTP API for Cardano, hosted by Demeter.
What it is for
Looking up unspent outputs by address, payment or stake credential, policy id
or asset, with their datums and scripts. Lucid Evolution's Kupmios provider
pairs a Kupo port with an Ogmios port: Kupo answers the UTxO
queries and Ogmios submits transactions and reads the ledger. Any HTTP client
can call it directly.
Demeter's Kupo serves unspent outputs only. A /matches request with
spent, spent_after or spent_before returns 400. For the API itself, see
the API reference.
Hosts
The pattern, where {network} is cardano-mainnet, cardano-preprod or
cardano-preview:
https://{network}-v2.kupo-m1.dmtr.host
On preprod:
https://cardano-preprod-v2.kupo-m1.dmtr.host
The authenticated form puts the key in the host:
https://{key}.{network}-v2.kupo-m1.dmtr.host
Authentication
Send the key in the dmtr-api-key header:
dmtr-api-key: <your key>
Or use the authenticated host, with no header, for clients that cannot set one.
Networks
cardano-mainnet, cardano-preprod and cardano-preview. Each port serves
one network, chosen when you create it.
Limits
| Tier | Minimum fee | Per 100k requests | Max requests / second | Daily requests |
|---|---|---|---|---|
| Free | $0 | $0 | 5 | ~430,000 |
| Flexible | $0 | $0.30 | 20 | ~1,700,000 |
| Pro I | $50 | $0.26 | 100 | ~8,600,000 |
| Pro II | $150 | $0.23 | 300 | ~26,000,000 |
Usage is counted per 100,000 requests, and throughput is capped by requests per second. Minimum fees apply only to the tiers that reserve throughput.
Getting a key
Create a Kupo port at https://console.demeter.run. The port's page shows
its endpoint, its authenticated endpoint and its API key.
Example
Set the key and an address in your shell:
export DEMETER_API_KEY=... # the API key from the port's page
export ADDRESS=addr_test1... # any preprod address
With curl, the unspent outputs at that address on preprod:
curl -H "dmtr-api-key: $DEMETER_API_KEY" \
"https://cardano-preprod-v2.kupo-m1.dmtr.host/matches/$ADDRESS?unspent"
Kupmios with Lucid Evolution
Kupmios takes the Kupo and Ogmios URLs and a header for each. The two
ports have separate keys, so this reads two variables (checked against
@lucid-evolution/lucid 0.8.2):
import { Kupmios, Lucid } from "@lucid-evolution/lucid";
const provider = new Kupmios(
"https://cardano-preprod-v2.kupo-m1.dmtr.host",
"https://cardano-preprod-v6.ogmios-m1.dmtr.host",
{
kupoHeader: { "dmtr-api-key": process.env.DEMETER_KUPO_API_KEY! },
ogmiosHeader: { "dmtr-api-key": process.env.DEMETER_OGMIOS_API_KEY! },
},
);
console.log(await provider.getUtxos(process.env.ADDRESS!));
const lucid = await Lucid(provider, "Preprod");