Common Data Types¶
Definitions of data objects that are good candidates for wider usage:
May Use a Common Money Object¶
Use the following common money structure:
Money: type: object properties: amount: type: number description: Amount expressed as a decimal number of major currency units format: decimal example: 99.95 currency: type: string description: 3 letter currency code as defined by ISO-4217 format: iso-4217 example: EUR required: - amount - currency
The decimal values for "amount" describe unit and subunit of the currency in a single value, where the digits before the decimal point are for the major unit and the digits after the decimal point are for the minor unit. Note that some business cases (e.g. transactions in Bitcoin) call for a higher precision, so applications must be prepared to accept values with unlimited precision, unless explicitly stated otherwise in the API specification. Examples for correct representations (in EUR):
42.20
or42.2
= 42 Euros, 20 Cent0.23
= 23 Cent42.0
or42
= 42 Euros1024.42
= 1024 Euros, 42 Cent1024.4225
= 1024 Euros, 42.25 Cent
Make sure that you don’t convert the “amount” field to float
/ double
types when implementing
this interface in a specific language or when doing calculations. Otherwise, you might lose
precision. Instead, use exact formats like
Java’s BigDecimal
.
See Stack Overflow for more info.
Some JSON parsers (NodeJS’s, for example) convert numbers to floats by default. After discussing the pros and cons, we’ve decided on "decimal" as our amount format. It is not a standard OpenAPI format, but should help us to avoid parsing numbers as float / doubles.
Use common field names and semantics¶
There exist a variety of field types that are required in multiple places. To achieve consistency across all API implementations, you must use common field names and semantics whenever applicable.
Generic Fields¶
There are some data fields that come up again and again in API data:
-
id
: the identity of the object. If used, IDs must opaque strings and not numbers. IDs are unique within some documented context, are stable and don't change for a given object once assigned, and are never recycled cross entities. -
xyzId
: an attribute within one object holding the identifier of another object must use a name that corresponds to the type of the referenced object or the relationship to the referenced object followed byId
(e.g.customerId
notcustomer_number
;parentNodeId
for the reference to a parent node from a child node, even if both have the typeNode
) -
createdDate
: when the object was created. If used, this must be adate-time
construct. -
updateDate
: when the object was updated. If used, this must be adate-time
construct. -
_type
: the kind of thing this object is. If used, the type of this field should be a string. Types allow runtime information on the entity provided that otherwise requires examining the Open API file.
Example JSON schema:
tree_node: type: object properties: id: description: the identifier of this node type: string createdDate: description: when got this node created type: string format: 'date-time' editedDate: description: when got this node last updated type: string format: 'date-time' \_type: type: string enum: [ 'LEAF', 'NODE' ] parentNodeId: description: the identifier of the parent node of this node type: string example: id: '123435' created: '2017-04-12T23:20:50.52Z' modified: '2017-04-12T23:20:50.52Z' type: 'LEAF' parent_node_id: '534321'
These properties are not always strictly necessary, but making them idiomatic allows API client developers to build up a common understanding of Zalando's resources. There is very little utility for API consumers in having different names or value types for these fields across APIs.
Address Fields¶
Address structures play a role in different functional and use-case contexts, including country variances. All attributes that relate to address information should follow the naming and semantics defined below.
addressee: description: a (natural or legal) person that gets addressed type: object required: - firstName - lastName - street - city - zip - countryCode properties: salutation: description: | a salutation and/or title used for personal contacts to some addressee; not to be confused with the gender information! type: string example: Mr firstName: description: | given name(s) or first name(s) of a person; may also include the middle names. type: string example: Hans Dieter lastName: description: | family name(s) or surname(s) of a person type: string example: Mustermann businessName: description: | company name of the business organization. Used when a business is the actual addressee; for personal shipments to office addresses, use `care_of` instead. type: string example: Consulting Services GmbH address: description: an address of a location/destination type: object properties: street: description: | the full street address including house number and street name type: string example: Schönhauser Allee 103 additional: description: | further details like building name, suite, apartment number, etc. type: string example: 2. Hinterhof rechts city: description: | name of the city / locality type: string example: Berlin zip: description: | zip code or postal code type: string example: 14265 countryCode: description: | the country code according to [iso-3166-1-alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) type: string example: DE required: - street - city - zip - countryCode
Grouping and cardinality of fields in specific data types may vary based on the specific use case (e.g. combining addressee and address fields into a single type when modeling an address label vs distinct addressee and address types when modeling users and their addresses).
{{ book.must }} Follow Hypertext Control Conventions¶
APIs that provide hypertext controls (links) to interconnect API resources must follow the conventions for naming and modeling of hypertext controls as defined in section Hypermedia.
{{ book.must }} Use Problem JSON¶
RFC 7807 defines the media type application/problem+json
.
Operations should return that (together with a suitable status code) when any problem
occurred during processing and you can give more details than the status code itself
can supply, whether it be caused by the client or the server (i.e. both for 4xx or 5xx errors).
A previous version of this guideline (before the publication of that RFC and the
registration of the media type) told to return application/x.problem+json
in these
cases (with the same contents).
Servers for APIs defined before this change should pay attention to the Accept
header sent
by the client and set the Content-Type
header of the problem response correspondingly.
Clients of such APIs should accept both media types.
APIs may define custom problems types with extension properties, according to their specific needs.
The Open API schema definition can be found on github. You can reference it by using:
responses: 503: description: Service Unavailable schema: $ref: 'https://zalando.github.io/problem/schema.yaml#/Problem'
{{ book.must }} Do not expose Stack Traces¶
Stack traces contain implementation details that are not part of an API, and on which clients should never rely. Moreover, stack traces can leak sensitive information that partners and third parties are not allowed to receive and may disclose insights about vulnerabilities to attackers.
Data Formats¶
{{ book.must }} Use JSON to Encode Structured Data¶
Use JSON-encoded body payload for transferring structured data. The JSON payload must follow RFC-7159 by having (if possible) a serialized object as the top-level structure, since it would allow for future extension. This also applies for collection resources where one naturally would assume an array. See the pagination section for an example.
{{ book.may }} Use non JSON Media Types for Binary Data or Alternative Content Representations¶
Other media types may be used in following cases: * Transferring binary data or data whose structure is not relevant. This is the case if payload structure is not interpreted and consumed by clients as is. Example of such use case is downloading images in formats JPG, PNG, GIF. * In addition to JSON version alternative data representations (e.g. in formats PDF, DOC, XML) may be made available through content negotiation.
{{ book.must }} Use Standard Date and Time Formats¶
JSON Payload¶
Read more about date and time format in Json Guideline.
HTTP headers¶
Http headers including the proprietary headers. Use the HTTP date format defined in RFC 7231.
{{ book.may }} Use Standards for Country, Language and Currency Codes¶
Use the following standard formats for country, language and currency codes:
-
ISO 3166-1-alpha2 country codes
- (It is “GB”, not “UK”, even though “UK” has seen some use at Zalando)
-
- BCP-47 (based on ISO 639-1) for language variants
{{ book.must }} Define Format for Type Number and Integer¶
Whenever an API defines a property of type number
or integer
, the precision must be defined by the format as follows to prevent clients from guessing the precision incorrectly, and thereby changing the value unintentionally:
type | format | specified value range |
---|---|---|
integer | int32 | integer between -231 and 231-1 |
integer | int64 | integer between -263 and 263-1 |
integer | bigint | arbitrarily large signed integer number |
number | float | IEEE 754-2008/ISO 60559:2011 binary64 decimal number |
number | double | IEEE 754-2008/ISO 60559:2011 binary128 decimal number |
number | decimal | arbitrarily precise signed decimal number |
The precision must be translated by clients and servers into the most specific language types. E.g. for the following definitions the most specific language types in Java will translate to BigDecimal
for Money.amount
and int
or Integer
for the OrderList.page_size
:
Money: type: object properties: amount: type: number description: Amount expressed as a decimal number of major currency units format: decimal example: 99.95 ... OrderList: type: object properties: pageSize: type: integer description: Number of orders in list format: int32 example: 42
{{ book.should }} Prefer standard Media type name application/json
¶
Previously, this guideline allowed the use of custom media types like application/x.zalando.article+json
.
This usage is not recommended anymore and should be avoided, except where it is necessary for cases
of media type versioning. Instead, the standard media type name application/json
(or application/problem+json
for HTTP error details) should be used for JSON-formatted data.
Custom media types with subtypes beginning with x
bring no advantage compared to the standard media type for JSON, and make automated processing more difficult. They are also discouraged by RFC 6838.