Get IDL
Get the IDL that was in effect for a Solana program at any slot, from the catalog Parsed Events uses to decode instructions.
curl --request GET \
--url 'https://mainnet.helius-rpc.com/v1/parsed-events/idl/{programId}/{slot}?api-key='import requests
url = "https://mainnet.helius-rpc.com/v1/parsed-events/idl/{programId}/{slot}?api-key="
response = requests.get(url)
print(response.text)const options = {method: 'GET'};
fetch('https://mainnet.helius-rpc.com/v1/parsed-events/idl/{programId}/{slot}?api-key=', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://mainnet.helius-rpc.com/v1/parsed-events/idl/{programId}/{slot}?api-key=",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://mainnet.helius-rpc.com/v1/parsed-events/idl/{programId}/{slot}?api-key="
req, _ := http.NewRequest("GET", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://mainnet.helius-rpc.com/v1/parsed-events/idl/{programId}/{slot}?api-key=")
.asString();require 'uri'
require 'net/http'
url = URI("https://mainnet.helius-rpc.com/v1/parsed-events/idl/{programId}/{slot}?api-key=")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
response = http.request(request)
puts response.read_bodyslot. slot doesn’t need to match a version exactly, so you can pass any point in history. To fetch one specific version, pass its slot from List IDL Versions.
The IDL comes from the same catalog that Parsed Events and Parsed Streams use to decode instructions. The Orb explorer uses these endpoints to show program IDLs.
Use Cases
- Decode history with the right interface. Pass a transaction’s slot to get the IDL that was live when it executed. Programs change their instructions and accounts over time, so the current IDL can misread older transactions.
- Find exact names for filters. Scan Transaction History
match.programs[].instructionsaccepts instruction names as the IDL spells them. - Review interface changes. Fetch two versions and compare their
instructionsto see what an upgrade added or removed. See the example on List IDL Versions.
IDL Formats
The response is the IDL document as stored. Programs in the catalog use one of two Anchor formats, and one program’s versions can use both. Check which format you received before reading it:| Legacy Anchor (before 0.30) | Anchor 0.30+ | |
|---|---|---|
| Program name and version | Top-level name and version | metadata.name and metadata.version |
| Program address | No top-level address | Top-level address |
| Instruction discriminator | Not included | instructions[].discriminator |
| Instruction account flags | isMut, isSigner | writable, signer |
instructions. Most IDLs also have accounts, types, and errors, and many have events.
Credits
Each request costs 10 credits and is available on all plans. See Credits.Errors
| Status | When |
|---|---|
400 | programId isn’t a valid base58 address, or slot isn’t an unsigned 64-bit integer. |
401 | The API key is missing or invalid. The body is plain text: Unauthorized. |
404 | The catalog has no IDL for the program, or no version was active at or before slot. |
error message, such as {"error": "no IDL found for program KLend2g3cP87fffoy8q1mQqGKjrxjC8boSyAYavgmjD at or before slot 1"}.
Request Parameters
slot from List IDL Versions to get that exact version, or a transaction’s slot to get the IDL in effect when it executed.Authorizations
Path Parameters
Program address, base58-encoded.
"KLend2g3cP87fffoy8q1mQqGKjrxjC8boSyAYavgmjD"
Slot to look up. It doesn't need to match a version's activation slot. Pass a slot from List IDL Versions to get that exact version, or a transaction's slot to get the IDL in effect when it executed.
x >= 0205509752
Response
The IDL document as stored. Both the legacy Anchor format and the Anchor 0.30+ format occur, so check which one you received before reading it.
An IDL document, returned as stored. Two formats occur:
- Legacy Anchor (before 0.30): top-level
nameandversion. Instruction accounts useisMutandisSigner. - Anchor 0.30+: top-level
addressandmetadata(name,version,spec,description). Instructions carry adiscriminator, and instruction accounts usewritableandsigner.
Both formats have instructions. Most IDLs also have accounts, types, and errors, and many have events. One program's versions can use different formats.
Was this page helpful?
curl --request GET \
--url 'https://mainnet.helius-rpc.com/v1/parsed-events/idl/{programId}/{slot}?api-key='import requests
url = "https://mainnet.helius-rpc.com/v1/parsed-events/idl/{programId}/{slot}?api-key="
response = requests.get(url)
print(response.text)const options = {method: 'GET'};
fetch('https://mainnet.helius-rpc.com/v1/parsed-events/idl/{programId}/{slot}?api-key=', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://mainnet.helius-rpc.com/v1/parsed-events/idl/{programId}/{slot}?api-key=",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://mainnet.helius-rpc.com/v1/parsed-events/idl/{programId}/{slot}?api-key="
req, _ := http.NewRequest("GET", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://mainnet.helius-rpc.com/v1/parsed-events/idl/{programId}/{slot}?api-key=")
.asString();require 'uri'
require 'net/http'
url = URI("https://mainnet.helius-rpc.com/v1/parsed-events/idl/{programId}/{slot}?api-key=")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
response = http.request(request)
puts response.read_body