TMF630 REST API Design Guidelines Part 3 v4.0.0
TMF630 REST API Design Guidelines Part 3 v4.0.0
TMF630
Team Approved Date: Nov. 25th, 2020
This document and translations of it may be copied and furnished to others, and derivative works that
comment on or otherwise explain it or assist in its implementation may be prepared, copied, published, and
distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and
this section are included on all such copies and derivative works. However, this document itself may not be
modified in any way, including by removing the copyright notice or references to TM FORUM, except as needed
for the purpose of developing any document or deliverable produced by a TM FORUM Collaboration Project
Team (in which case the rules applicable to copyrights, as set forth in the TM FORUM IPR Policy, must be
followed) or as required to translate it into languages other than English.
The limited permissions granted above are perpetual and will not be revoked by TM FORUM or its successors or
assigns.
This document and the information contained herein is provided on an "AS IS" basis and TM FORUM
DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT
THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY OWNERSHIP RIGHTS OR ANY IMPLIED
WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
Executive Summary
This document, “REST API Design Guidelines Part 3” provides information for the development of
hypermedia extensions to TM Forum APIs without payload modification.
It also includes guidelines on how JSON-LD support may also be added to the existing TMF Open API
without payload modifications.
An API can support hypermedia extension and can also be JSON-LD enabled.
Conventions
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT",
"RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC
2119 [RFC2119].
A hypermedia aka web API shall express that an API is naturally following the REST architectural style
and hence the web architecture in all aspects. A good summary reflecting on the important role HATEOS
is playing for RESTful APIs and an explanation of a RESTful API maturity model, can be found here.
Hypermedia is a way for the server to tell the client what HTTP requests the server, from which the
client is free to choose. The server knows what happens, but the client decides what actually happens.
The World Wide Web works like this.
Due to the nature of HATEOAS, a web API (and also every web application) can be modelled as a state
machine or a workflow.
It describes all states by nodes and the state transitions by vertices from one node to another.
The states usually correspond to a resource, the transitions usually correspond to hypermedia controls,
i.e. links that are provided by a resource representation in order to reach another state.
An example
is given below:
Included along with other fields of a resource representation, links convey the relationships between
resources and offer clients a menu of resource-related actions, which are context-sensitive.
A Web API MUST offer clients a consistent way to easily discover the available links within a
representation.
TMF Open APIs offer support for hypermedia links as an extension so without breaking existing clients
that rely on the application/json media type.
At the moment the presense of hypermedia extension in the API is not negotiated between client and
server based on media type.
The TMF does not use a special media type for hypermedia.
It is assumed that an application supporting hypermedia extension will use the extended representation
when the application context is application/json.
• Evolve like all the other parts of a hypermedia API. The API provider can introduce new link-relation
types “on – the fly”. Clients need to be able to cope with getting new link relation types in the home
document. By that we mean that they should keep providing the established functionality and they
must not crash – obviously they don’t need to make use of the additional functionality
• Vary depending in which context it is retrieved. Typically, the available functionality depends on:
◦ Which API Consumer has been requesting the home document
◦ On which user’s behalf is the home document retrieved
The Home URI can be thought of in the same light as a web site home page.
If the API supports hypermedia extension then the HOME URI MUST be supported by the
implementation.
A HOME URI MUST return a JSON list of linked resource collections as a minimum.
An example of Home resource for Trouble Ticket API can be seen below:
{
"_links": {
"self": {
"href": "/troubleTicketManagement/v2/home"
},
"list-ticket": {
"href": "/troubleTicketManagement/v2/troubleTicket"
},
"retrieve-ticket": {
"hrefTemplate": "/troubleTicketManagement/v2/troubleTicket/{id}",
"hrefVars": {
"id": " /troubleTicketManagement/v2/schema/troubleTicket.json"
}
},
"create-ticket": {
"title": "Create Ticket",
"href": "/troubleTicketManagement/v2/troubleTicket",
"method": "POST",
"accepts": "application/json",
"schemaType": "json-schema",
"schemaUrl": " /troubleTicketManagement/v2/schema/troubleTicket.json"
},
"create-hub": {
"href": "/troubleTicketManagement/v2/hub",
"method": "POST"
},
"get-hub": {
"hrefTemplate": "/troubleTicketManagement/v2/hub{id}",
"hrefVars": {
"href": " /troubleTicketManagement/v2/schema/troubletTicket.json"
},
"method": "GET"
},
"delete-hub": {
"hrefTemplate": "/troubleTicketManagement/v2/hub\{id}",
"hrefVars": {
"href": "/troubleTicketManagement/v2/schema/param/id"
},
"method": "DELETE"
},
"publish-event": {
"href": "/troubleTicketManagement/v2/listener",
"method": "POST"
}
}
2.3. Linking
A Web API response message body MUST includes links and information about the meaning of the links
to allow REST clients to traverse the links to access resources related to the actual resource and perform
actions on them.
Links MUST be included, along with fields, within resource state representation.
The link is a JSON object with the name of the object indicating the relationship type, "rel" attribute.
Links are represented in TMF Open APIs as JSON objects contained within a _links hash that MUST be a
direct property of a resource object and have the following structure:
"hrefVars
": \{
"widget_i
d":
"https://
example.o
rg/param/
widget"
}
Default: GET
Fields No Array
{
"_links": {
"self": {
"href": "/troubleTicketManagement/v2/troubleTicket/42"
},
"home": {
"href": "/troubleTicketManagement/v2/home"
}
}
The self link for the collection resource SHOULD be exposed as Web Linking HTTP header.
{empty}[Response]
Content-Type: application/json
X-Total-Count :50
[{
"_links": {
"self": {
"href": "/troubleTicketManagement/v2/troubleTicket/6275"
},
"home": {
"href": "/troubleTicketManagement/v2/home"
}
},
"correlationId": "332",
"creationDate": "2016-10-19T00:00",
"description": "Compliant over last invoice",
"href": "/troubleTicketManagement/v2/troubleTicket /6275",
"id": "6275",
...
},
...
]
When retrieving the items within a collection resource, self link MUST be included for each item.
Other special links MAY be included but it is recommended that other links to be retrieved by the client
by going to the self link for each item within a collection.
A resource MAY have multiple links that share the same link relation. This can be represented using an
array of links. In this case the attribute name can be used as a secondary key.
{
"_links": {
"self": {
"href": "/troubleTicketManagement/v2/troubleTicket/6275"
},
"home": {
"href": "/troubleTicketManagemet/v2/home"
},
"related-party": [{
"name": "Individual",
"href": "/partyManagement/v2/individual/123"
},
{
"name": "Organisation",
"href": "/partyManagement/v2/organisation/345"
}]
}
}
Here is a full example for Trouble Ticket with all possbile links as per the API state machine defined in
chapter 1:
{
"id": "2",
"type": "Invoice dispute",
"severity": "low",
"description": "Invoice number 42 is wrong",
"status": "Submitted",
"statusChangeReason": "Initial submission",
"note": [{
"author": "Dirk Rejahl",
"text": "Customer called CC"
}],
"_links": {
"self": {
"href": "/troubleTicketManagement /v1/troubleTicket/2"
},
"acknowledge": {
The table below holds the list of special relationship types supported by the links "rel" property. These
are also registered as per the Web Linking standard [RFC5988].
In addition to that the identifier can be represented as a Web Linking HTTP header or as a link object –
both with the relation type self.
This can be done by passing the JSON-LD context to the consumer of the API.
The JSON-LD context SHOULD be passed in the Link HTTP Response header.
Link:<https://host:port/troubleTicketManagemet/v2/tt_context>;
rel="http://www.w3.org/ns/json-ld#context[http://www.w3.org/ns/json-ld#context";
{
"id": "1",
"href": "/troubleTicketManagemet/v2/troubleTicket/1",
"correlationId": "TT53482",
"description": "Customer complaint over last invoice.",
"severity": "Urgent",
"@type": “troubleTicket",
"_links": {
"self": {
"href": "/troubleTicketManagemet/v2/troubleTicket/1”
}
}
},
{
"id": "2",
"correlationId": "TT53483",
"description": "Customer asks for information about upgrading products",
"severity": "Low",
"@type": "troubleTicket",
"_links": {
"self": {
"href": "/troubleTicketManagemet/v2/troubleTicket/2"
}
}
}
{
"@context": {
"troubleTicket": "http://tmf.schema.org/TroubleTicket[http://tmf.schema.org/Troub
leTicket",
"id": "http://tmf.schema.org/id[http://tmf.schema.org/id",
"correlationId": "http://tmf.schema.org/correlationId[http://tmf.schema.org/corre
lationId",
"description": "http://tmf.schema.org/description[http://tmf.schema.org/descripti
on",
"severity": "http://tmf.schema.org/severity[http://tmf.schema.org/severity",
"creationDate": "http://tmf.schema.org/creationDate[http://tmf.schema.org/creatio
nDate",
"targetResolutionDate": "http://tmf.schema.org/targetResolutionDate[http://tmf.sc
hema.org/targetResolutionDate",
"status": "http://tmf.schema.org/status[http://tmf.schema.org/status",
"substatus": "http://tmf.schema.org/substatus[http://tmf.schema.org/substatus",
"statusChangeReason": "http://tmf.schema.org/statusChangeReason[http://tmf.schema
.org/statusChangeReason",
"statusChangeDate": "http://tmf.schema.org/statusChangeDate[http://tmf.schema.org
/statusChangeDate",
"resolutionDate": "http://tmf.schema.org/resolutionDate[http://tmf.schema.org/res
olutionDate",
"relatedParty": "http://tmf.schema.org/RelatedParty[http://tmf.schema.org/Related
Party",
"href": {
"@id": "http://tmf.schema.org/RelatedParty#href[http://tmf.schema.org/RelatedPart
y#href",
"@type": "@id"
},
"role": "http://tmf.schema.org/RelatedParty#role[http://tmf.schema.org/RelatedPar
ty#role",
"relatedObject": "http://tmf.schema.org/RelatedObject[http://tmf.schema.org/Relat
edObject",
"involvement": "http://tmf.schema.org/RelatedObject#involement[http://tmf.schema.
org/RelatedObject#involement",
"reference": {
"@id": "http://tmf.schema.org/RelatedObject#reference[http://tmf.schema.org/Relat
edObject#reference",
"@type": "@id"
},
"note": "http://tmf.schema.org/Note[http://tmf.schema.org/Note",
"date": "http://tmf.schema.org/Note#date[http://tmf.schema.org/Note#date",
"author": "http://tmf.schema.org/Note#author[http://tmf.schema.org/Note#author",
"text": "http://tmf.schema.org/Note#text",
"_links": "http://tmf.schema.org/links[http://tmf.schema.org/links",
"self": "http://tmf.schema.org/self[http://tmf.schema.org/self",
"@schemaLocation": "http://tmf.schema.org/schemaLocation",
"@baseType": "http://tmf.schema.org/baseType"
}
}
Note that the context for core TroubleTicket attributes like id, correlationid, description, severity etc. as
well as that of keywords like _links, @schemaLocation, @type,@baseType etc. is also defined above.
Any extensions to the Trouble Ticket API SHOULD be present in the JSON-LD context.
TMF.schema.org vocabulary provides a specialized vocabulary for the TMF Open APIs and it is built upon
the core Schema.org using the extension mechanism provided.
The following provides an example defining the vocabulary of Trouble Ticket entity:
{
"@context": {
"rdf": "http://www.w3.org/1999/02/22-rdf-syntax-
ns[http://www.w3.org/1999/02/22-rdf-syntax-ns#",
"rdfs": "http://www.w3.org/2000/01/rdf-
schema[http://www.w3.org/2000/01/rdf-schema#",
"xsd": "http://www.w3.org/2001/XMLSchema[http://www.w3.org/2001/XMLSchema#"
},
"@graph": [{
"@id": "http://schema.org/TroubleTicket[http://schema.org/TroubleTicket",
"@type": "rdfs:Class",
"http://schema.org/isPartOf[http://schema.org/isPartOf": {
"@id": "http://tmf.schema.org/[http://tmf.schema.org"
},
"rdfs:comment": "Trouble Ticket",
"rdfs:label": "TroubleTicket",
"rdfs:subClassOf": {
"@id": "http://schema.org/Thing[http://schema.org/Thing"
}
},
{
"@id": "http://schema.org/id[http://schema.org/id",
"@type": "rdf:Property",
"http://schema.org/domainIncludes[http://schema.org/domainIncludes": [{
"@id": "http://schema.org/TroubleTicket[http://schema.org/TroubleTicket"
}],
"http://schema.org/rangeIncludes[http://schema.org/rangeIncludes": {
"@id": "http://schema.org/Text[http://schema.org/Text"]
},
"http://schema.org/isPartOf[http://schema.org/isPartOf": {
"@id": "http://tmf.schema.org/[http://tmf.schema.org"
},
"rdfs:comment": "Ticket ID for a Trouble Ticket entity",
"rdfs:label": "id"
},
]}
{
"@id": "http://schema.org/TroubleTicket[http://schema.org/TroubleTicket",
"@type": "rdfs:Class",
"http://schema.org/isPartOf[http://schema.org/isPartOf": {
"@id": "http://tmf.schema.org/[http://tmf.schema.org"
},
"rdfs:comment": "Trouble Ticket",
"rdfs:label": "TroubleTicket",
"rdfs:subClassOf": {
"@id": "http://schema.org/Thing[http://schema.org/Thing"
}
}
Attribute Correlation Id
{
"@id": "http://schema.org/correlationId[http://schema.org/correlationId",
"@type": "rdf:Property",
"http://schema.org/domainIncludes[http://schema.org/domainIncludes": [{
"@id": "http://schema.org/TroubleTicket[http://schema.org/TroubleTicket"
}],
"http://schema.org/rangeIncludes[http://schema.org/rangeIncludes": {
"@id": "http://schema.org/Text[http://schema.org/Text"
},
"http://schema.org/isPartOf[http://schema.org/isPartOf": {
"@id": "http://tmf.schema.org/[http://tmf.schema.org"
},
"rdfs:comment": "Correlation ID for a Trouble Ticket entity",
"rdfs:label": "correlationId"
}
Similarly enumerated values are also can be defined – Example: Severity - http://schema.org/Severity.
Enumerated -Severity
{
"@id": "http://schema.org/Severity[http://schema.org/Severity",
"@type": "rdfs:Class",
"http://schema.org/isPartOf[http://schema.org/isPartOf": {
"@id": "http://tmf.schema.org/[http://tmf.schema.org"
},
"rdfs:comment": "Enumerated Severity values.",
"rdfs:label": "Severity",
"rdfs:subClassOf": {
"@id": "http://schema.org/Enumeration[http://schema.org/Enumeration"
}
},
{
"@id": "http://schema.org/Critical[http://schema.org/Critical",
"@type": "http://schema.org/Severity[http://schema.org/Severity",
"http://schema.org/isPartOf[http://schema.org/isPartOf": {
"@id": "http://tmf.schema.org/[http://tmf.schema.org"
},
"rdfs:comment": "Critical Severity",
"rdfs:label": "Critical"
}
Chapter 5. References
5.1. References
JSON-LD JSON For Linking Data http://json-ld.org/ Enrich TMF Open API
with application
Define context to semantics in order to
provide clients with enable machine-
additional application readable API’s.
semantics of the data
This section records the changes between this and the previous document version as it is edited by the
team concerned. Note: this is an incremental number which does not have to match the release number
and used for change control purposes only.
This section records the changes between this and the previous Official document release. The release
number is the ‘Marketing’ number which this version of the document is first being assigned to.
6.2. Acknowledgments
This document was prepared by the members of the TM Forum Open API team team: