Appearance
HATEOAS — Navigating the API
The Agents API is, in essence, a hypermedia API on top of HTTP, with all that this entails: API responses contain the data being requested, but they also expose the actions that can be currently performed on the underlying business state, in the form of Link Relation Types and profiles applied to the generated representations.
In practice, this means you start at the root and follow links to reach the next state. The server tells you what's available; your client picks the desired transition and follows it.
Content type
The Content-Type of every response is application/json, informally extended with JSON Pointer (Section 6 of RFC 6901) values inside links[].anchor (see Anchoring).
Designed for end-user UIs
Not all relation types are designed for server-to-server communication. Some link relations — for example the payment IANA relation, or the monitor link on payments — point to user-facing pages and are intended to be opened by the end user, not fetched programmatically. The relation descriptions in Link Relations note when this is the case.
The Root Resource
The only URL you ever hardcode is the root:
GET https://api-platform.demo.flywire.com/agents/v2/Everything else is discovered from the response:
json
{
"links": [
{ "rel": "self", "href": "https://api-platform.demo.flywire.com/agents/v2/" },
{ "rel": "tag:flywire.com,2016:agents:api:relation:intermediated-payments", "href": "https://..." },
{ "rel": "tag:flywire.com,2016:agents:api:relation:claim-intermediation-of-payment", "href": "https://..." },
{ "rel": "tag:flywire.com,2016:agents:api:relation:payment-recipients", "href": "https://..." },
{ "rel": "tag:flywire.com,2016:agents:api:relation:insurance-types", "href": "https://..." },
{ "rel": "tag:flywire.com,2016:agents:api:relation:intermediated-insurance-applications", "href": "https://..." }
]
}Each entry in links has at least two fields:
| Field | Purpose |
|---|---|
rel | A relation type that tells you what the target resource means in the context of the current state |
href | The URL to follow — opaque to your client, never parse or construct it |
States and Transitions
Think of the API as a state machine. Each response is a state, and the links in it are the available transitions, whose meaning is defined by the relation.
Your client never needs to know the full graph ahead of time. At each step, just inspect the links array to see what's possible.
The Golden Rule: Never Hardcode URLs
WARNING
URLs are opaque. They may contain signed tokens, cursor parameters, or internal identifiers that change between requests. Treat them as values you receive and follow — nothing more.
The only URL your client should store is the API root. Everything else comes from link discovery:
python
root = requests.get(BASE_URL, headers=auth).json()
payments_link = next(
link for link in root["links"]
if link["rel"].endswith("intermediated-payments")
)
payments = requests.get(payments_link["href"], headers=auth).json()How This Differs from Traditional REST
| Traditional REST | HATEOAS (this API) |
|---|---|
| Client constructs URLs from documentation | Client discovers URLs from responses |
| URL patterns are part of the contract | Only link relations are stable |
| Changing a URL breaks clients | Server can change URLs freely |
| Client must hardcode the state machine | Client discovers possible transitions |
TIP
If you find yourself string-concatenating a URL, you're doing it wrong. Look for a link with the right rel instead.
What Each Response Tells You
Besides the HTTP status code and the Content-Type header, the shape of the body and what you can expect to find in it are defined by profiles (exposed through Link headers, e.g. Link: <tag:flywire.com,2016:agents:api:profile:root>, rel="**profile**"). For example, if you encounter the hypermedia profile, you can expect the response to contain a links array. Encountering item tells you the body is one element in a collection whose contents you can browse through the exposed links, while form helps you collect and submit information from the end user.
The combination of these elements means your client can be fully generic — driven by the API responses rather than hardcoded logic.
Next Steps
- Profiles — understand what shape a response has
- Link Relations — the action vocabulary
- Forms — how to collect and submit data
- Reference — the full catalogue of relations, profiles, and schemas