Resource Objects
Resource Objects
Section titled “Resource Objects”Standard structure for representing domain entities
Overview
Section titled “Overview”Resource objects represent domain entities (database records, API resources, etc.) with a consistent structure. This enables predictable data access, relationship handling, and query operations.
Resource Object Structure
Section titled “Resource Object Structure”A resource object MUST contain:
{ "type": "order", "id": "12345", "attributes": { "status": "pending", "total": { "amount": "99.99", "currency": "USD" }, "created_at": "2024-01-15T10:30:00Z" }}Required Members
Section titled “Required Members”| Member | Type | Description |
|---|---|---|
type | string | Resource type identifier |
id | string | Unique identifier within type |
Optional Members
Section titled “Optional Members”| Member | Type | Description |
|---|---|---|
attributes | object | Resource attributes |
relationships | object | Related resources |
meta | object | Non-standard meta-information |
Type Member
Section titled “Type Member”The type member identifies the resource’s type.
- MUST be a string
- MUST contain at least one character
- MUST be unique across the API
- SHOULD use
snake_casefor multi-word types - SHOULD be singular (e.g.,
ordernotorders) - SHOULD match the domain model name
Examples
Section titled “Examples”orderorder_itemshipping_addresstracking_eventcustomerAnti-patterns
Section titled “Anti-patterns”orders # Plural - use singularorderItem # camelCase - use snake_caseOrder # PascalCase - use lowercaseorder-item # kebab-case - use snake_caseID Member
Section titled “ID Member”The id member uniquely identifies a resource within its type.
- MUST be a string
- MUST be unique within the resource type
- MUST NOT change for the lifetime of the resource
- SHOULD be URL-safe
ID Formats
Section titled “ID Formats”Recommended formats:
| Format | Example | Notes |
|---|---|---|
| UUID v4 | "550e8400-e29b-41d4-a716-446655440000" | Universal uniqueness |
| ULID | "01ARZ3NDEKTSV4RRFFQ69G5FAV" | Sortable, compact |
| Prefixed | "order_abc123xyz" | Type-aware, readable |
| Integer (as string) | "12345" | Database primary keys |
IDs MUST be strings even for numeric values:
// Correct{ "type": "order", "id": "12345" }
// Incorrect{ "type": "order", "id": 12345 }Attributes Member
Section titled “Attributes Member”The attributes member contains the resource’s data.
- MUST be an object
- MUST NOT contain
idortype(these are top-level) - MUST NOT contain relationship data
- MAY contain any valid JSON value
Attribute Naming
Section titled “Attribute Naming”Attribute names SHOULD:
- Use
snake_case - Be descriptive
- Avoid abbreviations
{ "type": "order", "id": "12345", "attributes": { "order_number": "ORD-2024-001", "status": "pending", "total_amount": { "amount": "99.99", "currency": "USD" }, "item_count": 3, "is_gift": false, "notes": null, "created_at": "2024-01-15T10:30:00Z", "updated_at": "2024-01-15T10:35:00Z" }}Complex Attributes
Section titled “Complex Attributes”Attributes MAY contain nested objects and arrays:
{ "type": "customer", "id": "42", "attributes": { "name": "Alice Smith", "email": "alice@example.com", "address": { "line1": "123 Main St", "line2": null, "city": "Helsinki", "postal_code": "00100", "country_code": "FI" }, "tags": ["vip", "wholesale"], "preferences": { "newsletter": true, "language": "en" } }}Attribute Types
Section titled “Attribute Types”| JSON Type | Usage |
|---|---|
| string | Text, enums, dates (ISO 8601), UUIDs |
| number | Integers, floats (avoid for currency) |
| boolean | True/false flags |
| null | Absent or unknown values |
| object | Structured data, value objects |
| array | Lists, collections |
Money Values
Section titled “Money Values”Money SHOULD use a structured format to avoid floating-point issues:
{ "total": { "amount": "99.99", "currency": "USD" }}Date/Time Values
Section titled “Date/Time Values”Dates and times MUST use ISO 8601 format:
{ "created_at": "2024-01-15T10:30:00Z", "scheduled_date": "2024-01-20", "duration": { "value": 30, "unit": "minute" }}Relationships Member
Section titled “Relationships Member”The relationships member describes connections to other resources.
Structure
Section titled “Structure”{ "type": "order", "id": "12345", "attributes": { ... }, "relationships": { "customer": { "data": { "type": "customer", "id": "42" } }, "items": { "data": [ { "type": "order_item", "id": "1" }, { "type": "order_item", "id": "2" } ] }, "shipping_address": { "data": null } }}Relationship Object
Section titled “Relationship Object”Each relationship MUST contain a data member:
data Value | Meaning |
|---|---|
| Object | To-one relationship (resource identifier) |
| Array | To-many relationship (resource identifiers) |
| null | Empty to-one relationship |
[] | Empty to-many relationship |
Resource Identifier
Section titled “Resource Identifier”A resource identifier contains only type and id:
{ "type": "customer", "id": "42" }This is NOT a full resource object—it’s a reference.
Relationship Names
Section titled “Relationship Names”Relationship names SHOULD:
- Use
snake_case - Be descriptive of the relationship
- Match the related resource type when appropriate
{ "relationships": { "customer": { ... }, // Matches type "billing_address": { ... }, // Descriptive "shipping_address": { ... }, // Descriptive "created_by": { ... }, // Describes relationship "items": { ... } // Plural for to-many }}Compound Documents
Section titled “Compound Documents”When including related resources, use the included array:
{ "data": { "type": "order", "id": "12345", "attributes": { "status": "pending" }, "relationships": { "customer": { "data": { "type": "customer", "id": "42" } } } }, "included": [ { "type": "customer", "id": "42", "attributes": { "name": "Alice", "email": "alice@example.com" } } ]}includedMUST be an array of resource objects- Each included resource MUST be unique (by type + id)
- Included resources MUST be referenced by at least one relationship
- Included resources MAY have their own relationships
See Relationships for inclusion details.
Meta Member
Section titled “Meta Member”The meta member contains non-standard information:
{ "type": "order", "id": "12345", "attributes": { ... }, "meta": { "permissions": ["read", "update"], "cache_expires_at": "2024-01-15T11:00:00Z", "version": 3 }}Use Cases
Section titled “Use Cases”- Permission indicators
- Cache control hints
- Version numbers
- Computed values not in attributes
Resource Definition
Section titled “Resource Definition”Services SHOULD define their resources with allowed fields, filters, relationships, and sorts:
// Conceptual resource definition{ "type": "order", "fields": { "self": ["id", "order_number", "status", "total_amount", "created_at", "updated_at"], "customer": ["id", "name", "email"], "items": ["id", "sku", "quantity", "price"] }, "filters": { "self": ["id", "order_number", "status", "created_at"], "customer": ["id", "name"] }, "sorts": { "self": ["order_number", "status", "created_at", "total_amount"] }, "relationships": ["customer", "items", "shipping_address", "billing_address"]}This definition:
- Whitelists queryable fields
- Whitelists filterable attributes
- Whitelists sortable attributes
- Defines available relationships
Sparse Fieldsets
Section titled “Sparse Fieldsets”Clients MAY request specific fields:
{ "fields": { "self": ["id", "status", "total_amount"], "customer": ["id", "name"] }}Response includes only requested fields:
{ "type": "order", "id": "12345", "attributes": { "status": "pending", "total_amount": { "amount": "99.99", "currency": "USD" } }}See Sparse Fieldsets for details.
Examples
Section titled “Examples”Simple Resource
Section titled “Simple Resource”{ "type": "customer", "id": "42", "attributes": { "name": "Alice Smith", "email": "alice@example.com", "created_at": "2024-01-10T08:00:00Z" }}Resource with Relationships
Section titled “Resource with Relationships”{ "type": "order", "id": "12345", "attributes": { "order_number": "ORD-2024-001", "status": "shipped", "total_amount": { "amount": "249.99", "currency": "USD" }, "created_at": "2024-01-15T10:30:00Z" }, "relationships": { "customer": { "data": { "type": "customer", "id": "42" } }, "items": { "data": [ { "type": "order_item", "id": "101" }, { "type": "order_item", "id": "102" } ] }, "shipping_address": { "data": { "type": "address", "id": "addr_789" } } }}Resource with Meta
Section titled “Resource with Meta”{ "type": "document", "id": "doc_abc", "attributes": { "title": "Q4 Report", "content_type": "application/pdf", "size_bytes": 1048576 }, "meta": { "download_url": "https://...", "expires_at": "2024-01-16T10:30:00Z", "permissions": ["read", "download"] }}Collection of Resources
Section titled “Collection of Resources”{ "data": [ { "type": "tracking_event", "id": "evt_001", "attributes": { "status": "in_transit", "location": "Helsinki Hub", "occurred_at": "2024-01-15T14:30:00Z" } }, { "type": "tracking_event", "id": "evt_002", "attributes": { "status": "out_for_delivery", "location": "Local Depot", "occurred_at": "2024-01-15T16:00:00Z" } } ], "meta": { "page": { "cursor": { "current": "...", "next": null } } }}Full Compound Document
Section titled “Full Compound Document”{ "data": { "type": "shipment", "id": "ship_12345", "attributes": { "tracking_number": "MH726955185FI", "status": "in_transit", "carrier": "posti", "created_at": "2024-01-14T09:00:00Z" }, "relationships": { "origin": { "data": { "type": "location", "id": "loc_001" } }, "destination": { "data": { "type": "location", "id": "loc_002" } }, "events": { "data": [ { "type": "tracking_event", "id": "evt_001" }, { "type": "tracking_event", "id": "evt_002" } ] } } }, "included": [ { "type": "location", "id": "loc_001", "attributes": { "name": "Helsinki Warehouse", "postal_code": "00100", "country_code": "FI" } }, { "type": "location", "id": "loc_002", "attributes": { "name": "Tampere Office", "postal_code": "33100", "country_code": "FI" } }, { "type": "tracking_event", "id": "evt_001", "attributes": { "status": "picked_up", "occurred_at": "2024-01-14T10:00:00Z" } }, { "type": "tracking_event", "id": "evt_002", "attributes": { "status": "in_transit", "occurred_at": "2024-01-15T08:00:00Z" } } ]}