skip to content

API responses often carry links tagged with relation names such as self, next, and edit. What does a link relation name mean, and why prefer registered names like those over inventing your own?

level: juniorimportance: should knowfreq 36%

answer

  1. rel = the stable part, URL = opaque
  2. self, next/prev/first/last, edit, collection/item, up, describedby
  3. IANA link relations registry, RFC 8288
  4. custom rels must be URIs you own
  5. unknown rels must be ignored, never repurposed

basics

~20 s

A link relation is a short label saying how the target URL relates to the current resource: self is this resource's own URL, next the following page, edit the URL you write to. Registered IANA names give clients a shared vocabulary so generic code can follow links without endpoint-specific rules.

solid answer

~50 s

A link has two parts that matter: the URL, which is opaque and may change, and the relation name, which is the stable semantic contract. The client codes against the rel and never against the URL string. IANA maintains a registry of relation names, so common intents already have agreed labels: self, next, prev, first, last for paging; edit for the URL you send updates to; collection and item for containment; up, related, alternate, describedby. Using them means a generic pager or crawler already understands your response, and two teams do not ship nextPage and next_link for the same idea. When nothing registered fits, extension relations are allowed but must be URIs you own, such as https://api.example.com/rels/approve, ideally resolving to documentation. Clients must ignore relations they do not recognise, which is what makes adding new ones a non-breaking change.

code

json · 10 lines
json
{
  "items": [ { "id": "a1" }, { "id": "a2" } ],
  "_links": {
    "self":  { "href": "/orders?page=2" },
    "first": { "href": "/orders?page=1" },
    "prev":  { "href": "/orders?page=1" },
    "next":  { "href": "/orders?page=3" },
    "https://api.example.com/rels/export": { "href": "/orders/export" }
  }
}

go deeper

for a junior

Define rel as the label describing the link's meaning, name self/next/prev/edit, and say clients look up by rel instead of building URLs.

for a middle

Add the IANA registry and RFC 8288, the URI requirement for extension relations, and the ignore-unknown-rels rule.

for a senior

Discuss rel vocabulary as a versioned public contract - additive only, never repurposed - and how relation-driven clients decouple from URL structure.

for a principal

Own the vocabulary across services: a shared registry of custom rels, documentation at each rel URI, and review rules preventing per-team synonyms for the same relationship.

## Relation names are the contract A hypermedia link is a typed pointer. The type is the relation name - conventionally rel - and it answers the question: what is at the other end of this link, relative to the thing I am looking at? The URL itself is deliberately opaque; the whole point of naming relations is that the server may move, restructure, or shard its URLs while clients keep working, because they look up links by rel rather than assembling paths from templates baked into their code. ## The registered vocabulary IANA hosts the link relations registry (the mechanism is defined in RFC 8288, Web Linking). Names you will use constantly: - **self** - the canonical URL of the resource you are looking at. Nearly every hypermedia response includes it, and clients use it to refetch or to key a cache. - **next / prev / first / last** - traversal of an ordered series, which is how pagination is expressed. The presence or absence of next is what tells a client whether more pages exist, without the client computing offsets. - **edit** - the URL to which an editing request is sent. Note it is about where you write, not what method you use. - **collection / item** - the collection containing this resource, and the members of a collection. - **up**, **related**, **alternate** (another representation of the same thing), **describedby** (a description or schema), **search**. The registry has extension procedures, so genuinely general-purpose relations can be registered rather than invented. ## Why not just make names up Three reasons. First, interoperability: a generic client, a documentation renderer, or a test harness that knows next can page any compliant API. Second, collision: rel names live in a shared namespace, and two APIs both meaning something different by owner is a real problem when documents get merged or embedded. Third, discipline: choosing from a registry forces you to describe the relationship instead of the implementation detail. ## Extension relations, when you need them Domain verbs have no registered name - approve-invoice, cancel-order. RFC 8288 says extension relation names must be URIs, which both namespaces them to a domain you control and gives you somewhere to publish their meaning. A rel of https://api.example.com/rels/approve is unambiguous globally, and pointing a browser at it should ideally land on the docs for that affordance. Some media types provide a shorthand mechanism so documents do not repeat long URIs, but the underlying identity is still the URI. Evolution rules follow from this: never repurpose an existing rel to mean something new, add a new rel instead; clients must silently ignore unknown rels; and removing a rel that clients follow is a breaking change even though no URL changed. ## The client's side of the deal A client that hardcodes /orders/{id}/items has taken on the server's URL structure as a dependency. A client that reads the link named items has taken on only the rel vocabulary. That is the trade the relation name exists to enable - and it only pays off if clients actually do the lookup.

  • How do you name a relation for something with no registered equivalent, such as submit-for-approval?
    Use an extension relation expressed as a URI in a namespace you control, for example https://api.example.com/rels/submit-for-approval, and publish documentation at that address. That guarantees no collision with anyone else's vocabulary and gives client developers a place to read what the affordance means. If the concept turns out to be broadly useful, it can be proposed to the IANA registry.
  • What happens when a client meets a relation name it does not know?
    It must ignore it. That rule is what makes adding new relations a backwards-compatible change and lets a server expose new affordances to new clients without coordinating a release. Conversely, removing or changing the meaning of an existing relation breaks clients even though the URLs never moved.

saying these in an interview costs you the question

  • Treating the href as the contract and the rel as decoration
  • Inventing bare-word custom relations like approve that collide across APIs
  • Assuming edit implies a specific HTTP method rather than a target URL
  • Thinking clients may fail when they encounter an unrecognised relation

context