Skip to content

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:

FieldPurpose
relA relation type that tells you what the target resource means in the context of the current state
hrefThe 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 RESTHATEOAS (this API)
Client constructs URLs from documentationClient discovers URLs from responses
URL patterns are part of the contractOnly link relations are stable
Changing a URL breaks clientsServer can change URLs freely
Client must hardcode the state machineClient 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

Flywire Agents API Documentation