Resource

Name

Use the plural version of a resource name to be consistent when referring to particular resources, e.g.:

/users
/offers
/contests
/shipments
/transactions
/payments

Identification (UU)IDs

Use UUIDs unless you have a very good reason not to. Do not use IDs that will not be globally unique across instances of the service or other resources in the service, especially auto-incrementing IDs.

Provide UUIDs as a lowercase string in 8-4-4-4-12 format, e.g.:

01234567-89ab-cdef-0123-456789abcdef

URLs for user's collections

If you want to return collections containing user's private data, always add user-id to the URL (in path or in query).

E.g.:

\orders?seller.id={sellerId}
\users\{userId}\watched-offers

Because watched offers for users A and B are different, these collections should have different URLs.

GET responses can be cached on public proxies (varnish, ISP proxies). To prevent caching return header: "Cache-Control: private"

Lowercase paths

Use lowercase and dash-separated path names, e.g.:

/general-deliveries
/application-configurations

Minimize resources nesting

In data models with nested parent/child resource relationships, paths may become deeply nested, e.g.:

/users/{userId}/offers/{offerId}/shipments/{shipmentId}

Limit nesting depth by preferring to locate resources at the root path. Use nesting to indicate scoped collections. For example, for the case above where shipping belongs to an offer:

/users/{userId}
/users/{userId}/offers
/offers/{offerId}
/offers/{offerId}/shipments
/shipments/{shipmentId}

Beta resources

Beta version of API resources is aimed at helping developers get familiar with it before realising a new API version. Beta version resources can change continuously and affect compatibility of current API.

Beta resources rules:

  • Numbers added to beta version resources are +1 compared to the numbers of current resources. Moreover, “public” is replaced with “beta”, e.g. if resources or users are marked as application/vnd.allegro.public.v1+json, then in beta version the same resources will be marked as application/vnd.allegro.beta.v2+json,
  • Within a given version, beta resources can be subject to modifications. As a result, we do not recommend the production use of beta resources,
  • When completing a beta resource , enter it into the API with a suitable beta number, e.g. if you complete your work, resources or users marked as application/vnd.allegro.beta.v2+json will be entered into the API as application/vnd.allegro.public.v2+json.

Versioning

To prevent unexpected, breaking changes to users, ask for providing a suitable version in all the requests.

Avoid default versions as it can change in the future.

To specify version use custom media type and +json Structured Syntax Suffix i.e. application/vnd.allegro.public.v1+json. Each request must specify its version by setting up Accept or Content-type properly. The header depends on method semantics e.g.: GET methods usually expect Accept header, POST methods usually expectContent-type header and PUT methods usually expect both headers.

Content-Type: application/vnd.allegro.public.v1+json
Accept: application/vnd.allegro.public.v1+json

With jersey you can simply use:

@Consumes("application/vnd.allegro.public.v1+json")
@Produces("application/vnd.allegro.public.v1+json")

Beta version

Beta version resources are marked the same way as described above, but “public” is replaced with “beta” in a media type, e.g. application/vnd.allegro.beta.v1+json.

Content-Type: application/vnd.allegro.beta.v1+json
Accept: application/vnd.allegro.beta.v1+json

Views

If you need different views of the same object, construct different URLs to distinguish views.

For example: some offer data are available only for seller. To get these private data, add context /sale/ to the path:

GET /sale/offers

To get only public data use:

GET /offers

To get offers watched by user:

GET /watched-offers

User Agent Header

All API requests MUST include a valid User-Agent header.

Here are default User-Agent examples:

User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Iron/35.0.1900.0 Chrome/35.0.1900.0 Safari/537.36
User-Agent: Mozilla/5.0 (Linux; U; Android 2.2.1; en-us; Nexus One Build/FRG83) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1

Identifying your client

When you make HTTP requests to the API, be sure to specify a User-Agent header that properly identifies your client. Make up a custom value of an User-Agent header that identifies your service or application.

