Request / Response Format
Horizon’s REST-like API uses HTTP methods and status codes to communicate with clients. Responses are JSON in the HAL format. See Horizon’s Response Format. RPC’s JSON-RPC API uses JSON-RPC 2.0 to communicate with clients. Requests to the API are JSON objects that contain one or more method invocations. Responses are also JSON objects that contain a result for each invocation in the request. See JSON-RPC. Both formats utilise JSON for the overall structure which are relatively simple and do not require any special client code, although there are client SDKs available. Some values contained within are XDR encoded and can be decoded using Stellar SDKs. The two APIs also return different response shapes. See Response Differences after the endpoint mapping.Endpoint Mapping
Applications that use the following Horizon endpoints can typically migrate directly to the RPC using the referenced methods. Endpoints without mappings do not have a direct replacement in the RPC API. To build similar functionality in an application, please consider partnering with an indexer or using the information listed below to build your own indexed representation of horizon endpoints. Consider using other Data products for analytics use cases.Response Differences
The endpoint mapping above pairs each Horizon endpoint with an RPC method, but the two responses do not have the same shape. Horizon curates the ledger for you. RPC hands you the ledger entry as the protocol stores it. This section compares one pair,GET /accounts/{address} and getLedgerEntries, because most migrations hit it first. The rows about missing keys, the 200-key limit, and paging describe getLedgerEntries only. getTransactions, getLedgers, and getEvents page with a cursor and a limit. Plan for these differences before you swap one call for the other.
The RPC column describes the decoded ledger entry. A default response holds those fields inside the base64 XDR, so you see them only after you decode it, or after you ask for the JSON view with
xdrFormat.
Example: Account Balances
Horizon’sGET /accounts/{address} response is an aggregation. It joins the account entry with the account’s trustline entries. The AccountEntry structure holds no trustlines of its own. It holds only a count of the account’s sub-entries. So, for balances, one Horizon call becomes a getLedgerEntries call with an account key plus one trustline key per non-native balance, including liquidity pool shares, and you must already know each asset. The XLM balance is in the account entry itself, so it needs no trustline key. Horizon’s data map comes from separate data entries, so each account data key you need is one more key in the request. A call takes at most 200 keys, so an account with many trustlines or data entries needs more than one call.
The example below uses a Testnet account. A Testnet data reset clears it, so use your own account and asset to follow along. This Horizon request returns both balances at once:
keyJson field. This is the result object of that response, trimmed the same way:
- Horizon’s
nativebalance of9009.2998203is the account entry’sbalanceof90092998203stroops. - Horizon’s USDC balance of
1252.7872975is the trustline entry’sbalanceof12527872975stroops. It is a separate entry, so it needs a separate key. - Horizon’s
limitof922337203685.4775807is the trustline entry’slimitof9223372036854775807, the largest value a 64-bit amount can hold. - The entry’s four-byte
thresholdsstring is[weight of master|low|medium|high], so"01000000"means a master key weight of1and no other threshold set. Horizon’sthresholdsobject exposes only the last three bytes, aslow_threshold,med_threshold, andhigh_threshold. - The first byte, the master weight, appears in Horizon as the
weightof the master key in thesignersarray. The raw account entry’ssignerslist never includes the master key. - Horizon’s
flagsbooleans expand the entry’sflagsbitmask. The trustline’sflagsvalue of1isAUTHORIZED_FLAG, which Horizon reports asis_authorized.
Pass
"xdrFormat": "json" to read an entry without an SDK, as the responses above do. Do not build an application on that JSON. The getLedgerEntries specification warns that its shape changes whenever the underlying XDR changes. Decode the default base64 XDR with one of the SDKs instead.Amounts Are Raw Integers
Every classic amount on the ledger is a signed 64-bit integer of stroops. Horizon divides it by ten million and returns a string with seven decimal places. RPC returns the stroop count itself. It is a JSON string, not a JSON number, because a 64-bit integer does not fit a JSON number safely. Divide it in your own code, and use a big-number type so you do not lose precision. See Amount precision.A Missing Entry Is Not an Error
Horizon answers404 when a resource does not exist. RPC answers 200 and leaves the key out of entries, so a request for two keys can return one entry. If no key exists, entries is an empty array. The current server always sends the field, but the getLedgerEntries specification lists only latestLedger as required, so treat a missing entries as empty.
Match each returned entry back to its own key with the entry’s keyJson field, or key in the default base64 format. Do not match on the position you sent it in.