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
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}
Versioning
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")
We don't introduce new API versions, all changes also those that are breaking would be introduced under already existing version, marked as application/vnd.allegro.public.v1+json
.
Instead of API versioning, we have the procedures to handle new changes depending on their type. The context, decision, and types of changes and how we handle them are described in document ADR-001: Public API is not versioned.
Beta resources
Beta version of API resources is aimed at helping developers get familiar with it before releasing a new API resource. Beta version resources can change continuously and affect compatibility of current API.
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
Rules for new beta resources:
* within a given version, beta resources can be subject to modifications. As a result, we do not recommend the production use of beta resources,
* breaking changes within the beta version can be implemented within subsequent versions and marked, for example, as application/vnd.allegro.beta.v2+json
,
* if you complete your work with the beta version, release it as application/vnd.allegro.public.v1+json
.
Beta version marked as application/vnd.allegro.beta.v1+json
can be used in exceptional situations to implement compatibility-breaking changes to resources that have already been released in the version marked as application/vnd.allegro.public.v1+json
. Read more on that in ADR-001: Public API is not versioned.
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://api.allegro.pl/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://api.allegro.pl/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://api.allegro.pl/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://api.allegro.pl/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://api.allegro.pl/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://api.allegro.pl/users/{id}
Return appropriate 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 successfulGET
,PUT
,PATCH
request. An existing resource is updated synchronously.201 Created
: Response to aPOST
request that results in entity creation. It should be combined with aLocation
header pointing to the location of the new resource.202 Accepted
: Accepted request concerning aPOST
,PUT
,DELETE
, orPATCH
request that will be processed asynchronously.204 No Content
: Response to a successful request that will return empty body (as aDELETE
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 authenticated403 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 exist405 Method Not Allowed
: Requested HTTP method is not available for a given resource406 Not Acceptable
: Missing or incorrectAccept
header was provided as part of the request410 Gone
: Indicates that the resource is no longer available. Useful as a blanket response for old API resource versions414 URI Too Long
: Indicates that the URI requested by the client is longer than the server is willing to interpret415 Unsupported Media Type
: If incorrectContent-type
header was provided as part of the request422 Unprocessable Entity
: Used for validation errors – request was understood, but contained invalid parameters429 Too Many Requests
: When a request is rejected due to rate limiting500 Internal Server Error
: Something is wrong with the server501 Not Implemented
: This feature is not ready yet502 Bad Gateway
: Something is wrong with the server503 Service Unavailable
: Unable to connect to the service504 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://api.allegro.pl/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://api.allegro.pl/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