Here are examples of custom User-Agent headers:

For mobile application:

User-Agent: Application-Package-Name_BundleId/ApplicationVersion (Client-Id CMDeviceUUID) OSName/OSVersion (Manufacturer Model)

For a service:

User-Agent: Your-Service-Name/ServiceVersion (your-service-host-id) OSName

Sample:

User-Agent: pl.allegro.sale/1.5.0 (Client-Id 01234567-89ab-cdef-0123-456789abcdef) Android/4.0 (Motorola XT1052)

Use HTTP methods to operate on collections and entities

There is one single rule concerning operations performed on collections and entities - Use HTTP methods

You can operate on resources using HTTP methods such as POST, GET, PUT, and DELETE - to remember them, refer to the CRUD acronym (Create-Read-Update-Delete).

Resource / HTTP method POST (create) GET (read) PUT (update) DELETE (delete)
/users Create new user List users Error Error
/users/{uuid} Error Get user Update user if exists Delete user

Update and create must return a resource representation

PUT and POST methods modify fields of the underlying resource that were not part of the provided parameters (for example: createdAt or updatedAt timestamps). As indicated in the section Provide full resources where available, to prevent an API consumer from having to hit the API again for an updated representation, have the API return the updated (or created) representation as part of the response.

Create entity

  • server requires all entity properties to be located in a request body
  • server returns the HTTP 201 Created status code
  • response will also include the Location header that points to the URL of the new resource (RFC 6570)
  • server returns the new entity in the established version (see Versioning section)

Sample request:

curl -X POST https://allegroapi.io/users \
    -H "Accept: application/vnd.allegro.public.v1+json" \
    -H "Content-Type: application/vnd.allegro.public.v1+json" \
    -d
{
  "firstName": "John",
  "middleName": "Doe",
  "nickName": "Zen",
  "email": "zed@allegro.pl"
}

Sample response:

  • status: 201 Created
  • header Location: https://allegroapi.io/users/01234567-89ab-cdef-0123-456789abcdef
  • header Content-Type: application/vnd.allegro.public.v1+json
  • whole entity is included in a body (additional fields such as id, createdAt, updatedAt)
{
  "id": "01234567-89ab-cdef-0123-456789abcdef",
  "firstName": "John",
  "middleName": "Doe",
  "nickName": "Zen",
  "email": "zed@allegro.pl",
  "createdAt": "2012-01-01T12:00:00.000Z",
  "updatedAt": "2012-01-01T13:00:00.000Z"
}

List entities (collection)

  • server returns the HTTP 200 Ok status code
  • response collection is presented as an array (in the established version) in a field bearing the same name as the resource (Wrap collection in object)

Sample request:

curl https://allegroapi.io/users -H "Accept: application/vnd.allegro.public.v1+json"

Get selected entity

  • server returns the HTTP 200 Ok status code
  • server returns an entity in the established version

Sample request:

curl https://allegroapi.io/users/{id} -H "Accept: application/vnd.allegro.public.v1+json"

Update entity

  • to update an entity, the server requires being provided with all the properties that can be subject to update
  • server returns the HTTP 200 Ok status code
  • server returns an updated entity in the established version

Sample request:

curl -X PUT https://allegroapi.io/users/01234567-89ab-cdef-0123-456789abcdef \
    -H "Accept: application/vnd.allegro.public.v1+json" \
    -H "Content-Type: application/vnd.allegro.public.v1+json" \
    -d
{
  "middleName": null,
  "nickName": "Zed"
}

Sample response:

  • status: 200 Ok
  • header Content-Type: application/vnd.allegro.public.v1+json
{
  "id": "01234567-89ab-cdef-0123-456789abcdef",
  "firstName": "John",
  "middleName": null,
  "nickName": "Zed",
  "email": "zed@allegro.pl",
  "createdAt": "2012-01-01T12:00:00.000Z",
  "updatedAt": "2012-01-01T13:00:00.000Z"
}

