IBM Cloud Docs
Resources

Resources

The design of resources is fundamental to a usable API. That is, APIs should be designed primarily around how the state of a service is modeled as resources and secondarily around operations available to manipulate those resources.

This distinction allows users of the APIs to learn and reason about a resource's state separately from how that state can be changed. It's also a familiar separation of concepts for programmers: any programming environment has some notion of structured data (from low-level constructs, such as blocks of memory, to high-level constructs, such as classes) and code that operates on it (from subroutines in assembly to methods on objects).

By defining the data structures — or resources — first, an API is more approachable. The REST architectural style for HTTP APIs is built on this idea.

Further, HTTP provides a standard way to represent a resource's canonical address in the form of a URL, and standard methods to create (with POST), list and read (with GET), mutate (with PUT and PATCH) and delete (with DELETE) resources. With standard methods available for each resource, users can apply knowledge and code across operations that each work in a predictable, robust way.

In IBM Cloud REST-style APIs, each resource type SHOULD have two standard URL path types:

  1. A resource collection path, such as /keys. A GET request on the collection returns a list of resources within it. A POST request on a collection URL creates a new resource in the collection.
  2. A resource path, such as /keys/{id} where {id} is a unique identifier for a specific resource. A GET request on a resource URL returns the canonical resource representation, PATCH updates a resource, PUT replaces a resource, and DELETE deletes a resource.

The aforementioned unique identifier MUST be immutable, generated by the system, and persisted in a field named id (which MUST NOT be used for any other purpose). The resource's URL (containing the unique identifier) MUST be in a field named href (which MUST NOT be used for any other purpose).

Resources directly created by clients using POST MUST also have a user-friendly name in a field named name (which MUST NOT be used for any other purpose). This user-friendly name:

  • MUST NOT be empty.
  • SHOULD NOT be more than 63 characters, and MUST NOT be more than 127 characters.
  • MUST consist of only characters in the set [a-zA-Z0-9-_.]
  • SHOULD consist only of characters in the set [a-z0-9-] (no uppercase letters).
  • SHOULD NOT start with a digit.
  • SHOULD reserve the prefixes - and ibm- for internal scenarios, such as system-created resources within the same scope.
  • SHOULD be mutable.
  • MUST be unique within a defined scope[1]. For example, if keys are per-account and per-region, then there can be at most one key named my-key within a given region for a given account.
  • SHOULD be automatically generated when unspecified at resource creation. The resulting name MUST be user-friendly (which precludes including id in the name) and MUST NOT include mutable aspects of the resource. For example, if a resource contains a mutable port number, the generated name MUST NOT include the port number.

For example, consider a resource's canonical representation:

GET /keys/b34f2d29-25ff-40ac-8762-78bad7e3eea9
---
{
  "id": "b34f2d29-25ff-40ac-8762-78bad7e3eea9",
  "href": "https://service.example.com/keys/b34f2d29-25ff-40ac-8762-78bad7e3eea9",
  "name": "my-key",
  "value": "VGhlcmUgd2FzIG5vIHBvc3NpYmlsaXR5IG9mIHRha2luZyBhIHdhbGsgdGhhdCBkYXkuIFdlIGhhZCBiZWVuIHdhbmRlcmluZywgaW5kZWVkLCBpbiB0aGUgbGVhZmxlc3Mgc2hydWJiZXJ5IGFuIGhvdXIgaW4gdGhlIG1vcm5pbmc7IGJ1dCBzaW5jZSBkaW5uZXIgKE1ycy4gUmVlZCwgd2hlbiB0aGVyZSB3YXMgbm8gY29tcGFueSwgZGluZWQgZWFybHkpIHRoZSBjb2xkIHdpbnRlciB3aW5kIGhhZCBicm91Z2h0IHdpdGggaXQgY2xvdWRzIHNvIHNvbWJyZSwgYW5kIGEgcmFpbiBzbyBwZW5ldHJhdGluZywgdGhhdCBmdXJ0aGVyIG91dGRvb3IgZXhlcmNpc2Ugd2FzIG5vdyBvdXQgb2YgdGhlIHF1ZXN0aW9uLg=="
  "zone": "us-south-1"
}

In such a resource type, id and href might be considered to be system-defined and thus omitted from the request schemas for POST /keys and PATCH /keys/{id}. Further, the key's value and zone could be considered immutable, and thus be included in the request schema for POST /keys but omitted from the request schema for PATCH /keys/{id}.

Properties that are included in such schemas MUST be defined consistently with a resource's canonical representation. For example, a PATCH request to change the name for the key in the previous example would look like:

PATCH /keys/b34f2d29-25ff-40ac-8762-78bad7e3eea9
{
  "name": "my-renamed-key"
}

... and MUST NOT look like:

PATCH /keys/b34f2d29-25ff-40ac-8762-78bad7e3eea9
{
  "label": "my-renamed-key"
}

Responses to requests that create or mutate a resource SHOULD return the resource's canonical representation. Rarely, a resource MAY have a "write-only" property represented in a request schema but not in its response schema.


  1. Note that the scope defined for resource name uniqueness need not be the scope resources are listed or otherwise viewed in. This means that a resource's canonical collection may return resources with duplicate names if that collection lists resources across a larger scope than the one defined for name uniqueness. Consequently, for a client to resolve a resource by name, it may need to filter the collection by name as well as an additional scoping property (such as region). The schemas for request payloads to create and mutate resources SHOULD be consistent with the canonical representation of the resource returned by a GET on the resource URL and MUST NOT differ arbitrarily. Often, schemas for resource creation and mutation MAY represent a subset of the properties in a resource's canonical representation, omitting properties that are system-defined or immutable. ↩︎