REST responses should be of a format that is both human and machine readable. Even if your initial consumer is via business to business (B2B), the API should be designed, where possible, for all potential consumers. REST APIs should, by default, return content in JSON format. But it is good practice to support multiple message formats (for example, XML, Multi-part Multipurpose Internet Mail Extensions [MIME]) and allow consuming applications to request the format they wish to consume (in line with the design for the consumer principle in section 2.1. Design for the consumer of Part A: API concepts and management 2022).

The response format required from a GET request must be indicated by the consumer in their request using the Accept header.

Example

# GET a resource and specify the response type

https://api.example.govt.nz/crown-property/0219c539-5885-4ab6-a55b-b0de7537c426

Accept: application/xml

Example

#Response

0219c539-5885-4ab6-a55b-b0de7537c426

commercial

Northbound Boulevard

Wellington

6011

NZ

annual

NZD

1000

squareMetre

rent

office

183

squareMetre

188

squareMetre

Free text describing the property in some way.

tennanted

2016-06-01

The request format for a request containing a request body (POST, PUT, PATCH) must be supplied in the Content-Type request header.

Example

#PUT (update) a resource

https://api.example.govt.nz/crown-property

Content-Type: application/json

Accept: application/json

#Request BODY

{

"id": "0219c539-5885-4ab6-a55b-b0de7537c426",

"category": "commercial",

"location": {

"streetName": "Northbound Boulevard",

"town": "Wellington",

"postalCode": "6011",

"countryCode": "NZ"

},

"pricing": {

"rentFrequency": "annual",

"currencyCode": "NZD",

"pricePerUnitArea": {

"price": 1000,

"units": "squareMetre"

},

"transactionType": "rent"

},

"property_type": "office",

"areas": {

"internal": {

"minimum": {

"value": 183,

"units": "squareMetre"

},

"maximum": {

"value": 188,

"units": "squareMetre"

}

}

},

"detailedDescription": [

{

"text": "Free text describing the property in some way."

}

],

"tennancy": {

"life\_cycle\_status": "vacant",

"nextReviewDate": "2016-07-01"

}

}

For a good example of this in action, see the tabbed format options for presenting patient information on the FHIR site.

Where JSON format is used in responses, it must conform to the JSON Standard (RFC 7159 — IETF). In line with this standard, textual content should be Unicode Transformation Format-8 (UTF-8) encoded by default, and any deviations from this must be limited.

It is inadvisable to use APIs for returning binary data such as images in the response content — hyperlinks to images are the preferred returned response. But where images are returned, ensure that the image encoding is MIME, HTTP Multipart.

Hypertext Markup Language (HTML) is allowed but is less flexible for consumer usage (for example, how can it be consumed by a native mobile app?), ties content to presentation and loses its benefits when building a single page application. It also reduces the ability to filter the content in transit for consumers who have fine-grained control on what they can access. However, it may be necessary for some forms of API like APIs with geospatial content.

Avoid using bespoke formats in returned content.

Recommended

Returned content format should be JSON by default.

Required

Requests for a specific return format must be defined in the Accept header.

1.7.3. Layout

Responses should be a JSON object (not an array) by default. Using an array to return results limits the ability to include metadata about results and limits the API’s ability to add additional top-level properties in the future. Do not use unpredictable properties. Parsing a JSON response where properties are unpredictable (for example, derived from data) is difficult, and adds friction for clients.

Example of good layout

{

"response_meatadata": {

"item1": "value1",

"item2": "value2"

},

"responseArray": [

{

"name": "entity1",

"type": "good"

},

{

"name": "entity2",

"type": "good"

}

]

}

Example of bad layout

[

{

"name": "entity1",

"type": "bad"

},

{

"name": "entity2",

"type": "bad"

}

]

1.7.4. JSON property names

Within content, property names should conform to the following guidelines:

Property names should be meaningful names with defined semantics.

Property names must be camel-case American Standard Code for Information Interchange (ASCII) strings.

The first character must be a letter or underscore (_).

Subsequent characters can be a letter, a digit or underscore.

Reserved JavaScript keywords should be avoided.

1.7.5. Consistency

Preserve backwards compatibility with existing consumers of the API by returning expected fields and employing sensible default values for missing fields. Keep consistency of terminology throughout, so that the consumer is not misled. Avoid modifying the semantics of content to new meanings, for example, do not change a ‘title’ field from being used for the title of a page to meaning a person’s job title.

1.7.6. Singletons versus collections

Some API GET calls will return a single resource item (for example, GET https://api.example.govt.nz/passengers/12345) whereas some calls will return a collection of resource items (for example, GET https://api.example.govt.nz/passengers), and the handling and error treatment can be different.

A single item will generally consist of all the pertinent fundamental details about the resource, and the GET will return these fundamental details.

Example

#GET a single passenger resource by ID

GET https://api.example.govt.nz/passengers/12345

Accept: application/json,version=1.*

{

“id”: 12345,

“names”: {

“firstName”: “John”,

“middleName”: “Howard”,

“lastName”: “Doe”,

“preferredName”: “Howie”,

“title”: “Mr”

},

“addresses”: [

{

“type”: “home”,

“address1”: “1 Some Street”,

“address2”: “Some Suburb”,

“address3”: “Some City”,

“address4”: null,

“country”: “New Zealand”,

“postcode”: 1111

},

{

“type”: “business”,

“address1”: “2 Work Street”,

“address2”: “Work Suburb”,

“address3”: “Work City”,

“address4”: null,

“country”: “New Zealand”,

“postcode”: 2222

}

]

}

If passenger 12345 did not exist, the HTTP return code would be 404.

If a requested sub resource did not exist — for example, addresses for passenger 54321: GET https://api.example.govt.nz/passengers/54321/addresses an HTTP 404 response would not be valid. The correct response would contain an empty array:

Example

#GET a single passenger address resource by ID

GET https://api.example.govt.nz/passengers/54321/addresses

Accept: application/json,version=1.*

{

“id”: 54321,

“addresses”: [

{

“type”: null,

“address1”: null,

“address2”: null,

“address3”: null,

“address4”: null,

“country”: null,

“postcode”: null

}

]

}

A collection will take the form of an array of the given resources, including any related metadata. The collection returned should be the complete set, leaving it to the consumer to reduce the quantity of information returned by sending filters in the resource request (see section 1.5.6. Query arguments).

The only reason the collection should be filtered by the API provider is based on the security context — the API consumer should only gain access to what that consumer is allowed to see. It is advisable to aim for consistent naming of collection resource fields, as this enables application developers to create generic handling of the data from across various resource collections offered by the API. Collection resources should not contain binary attachments or other content that will lead to large response payloads.

Note: The example below is contrived and it would be rare to expose a resource collection as large as passengers.

Example

# GET a collection of passenger resources

GET https://api.example.govt.nz/passengers

Accept: application/json,version=1.*

{

“passengers”: [

{

“id”: 12345,

“names”: {

“firstName”: “John”,