In the example above, a nick name is changed to "Zed" and a middle name is left empty (assuming that the field middleName is optional).

Delete entity

  • server returns the HTTP 204 No Content status code
  • response body content is empty
  • no need for Accept header (outcome of the Delete method should not be versioned, except for special cases – see Versioning section)

Sample request:

curl -X DELETE https://allegroapi.io/users/{id}

Return appropriate status codes

HTTP Status Codes

Return appropriate HTTP status codes with each response. Responses concerning successful operations should be coded according to the following rules:

  • 200 Ok: Response to a successful GET, PUT, PATCH request. An existing resource is updated synchronously.
  • 201 Created: Response to a POST request that results in entity creation. It should be combined with a Location header pointing to the location of the new resource.
  • 202 Accepted: Accepted request concerning a POST, PUT, DELETE, or PATCH request that will be processed asynchronously.
  • 204 No Content: Response to a successful request that will return empty body (as a DELETE request)
  • 304 Not Modified: Used when HTTP caching headers are in use (e.g. etags)

Pay attention to the use of authentication and authorization error codes:

  • 401 Unauthorized: Request failed because user is not authenticated
  • 403 Forbidden: Request failed because user does not have authorization to access a specific resource

Return suitable codes to provide additional information in case of errors:

  • 400 Bad Request: The request is malformed (the request body does not parse)
  • 404 Not Found: Requesting for a resource that does not exist
  • 405 Method Not Allowed: Requested HTTP method is not available for a given resource
  • 406 Not Acceptable: Missing or incorrect Accept header was provided as part of the request
  • 410 Gone: Indicates that the resource is no longer available. Useful as a blanket response for old API resource versions
  • 415 Unsupported Media Type: If incorrect Content-type header was provided as part of the request
  • 422 Unprocessable Entity: Used for validation errors – request was understood, but contained invalid parameters
  • 429 Too Many Requests: When a request is rejected due to rate limiting
  • 500 Internal Server Error: Something is wrong with the server
  • 501 Not Implemented: This feature is not ready yet
  • 502 Bad Gateway: Something is wrong with the server
  • 503 Service Unavailable: Unable to connect to the service
  • 504 Gateway Timeout: Something is wrong with the network layer (Load balancer or Edge service cannot connect to the service because of timeout)

Validate request parameters

In some situations you need to validate parameters before you send the create request (POST) to a given resource. It is particularly common in case of frontend, because you want to check whether provided data is acceptable, as only backend service has updated knowledge about how to validate parameters. You can reuse an existing method for creating resources by giving information about dry-run in a query string, e.g.:

curl -X POST https://allegroapi.io/users?dryRun=true  \
    -d {"login": "userLogin", "password": "userPassword", "email": "user@allegro.pl"}
    -H "Content-type: application/vnd.allegro.public.v1+json"
    -H "Accept: application/vnd.allegro.public.v1+json"

Sample response:

Response status: 204 No content

Validate errors

For error validation, return HTTP 422 Unprocessable Entity response body with a list of errors. Sample error validation response:

{
    "errors": [
        {
            "message": "Provided email address does not match pattern",
            "code": "EmailFormatNotValidException",
            "details": null,
            "path": "email",
            "userMessage": "Pole password musi zawierać małe i duże litery oraz przynajmniej jedną cyfrę."
        }
    ]
}

Validate selected fields

Use include in query string to specify what parameters you want to validate, e.g. to validate only login and password fields, use include=login&include=password:

curl -X POST https://allegroapi.io/users?dryRun=true&include=login&include=password  \
    -d {"login": "userLogin", "password": "userPassword", "email": "user@allegro.pl"}
    -H "Content-type: application/vnd.allegro.public.v1+json"
    -H "Accept: application/vnd.allegro.public.v1+json"

Sample response:

Response status 204 No Content