Copyright © 2026 World Wide Web Consortium . W3C ® liability , trademark and permissive document license rules apply.
[@@ from charter ]
The Linked Web Storage Protocol specification aims to provide applications with secure and permissioned access to externally stored data in an interoperable way.
The Linked Web Storage Protocol does/does not include protocol details for integration with identity layers and mechanisms; access management and data integrity; notifications about resource changes; and authorization mechanisms.
This section describes the status of this document at the time of its publication. A list of current W3C publications and the latest revision of this technical report can be found in the W3C standards and drafts index .
This is an unofficial proposal.
This document was published by the Linked Web Storage Working Group as an Editor's Draft.
Publication as an Editor's Draft does not imply endorsement by W3C and its Members.
This is a draft document and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to cite this document as other than a work in progress.
This document was produced by a group operating under the W3C Patent Policy . W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent that the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy .
This document is governed by the 18 August 2025 W3C Process Document .
This section is non-normative.
List of TODO s and ideas in flux to enable editors to communicate asynchronously.
This section is non-normative.
The
LWS
Protocol
defines
standard
interactions
by
which
a
some
party
can
make
some
resources
available
to
some
agents.
A
resource
manager
may
keep
a
served
resource
private,
may
make
it
publicly
available
to
anyone,
or
may
limited
limit
its
visibility
to
a
constrained
set
of
requesting
agents
.
As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.
The key words MAY , MUST , MUST NOT , OPTIONAL , RECOMMENDED , REQUIRED , SHOULD , and SHOULD NOT in this document are to be interpreted as described in BCP 14 [ RFC2119 ] [ RFC8174 ] when, and only when, they appear in all capitals, as shown here.
A
LWS
REST
Server
is
an
HTTP
server
[
rfc9112
]
that
complies
with
all
of
the
relevant
"
MUST
"
statements
in
this
specification.
Specifically,
the
relevant
normative
"
MUST
"
statements
in
Sections
999
REST
Binding
9.
Operations
of
this
document
MUST
be
respected.
A
LWS
REST
Client
is
an
HTTP
client
[
rfc9112
]
that
complies
with
all
of
the
relevant
"
MUST
"
statements
in
this
specification.
Specifically,
the
relevant
normative
"
MUST
"
statements
in
Sections
999
REST
Binding
9.
Operations
of
this
document
MUST
be
respected.
The terms "authorization server" and "client" are defined by the OAuth 2.0 Authorization Framework [ RFC6749 ].
The terms "end-user" and "issuer" are defined by OpenID Connect Core 1.0 [ OPENID-CONNECT-CORE ].
This
specificaiton
specification
defines
the
following
terms:
items
property
in
container
representations
and
the
rel="up"
link
relation
in
HTTP
headers.
This
specification
defines
operations
on
served
resources
,
the
resulting
change
of
state,
and
a
response
indended
intended
to
give
the
requesting
agent
requested
infomation
or
inform
them
of
the
outcome
of
the
operation
.
An
operation
is
any
of
the
following
actions
that
can
be
performed
on
a
served
resource
:
The folowing section will describe the semantics and responses of these operations but the following core responses apply to any operation:
This section defines a mechanism for identifying agents and end users that interact with a linked web storage server. This specification does not mandate a particular format for authentication credentials, though it does describe how existing identity systems can be used in conjunction with the linked web storage authorization framework.
The data model described in this section outlines the requirements for any concrete serialization of an authentication credential.
An authentication credential MUST include tamper evident claims about a subject, including:
Validation of an authentication credential requires a trust relationship between the verifier and issuer of the credential. This trust relationship MAY be established through an out-of-band mechanism. Any additional mechanisms for establishing trust between a verifier and an issuer are outlined in specific authentication suites.
An authentication credential MUST be signed. It is RECOMMENDED that the signature uses asymmetric cryptography.
Each authentication suite MUST be associated with a token type URI. An authentication suite SHOULD use a URI defined in the IANA "OAuth URI" registry.
A storage description resource provides information a client can use when interacting with a storage, including descriptions of capabilities and service endpoints.
id
-
the
id
property
is
REQUIRED
.
Its
value
MUST
be
a
URI
that
identifies
the
storage.
type
-
the
type
property
is
REQUIRED
.
Its
value
MUST
be
a
string
that
equals
Storage
or
a
set
of
strings
that
contains
an
item
equal
to
Storage
(case-sensitive).
capability
-
the
capability
property
is
OPTIONAL
.
Its
value
MUST
be
a
set
of
capabilities,
where
each
capability
is
described
by
a
map
containing
the
following
properties.
Additional
properties
MAY
be
present.
id
-
the
id
property
is
OPTIONAL
.
If
present,
its
value
MUST
be
a
URI.
type
-
the
type
property
is
REQUIRED
.
Its
value
MUST
be
a
string
or
a
set
of
strings.
service
-
the
service
property
is
REQUIRED
.
Its
value
MUST
be
a
set
of
services,
where
each
service
is
described
by
a
map
containing
the
following
properties.
Additional
properties
MAY
be
present.
id
-
the
id
property
is
OPTIONAL
.
If
present,
its
value
MUST
be
a
URI.
type
-
the
type
property
is
REQUIRED
.
Its
value
MUST
be
a
string
or
a
set
of
strings.
serviceEndpoint
-
the
serviceEndpoint
property
is
REQUIRED
.
Its
value
MUST
be
a
URI.
{
"@context": "https://www.w3.org/ns/lws/v1",
"id": "https://storage.example/",
"type": "Storage",
"service": [{
"type": "StorageDescription",
"serviceEndpoint": "https://storage.example/description"
}]
}
All
responses
to
GET
and
HEAD
requests
targeting
storage
resources
MUST
include
a
Link
header
whose
target
is
the
URI
of
the
storage
description
resource,
including
a
relation
(
rel
)
parameter
whose
value
equals
https://www.w3.org/ns/lws#storageDescription
.
When
dereferenced,
the
storage
description
MUST
contain
an
id
property
that
identifies
the
storage.
In
addition,
the
service
property
MUST
contain
a
service
description
whose
type
equals
StorageDescription
and
whose
serviceEndpoint
equals
the
URL
of
the
storage
description.
The URI for a storage description can be distinct from the URI identifying a storage, which can be distinct from the storage's root container. These URIs can also be identical, provided that the resulting representation conforms to the requirements outlined in this document.
A storage description may contain descriptions of additional capabilities supported by the storage.
In
addition
to
a
StorageDescription
service,
a
storage
description
resource
may
contain
links
to
other
services
connected
to
a
storage.
The
API
definition
of
these
services
are
outside
the
scope
of
this
specification.
A
storage
description
resource
MUST
be
serializable
with
the
media
type
application/lws+json
.
Other
representations
MAY
be
available
via
content
negotiation.
{
"@context": "https://www.w3.org/ns/lws/v1",
"id": "https://storage.example/",
"type": "Storage",
"capability": [{
"type": "https://feature.example/PatchSupport",
"mediaType": {
"text/turtle": ["application/sparql-update"],
"application/n-triples": ["application/sparql-update"],
"application/linkset+json": ["application/merge-patch+json", "application/json-patch+json"]
}
}, {
"type": "https://feature.example/ResumableUploads"
}, {
"type": "https://feature.example/ContentNegotiation",
"source": "application/ld+json",
"target": ["text/turtle", "application/n-triples"]
}, {
"type": "https://feature.example/ContentNegotiation",
"source": "image/jpeg",
"target": ["image/png"]
],
"service": [{
"type": "NotificationService",
"serviceEndpoint": "https://storage.example/notification/api"
}, {
"type": "TypeIndexService",
"serviceEndpoint": "https://storage.example/types/api"
}, {
"type": "DataSharingService",
"serviceEndpoint": "https://storage.example/sharing/api"
}, {
"type": "StorageDescription",
"serviceEndpoint": "https://storage.example/description"
}]
}
Linked Web Storage organizes resources into containers. A container is a specialized resource that holds references to other resources, called its members. Containers serve as organizational units, analogous to directories or collections, enabling clients to group, discover, and navigate resources. A container maintains references to its member resources, which may comprise both non-container resources and additional container resources, thereby enabling hierarchical formations. Typically, a container holds minimal intrinsic content beyond metadata or enumerations of its members; its principal role is to aggregate and structure subordinate resources. The storage system's root is designated as a container, serving as the apex organizational unit devoid of a superior parent. Containers MUST support pagination for membership listings using 'ContainerPage' types, with properties such as 'first', 'next', 'prev', and 'last'. Representations MUST use JSON-LD with a specific frame and normative context, optionally advertising content negotiation via 'Vary: Accept' headers. Storage MAY function as a root container, enabling direct writes.
Every LWS storage has a root container that serves as the top-level organizational unit. The root container has no parent and acts as the entry point for the storage hierarchy.
Resources in LWS are classified as either:
The
containment
relationship
between
a
resource
and
its
parent
container
is
expressed
via
the
rel="up"
link
relation.
Servers
MUST
include
a
Link
header
with
rel="up"
pointing
to
the
parent
container
in
responses
to
GET
and
HEAD
requests
on
any
non-root
resource.
Link: </alice/notes/>; rel="up"
A
container's
members
are
listed
in
its
representation
using
the
items
property.
The
server
manages
this
list;
clients
cannot
modify
it
directly.
Membership
changes
occur
as
a
side
effect
of
resource
creation
and
deletion.
The server MUST maintain containment integrity at all times:
items
list.
items
list.
Deleting
a
container
requires
the
container
to
be
empty,
unless
recursive
deletion
is
explicitly
requested.
Resources
are
identified
by
URIs.
The
URI
of
a
resource
is
independent
of
its
position
in
the
containment
hierarchy.
Servers
assign
URIs
during
resource
creation
and
MAY
incorporate
client
hints
(e.g.,
the
Slug
header),
but
clients
SHOULD
NOT
assume
that
URI
structure
reflects
containment.
Containment
relationships
are
expressed
through
metadata
(
rel="up"
links
and
the
items
property
in
container
representations),
not
through
URI
path
structure.
This
separation
allows
servers
flexibility
in
URI
assignment
while
maintaining
a
well-defined
organizational
model.
When a client retrieves a container, the server returns a structured container representation describing the container and its contents. This section defines the required and optional properties of a container representation.
A container representation MUST include the following properties:
id
:
The
URI
of
the
container.
type
:
The
value
"Container"
.
totalItems
:
An
integer
indicating
the
total
number
of
resources
contained
in
the
container
which
can
be
disclosed
to
the
client.
items
:
An
array
of
contained
resource
descriptions
(see
below).
If
the
container
is
empty,
this
MUST
be
an
empty
array.
Each
entry
in
the
items
array
describes
a
resource
contained
in
the
container.
A
contained
resource
description
MUST
include:
id
:
The
URI
of
the
contained
resource.
type
:
The
type
of
the
resource.
MUST
be
"DataResource"
or
"Container"
,
or
an
array
containing
at
least
one
of
these
two
strings.
Servers
MAY
include
additional
user-defined
types
as
URIs
(e.g.,
["DataResource",
"http://example.org/customType"]
).
A contained resource description SHOULD include:
mediaType
:
The
media
type
of
the
resource
(e.g.,
"text/plain"
,
"image/jpeg"
).
MUST
be
present
for
DataResources.
size
:
The
size
of
the
resource
in
bytes,
expressed
as
an
integer.
modified
:
The
date
and
time
the
resource
was
last
modified,
expressed
as
an
ISO
8601
date-time
string.
The
following
example
shows
a
container
at
/alice/notes/
containing
two
resources:
{
"@context": "https://www.w3.org/ns/lws/v1",
"id": "/alice/notes/",
"type": "Container",
"totalItems": 2,
"items": [
{
"type": "DataResource",
"id": "/alice/notes/shoppinglist.txt",
"mediaType": "text/plain",
"size": 47,
"modified": "2025-11-24T12:00:00Z"
},
{
"type": ["DataResource", "http://example.org/customType"],
"id": "/alice/notes/todo.json",
"mediaType": "application/json",
"size": 2048,
"modified": "2025-11-24T13:00:00Z"
}
]
}
This section defines the four core operations that a Linked Web Storage (LWS) server MUST support. These operations manipulate resources and containers in a transport-independent manner, focusing on semantics rather than implementation details. Each operation specifies inputs, expected behaviors, and possible responses. Responses include success indicators, resource representations (where applicable), and error conditions. Implementations MUST handle these operations atomically and consistently, meaning each operation either succeeds completely or fails without partial side effects. In case of errors, responses SHOULD provide enough detail for agents to understand the issue without leaking sensitive information.
For each core operation (create, read, update, delete), we describe the HTTP method(s) to use, required headers or special considerations (including concurrency controls via ETags, content negotiation, and pagination for container listings), and what the server should do and return. Standard HTTP status codes are used to indicate outcomes with additional mappings for scenarios such as quota exceeded (507 Insufficient Storage) or precondition failures (412 Precondition Failed). The binding tries to adhere to HTTP/1.1 and relevant RFCs (such as [ RFC7231 ] for HTTP semantics, [ RFC7233 ] for range requests, [ RFC5789 ] for PATCH, [ RFC8288 ] for Web Linking, and [ RFC9264 ] for Link Sets) so that it integrates naturally with web standards. Discoverability is emphasized through mechanisms like Link headers and WWW-Authenticate headers on 401 responses, avoiding hardcoded URI locations. Metadata integration is required across operations, ensuring atomicity and use of Link Sets for server-managed and user-managed properties.
Note:
As
all
examples
in
this
specifications,
examples
given
in
this
section
(HTTP
request
and
response
snippets)
are
non-normative
,
meant
to
illustrate
typical
usage.
The
actual
requirements
are
stated
in
the
descriptive
text
and
tables.
Also,
while
this
binding
covers
HTTP
(as
the
initial
target
protocol),
the
LWS
operations
could
in
principle
be
bound
to
other
protocols
in
the
future.
Servers
MUST
support
content
negotiation
for
application/lws+json
,
application/ld+json
,
and
application/json
for
container
representations
(see
Container
10.
LWS
Media
Type
).
Servers
MAY
additionally
support
formats
like
Turtle.
This section defines the model for associating metadata with LWS resources. The LWS metadata system is based on the principles of Web Linking [ RFC8288 ], which allows servers to describe the relationships between resources using typed links. Metadata enhances discoverability, supports self-descriptive APIs, and aligns with resource operations, and container hierarchies.
Metadata Model All metadata in LWS is expressed as a set of typed links originating from a resource (the link context). Each link consists of:
Metadata distinguishes between resources and their representations, allowing for multiple media types where applicable. For Data Resources, metadata includes representations, each with mediaType and optional sizeInBytes. For Containers and Data Resources we consider the link to its parent container resource to be part of the metadata of the resource.
The Linkset Resource For each resource in storage, a server MUST make metadata links available as a standalone resource according to [ RFC9264 ].
rel="linkset"
.
application/linkset+json
.
Discovering Metadata Clients discover metadata primarily through Link headers in response to GET or HEAD requests.
rel="storageDescription"
on
relevant
responses.
rel="up"
pointing
to
the
parent
container
for
any
non-root
resource.
https://www.w3.org/ns/lws#PreferLinkRelations
to
include
or
omit
specific
relations.
Metadata Types
| Category | Description |
|---|---|
| System Managed |
Maintained
by
the
server;
Read-Only.
Includes
linkset
,
type
,
mediaType
,
size
,
modified
.
|
| Core Metadata |
Managed
by
the
client
(subject
to
server
restrictions).
Includes
up
,
items
,
title
,
creator
.
|
| User-Defined | Custom vocabularies and indexes created by the user. |
Modifiability Considerations Core metadata MAY be modified by clients. To ensure interoperability, servers MUST use standard HTTP headers to advertise their capabilities:
Method Discovery: Servers MUST advertise support for GET and PATCH operations on the linkset resource via the Allow header.
Patch
Format
Discovery:
Servers
MUST
advertise
support
for
JSON
Merge
Patch
[
RFC7386
]
via
the
Accept-Patch
header:
Accept-Patch:
application/merge-patch+json
.
Optional Methods: Servers MAY support PUT or alternative patch formats; if supported, these MUST be included in the Allow and Accept-Patch headers respectively.
[!IMPORTANT] Clients SHOULD NOT assume support for PUT or specific patch formats unless they are advertised in the resource headers and MUST handle 405 Method Not Allowed or 415 Unsupported Media Type responses gracefully.
Managing Metadata Metadata is managed by interacting with the resource's associated linkset URI. Servers MUST support concurrency controls for updates.
Partial
Updates
(PATCH):
This
is
the
primary
mechanism
for
metadata
management.
Servers
MUST
support
PATCH
using
application/merge-patch+json
.
Replacement (PUT): If advertised in the Allow header, a client MAY replace the entire linkset. If the server does not support PUT, it MUST reject the request with 405 Method Not Allowed.
Restrictions:
Servers
MAY
restrict
modifications
to
specific
links
(like
up
or
items
)
to
maintain
system
integrity.
Lifecycle: Metadata lifecycles are tied to the described resource; deleting a resource MUST result in the automatic removal of its associated linkset metadata.
The create resource operation adds a new served resource to an existing container . This operation handles both the creation of data resources (files) and sub-containers.
Inputs:
Behavior:
Possible Responses:
New
resources
are
created
using
POST
to
a
target
container
URI,
with
the
server
assigning
the
final
identifier.
Clients
MAY
suggest
a
name
via
the
Slug
header.
Clients
MAY
provide
initial
user-managed
metadata
for
the
new
resource
by
including
one
or
more
Link
headers
in
the
POST
request,
following
the
syntax
of
Web
Linking
in
[
RFC8288
].
Server-managed
metadata
MUST
be
generated
automatically
by
the
server
upon
creation
and
MUST
NOT
be
overridden
by
client-provided
links.
On
success,
the
server
MUST
return
the
201
status
code
with
the
new
URI
in
the
Location
header.
The
server
MUST
include
Link
headers
for
key
server-managed
metadata,
including
a
link
to
the
parent
container
(
rel="up"
),
and
a
link
to
the
created
resource's
dedicated
linkset
resource
(
rel="linkset";
type="application/linkset+json"
).
Additional
links
SHOULD
include
rel="type"
(indicating
https://www.w3.org/ns/lws#Container
or
https://www.w3.org/ns/lws#DataResource
).
The
body
MAY
be
empty
or
include
a
minimal
representation
of
the
resource.
All
metadata
creation
and
linking
MUST
be
atomic
with
the
resource
creation
to
maintain
consistency.
POST
(to
a
container
URI)
–
Create
with
server-assigned
name:
Use
POST
to
add
a
new
resource
inside
an
existing
container.
The
server
assigns
an
identifier
to
the
resource,
optionally
suggested
via
the
Slug
header.
The
server
MAY
honor
the
Slug
header
if
it
does
not
conflict
with
naming
rules
or
existing
resources.
Clients
indicate
the
type
of
resource
to
create
as
follows:
Link
header
with
rel="type"
pointing
to
the
Container
type:
Link:
<https://www.w3.org/ns/lws#Container>;
rel="type"
.
Content-Type
header.
Example (POST to create a new data resource):
POST /alice/notes/ HTTP/1.1
Host: example.com
Authorization: Bearer <token>
Content-Type: text/plain
Content-Length: 47
Slug: shoppinglist.txt
milk
eggs
bread
butter
apples
orange juice
In
this
example,
the
client
is
posting
to
the
container
/alice/notes/
.
It
provides
text/plain
content
(a
grocery
list)
and
suggests
the
name
shoppinglist.txt
for
the
new
resource.
If
/alice/notes/
exists
and
the
client
is
authorized,
the
server
will
create
a
new
DataResource
and
add
it
to
the
container's
membership.
Example (Response to POST — Data Resource):
HTTP/1.1 201 Created
Location: /alice/notes/shoppinglist.txt
Content-Type: text/plain; charset=UTF-8
Link: </alice/notes/shoppinglist.txt.meta>; rel="linkset"; type="application/linkset+json"
Link: </alice/notes/>; rel="up"
Link: <https://www.w3.org/ns/lws#DataResource>; rel="type"
Content-Length: 0
On
success,
return
201
Created
with
the
new
URI
in
the
Location
header.
The
body
may
be
empty
or
a
minimal
representation.
If
the
target
container
/alice/notes/
does
not
exist,
the
server
MUST
return
a
404
error
status
unless
another
status
code
is
more
appropriate.
Creating
Containers:
To
create
a
new
container,
a
client
uses
POST
to
an
existing
parent
container
with
a
Link
header
indicating
the
Container
type.
For
example:
POST /alice/ HTTP/1.1
Host: example.com
Authorization: Bearer <token>
Content-Length: 0
Slug: notes
Link: <https://www.w3.org/ns/lws#Container>; rel="type"
Example (Response to POST — container):
HTTP/1.1 201 Created
Location: /alice/notes/
Link: </alice/notes/.meta>; rel="linkset"; type="application/linkset+json"
Link: </alice/>; rel="up"
Link: <https://www.w3.org/ns/lws#Container>; rel="type"
Content-Length: 0
This
creates
a
new
container
at
/alice/notes/
,
with
server-generated
metadata
including
rel="type"
as
https://www.w3.org/ns/lws#Container
.
Additional notes on Create (HTTP binding):
Link
header
with
rel="storageDescription"
on
401
responses
to
guide
clients
without
hardcoded
URIs.
Managing
and
Retrieving
Metadata
(Related
to
Creation):
While
metadata
is
primarily
retrieved
via
read
operations,
it
is
generated
during
creation.
Clients
can
immediately
retrieve
it
post-creation
using
GET
or
HEAD
on
the
new
resource
URI.
Clients
can
use
the
Prefer
header
to
request
inclusion
of
specific
metadata
links
(via
relation
types)
and
attributes.
Retrieves the representation of an existing resource or the listing of a container.
The
read
resource
operation
requests
a
resource
representation
with
HTTP
GET
requests
(and
HEAD
for
header-only
requests).
The
behavior
differs
depending
on
whether
the
target
URL
is
a
container
or
a
non-container
resource
(DataResource).
Servers
MUST
distinguish
resource
types
via
metadata.
All
responses
MUST
integrate
with
metadata
as
defined
in
Section
8.1,
including
Link
headers
for
key
relations
such
as
rel="linkset"
,
rel="up"
,
and
rel="type"
.
Servers
MUST
ensure
atomicity
between
the
resource
state
and
its
metadata
during
reads.
GET (non-container resource) – Retrieve a resource's content: Send GET to the resource URI for full content (if authorized). Respond with 200 OK, body containing the data, and Content-Type matching the stored media type. Servers MUST support range requests per [ RFC7233 ] for partial retrieval. Responses MUST include an ETag header for concurrency control and caching.
Example (GET a file):
GET /alice/notes/shoppinglist.txt HTTP/1.1
Authorization: Bearer <token>
Accept: text/plain
This
requests
the
content
of
/alice/notes/shoppinglist.txt
,
indicating
that
the
client
wants
it
in
text
form.
Assuming
the
resource
exists,
is
text,
and
the
client
has
access:
HTTP/1.1 200 OK
Content-Type: text/plain; charset=UTF-8
Content-Length: 34
ETag: "abc123456"
Link: </alice/notes/shoppinglist.txt.meta>; rel="linkset"; type="application/linkset+json"
Link: </alice/notes/>; rel="up"
Link: <https://www.w3.org/ns/lws#DataResource>; rel="type"
milk
cheese
bread
guacamole
soda
chocolate bars
hash
eggs
The
server
returned
the
text
content
(34
bytes
in
total,
as
indicated
by
Content-Length
).
The
content
is
exactly
the
stored
data
in
the
file.
The
ETag:
"abc123456"
is
a
version
identifier
for
caching
or
concurrency
purposes.
The
response
includes
Link
headers
for
metadata
discoverability,
with
mandatory
fields
such
as
up
and
type
.
GET (container resource) – List a container's contents: When the target URI corresponds to a container (determined via metadata type), a GET request returns a listing of the container's members. The response body is a container representation as defined in the Container Representation section, using the LWS container media type. The listing includes metadata for each member: resource identifiers ( MUST ), types ( MUST ), media types ( MUST for DataResources), sizes ( SHOULD ), and modification timestamps ( SHOULD ).
Example (GET a container):
GET /alice/notes/ HTTP/1.1
Authorization: Bearer <token>
Accept: application/ld+json
Assuming the container exists and the client has access:
HTTP/1.1 200 OK
Content-Type: application/lws+json
ETag: "container-etag-789"
Link: </alice/notes/.meta>; rel="linkset"; type="application/linkset+json"
Link: </alice/>; rel="up"
Link: <https://www.w3.org/ns/lws#Container>; rel="type"
{
"@context": "https://www.w3.org/ns/lws/v1",
"id": "/alice/notes/",
"type": "Container",
"totalItems": 2,
"items": [
{
"type": "DataResource",
"id": "/alice/notes/shoppinglist.txt",
"mediaType": "text/plain",
"size": 47,
"modified": "2025-11-24T12:00:00Z"
},
{
"type": ["DataResource", "http://example.org/customType"],
"id": "/alice/notes/todo.json",
"mediaType": "application/json",
"size": 2048,
"modified": "2025-11-24T13:00:00Z"
}
]
}
In
this
example,
/alice/notes/
is
a
container.
The
response
uses
JSON-LD
with
the
LWS
context,
listing
members
with
required
metadata.
Each
item
includes
its
type
,
id
,
mediaType
,
size
,
and
modified
timestamp
as
flat
properties.
In
all
cases,
the
server
MUST
include
the
following
metadata
in
the
response
headers:
an
ETag
(representing
the
listing
version,
which
changes
on
membership
modifications),
and
Link
headers
with
rel="type"
indicating
it
is
a
container,
rel="linkset"
and
rel="up"
.
HEAD (any resource or container) – Headers/metadata only: The LWS server MUST support HEAD [ RFC9110 ] for both containers and non-containers, returning the same headers as GET (including ETag, Content-Type, Link for metadata) but without a body. This enables metadata retrieval without transferring content.
Caching and Conditional Requests: LWS leverages HTTP caching semantics. Servers MUST support conditional requests via If-None-Match (with ETags) or If-Modified-Since headers. If the resource or container listing has not changed, respond with 304 Not Modified to avoid redundant transfers. ETags MUST be provided in all GET/HEAD responses for concurrency and caching support.
Discoverability and Authorization: For enhanced discoverability, servers SHOULD include WWW-Authenticate headers on 401 Unauthorized responses with parameters to guide clients without hardcoded URIs. Metadata links SHOULD be included where applicable.
Modifies the state of an existing [served resource] via full replacement or a partial patch.
The update resource modifies the contents of an existing served resource by a PUT request (to replace the entire resource) or a PATCH request (to apply a partial modification). The client must have write access to the resource’s URL to perform these operations. Note: This section describes updating a resource's primary content. To update its metadata, see Section 9.3.2. LWS servers MUST handle PUT and PATCH requests on resource URIs as modifications to the resource content only, with no default impact on the associated linkset. To optionally update both content and metadata in a single atomic operation, clients MAY include Link headers in the PUT/PATCH request to the resource URI and specify the preference 'Prefer: set-linkset' (as defined in RFC 7240). In this case, the server MUST interpret the provided Link headers as a replacement (for PUT) or partial update (for PATCH) to the linkset, in addition to applying the content changes. This behavior is OPTIONAL for servers but, if supported, MUST be invoked explicitly via the Prefer header to prevent unintentional metadata overwrites. Servers that do not support combined updates MUST ignore the preference or respond with 501 Not Implemented.
PUT
(replace
full
resource)
–
Send
PUT
to
the
resource
URI
with
new
full
content
in
the
body
and
matching
Content-Type
(generally
consistent
with
existing
type).
PUT
is
idempotent
for
existing
resources.
For
safety,
include
If-Match
with
current
ETag
(per
Section
7.3
concurrency);
mismatch
yields
412
Precondition
Failed
or
409
Conflict.
Without
checks,
updates
are
unconditional
but
risk
overwriting
concurrent
changes.
If
a
server
supports
Etags
for
a
resource,
it
MUST
reject
unconditional
PUT
requests
that
lack
an
If-Match
header
with
a
428
Precondition
Required
response.
Example (PUT to update a resource):
PUT /alice/personalinfo.json HTTP/1.1
Authorization: Bearer <token>
Content-Type: application/json
If-Match: "abc123456"
{
"name": "Alice",
"age": 30,
"city": "New London",
"state": "Connecticut"
}
In this example, the client is updating an existing JSON resource at /alice/personalinfo.json. It includes an If-Match header with the ETag "abc123456" that it got from an earlier GET or HEAD request. The server will compare that to the current ETag; if they match, it proceeds to replace the content with the JSON provided. If they don’t match, the server rejects the update (because the resource was changed by someone else in the meantime). Successful response: If the update succeeds, the server can respond with 200 OK and possibly include the updated representation or some confirmation (like the new content or a part of it). Alternatively, the server may respond with 204 No Content to indicate success with no body (especially common if no further info needs to be conveyed). In either case, the server SHOULD include a new ETag to signify the new version, and maybe a Content-Type if a body is returned. For example:
HTTP/1.1 204 No Content
ETag: "def789012"
This
tells
the
client
the
update
went
through
and
provides
the
new
ETag
.
If
the
server
chose
to
return
the
updated
content,
it
might
use
200
OK
and
include
the
JSON
in
the
body,
along
with
headers.
If-Match
did
not
match
(concurrent
modification),
the
server
could
return
412
Precondition
Failed
(meaning
the
precondition
header
failed)
or
409
Conflict
–
our
earlier
abstract
description
used
Conflict
for
concurrency
issues,
and
409
is
a
natural
mapping
for
that
scenario.
If
the
resource
did
not
exist,
a
PUT
meant
as
an
update
will
result
in
404
Not
Found
(unless
the
intent
was
to
create,
but
typically
clients
use
PUT
for
create
only
when
they
are
sure
of
what
they’re
doing,
or
they
use
it
as
upsert
without
If-Match).
If
the
client
is
not
authorized,
403
Forbidden
(or
401
Unauthorized
if
no
valid
credentials
were
provided).
If
the
request
payload
is
not
valid,
400
Bad
Request
.
PATCH (partial update) – The HTTP PATCH method [ RFC5789 ] allows a client to specify partial modifications to a resource, rather than sending the whole new content. This is useful for large resources where sending the entire content would be inefficient if only a small part changed, or for concurrent editing where you want to apply specific changes. LWS server MUST minimally support JSON Merge Patch (application/merge-patch+json) as defined in [ RFC7386 ].
Update Resource Metadata (HTTP PUT / PATCH on Linkset) A resource's metadata is updated by modifying its corresponding linkset resource, discovered via the Link header with rel="linkset". Full Replacement (PUT): A PUT request to the linkset URI with a complete linkset document in the body replaces all metadata for the resource. Partial Update (PATCH): A PATCH request to the linkset URI adds, removes, or modifies specific links.
Concurrency Control for Metadata Because a resource's metadata can be modified by multiple actors, preventing concurrent overwrites is critical. To ensure data integrity, LWS servers and clients MUST implement optimistic concurrency control using conditional requests [ RFC7232 ] for all PUT and PATCH operations on a linkset resource. Server Responsibilities: A server MUST include an Etag header in its responses to GET and HEAD requests for a linkset resource. Upon a successful PUT or PATCH on the linkset, the server MUST generate a new, unique Etag value for the modified linkset and return it in the Etag header of the response. Client Responsibilities: When modifying a linkset resource, a client MUST include an If-Match header containing the most recent Etag it received for that resource. Processing Rules: If the If-Match header value does not match the linkset's current Etag, the server MUST reject the request with a 412 Precondition Failed status code. If the If-Match header is missing from a PUT or PATCH request to a linkset URI, the server MUST reject the request with a 428 Precondition Required status code [ RFC6585 ]. Example (PUT to replace a linkset): A client first fetches the linkset and receives its ETag.
GET /alice/personalinfo.json.meta HTTP/1.1
Authorization: Bearer <token>
Accept: application/linkset+json
HTTP/1.1 200 OK
Content-Type: application/linkset+json
ETag: "meta-v1"
{
"linkset": [
{
"anchor": "/alice/personalinfo.json",
"describedby": [ { "href": "/schemas/personal-info.json" } ]
}
]
}
The client now wants to add a license. It constructs a new, complete linkset document and sends a PUT request with the If-Match header.
PUT /alice/personalinfo.json.meta HTTP/1.1
Authorization: Bearer <token>
Content-Type: application/linkset+json
If-Match: "meta-v1"
{
"linkset": [
{
"anchor": "/alice/personalinfo.json",
"describedby": [ { "href": "/schemas/personal-info.json" } ],
"license": [ { "href": "https://creativecommons.org/licenses/by/4.0/" } ]
}
]
}
If successful, the server responds with success and the new ETag.
HTTP/1.1 204 No Content
ETag: "meta-v2"
Summary of Update Rules If you want to change only the content of a resource → PUT/PATCH the resource itself. If you want to change only the links (metadata) of a resource → PUT/PATCH the resource’s associated linkset resource. If you want to change both content and links → PUT/PATCH the resource itself, including the appropriate Link headers AND 'Prefer: set-linkset'. Setting both is off by default.
Permanently removes a resource and its associated metadata.
The delete resource operation is implemented using the HTTP DELETE method, as defined in the abstract operation above. This section specifies the HTTP bindings for inputs, behaviors, and responses.
The
DELETE
request
targets
the
URI
of
the
resource
or
container
to
remove.
Clients
MAY
include
an
If-Match
header
with
an
ETag
for
concurrency
checks.
Deletion
and
Containment:
When
a
resource
is
deleted,
the
server
MUST
atomically
remove
it
from
its
parent
container's
items
list.
The
parent
container's
totalItems
count
and
ETag
MUST
be
updated
accordingly.
For non-container resources, the server removes the resource content, its associated metadata (linkset), and the containment reference in the parent container.
For
container
resources,
the
server
defaults
to
non-recursive
deletion.
If
the
container
is
not
empty
and
recursion
is
not
requested,
the
server
MUST
reject
the
request
with
409
Conflict.
Servers
MAY
support
recursive
deletion
of
all
contained
resources
within
the
container
that
is
being
deleted.
Clients
MUST
use
the
Depth:
infinity
header
to
request
for
a
recursive
delete,
as
defined
in
[
RFC4918
].
On success, the server MUST respond with 204 No Content. Servers SHOULD support conditional requests, as defined in [ RFC9110 ].
If the client lacks authorization, the server MUST return 403 Forbidden (if the client's identity is known but permissions are insufficient) or 401 Unauthorized (if no valid authentication is provided). In cases where revealing resource existence poses a security risk, the server MAY return 404 Not Found instead.
Example (DELETE a non-container resource):
DELETE /alice/notes/shoppinglist.txt HTTP/1.1
Authorization: Bearer <token>
If-Match: "abc123456"
Assuming
the
ETag
matches
and
the
client
is
authorized,
the
server
deletes
the
resource,
its
metadata,
and
removes
it
from
the
parent
container
/alice/notes/
atomically:
HTTP/1.1 204 No Content
Example (DELETE a non-empty container without recursion):
DELETE /alice/notes/ HTTP/1.1
Authorization: Bearer <token>
Assuming
/alice/notes/
contains
resources,
the
server
refuses
the
deletion:
HTTP/1.1 409 Conflict
Content-Type: text/plain
Cannot delete container /alice/notes/ - container is not empty.
Example (DELETE a container with recursion, if supported):
DELETE /alice/notes/ HTTP/1.1
Authorization: Bearer <token>
Depth: infinity
Assuming the server supports recursion and the client has permissions for all contents, the server deletes the container and its descendants atomically:
HTTP/1.1 204 No Content
This table maps generic LWS responses (from Section 8) to HTTP status codes and payloads for consistency, incorporating specific scenarios such as pagination, concurrency controls, quota constraints, and metadata integration:
| LWS response | HTTP status code | HTTP payload |
|---|---|---|
| Success (read or update, returning data) | 200 OK | Resource representation in the response body (for GET or if PUT/PATCH returns content), along with relevant headers (Content-Type, ETag, Link for metadata such as rel="linkset", rel="up"). For container listings, include JSON-LD with normative context and member metadata (IDs, types, sizes, timestamps). |
| Created (new resource) | 201 Created |
Typically
no
response
body
(or
a
minimal
representation
of
the
new
resource).
The
Location
header
is
set
to
the
new
resource’s
URI.
Headers
like
ETag
MUST
be
included
for
concurrency;
Link
headers
for
server-managed
metadata.
|
| Deleted (no content to return) | 204 No Content | No response body. Indicates the resource was deleted or the request succeeded and there’s nothing else to say. Servers MAY use 410 Gone for permanent deletions. |
| Bad Request (invalid input or constraints) | 400 Bad Request | Error details explaining what was wrong. Servers SHOULD use the standard format defined in [ RFC9457 ] for structured error responses, such as a JSON object with fields like "type", "title", "status", "detail", and "instance". |
LWS
container
representation
and
storage
description
resource
MUST
use
the
media
type
application/lws+json
.
While
LWS
container
representations
use
JSON-LD
conventions,
the
constraints
and
requirements
for
LWS
justify
the
use
of
a
specific
media
type.
Because
LWS
containers
can
be
considered
a
restricted
profile
of
JSON-LD,
implementations
SHOULD
consider
the
application/ld+json;
profile="https://www.w3.org/ns/lws/v1"
media
type
as
equivalent
to
application/lws+json
.
Servers
MUST
support
content
negotiation
for
container
representations.
The
response
payload
MUST
be
identical
regardless
of
the
requested
media
type
—
only
the
Content-Type
response
header
varies:
application/lws+json
,
the
server
MUST
respond
with
Content-Type:
application/lws+json
.
application/ld+json
,
the
server
MUST
respond
with
Content-Type:
application/ld+json
.
application/json
,
the
server
MUST
respond
with
Content-Type:
application/json
.
In
all
three
cases,
the
response
body
is
the
same
JSON-LD
document
conforming
to
the
LWS
container
vocabulary.
Servers
are
free
to
support
additional
media
types
(e.g.,
text/turtle
)
through
content
negotiation.
Container
representations
MUST
include
the
following
@context
value:
"@context": "https://www.w3.org/ns/lws/v1"
The normative JSON-LD context document defines the mapping between the short property names used in container representations and their full URIs in the LWS and related vocabularies. The context is defined as follows:
{
"@context": {
"@version": 1.1,
"@protected": true,
"lws": "https://www.w3.org/ns/lws#",
"as": "https://www.w3.org/ns/activitystreams#",
"schema": "https://schema.org/",
"xs": "http://www.w3.org/2001/XMLSchema#",
"id": "@id",
"type": "@type",
"Container": "lws:Container",
"DataResource": "lws:DataResource",
"items": "lws:items",
"totalItems": "as:totalItems",
"mediaType": "as:mediaType",
"size": {
"@id": "schema:size",
"@type": "xs:long"
},
"modified": {
"@id": "as:updated",
"@type": "xs:dateTime"
}
}
}
The
context
is
@protected
,
ensuring
that
the
term
definitions
cannot
be
overridden
by
other
contexts.
The LWS vocabulary defines the following types and properties used in container representations:
Types:
| Term | URI | Description |
|---|---|---|
Container
|
lws:Container
|
A resource that contains other resources |
DataResource
|
lws:DataResource
|
A data-bearing resource |
Properties:
| Term | URI | Description |
|---|---|---|
items
|
lws:items
|
The list of resources contained in a container |
totalItems
|
as:totalItems
|
The total number of contained resources |
mediaType
|
as:mediaType
|
The media type of a resource |
size
|
schema:size
|
The size of a resource in bytes |
modified
|
as:updated
|
The date-time a resource was last modified |
Define how resources are identified and addressed within the LWS Protocol, including URI schemes, resource naming conventions, and resolution mechanisms. This section may be moved within another section; e.g. Resource Access
this left intentionally blank
The features described in this section are being drafted to ground discussions and may be removed if there is:
this left intentionally blank
Define mechanisms for content negotiation based on profiles, allowing clients to request specific representations or views of resources (e.g., JSON-LD contexts, different RDF serializations, or application-specific profiles).
this left intentionally blank
Define notification mechanisms that allow clients to be informed of changes to resources, including subscription models, event formats, and delivery mechanisms.
this left intentionally blank
Define inbox resources with specific semantics within LWS, including message posting, retrieval, and management capabilities for asynchronous communication patterns.
this left intentionally blank
Describe considerations for ensuring LWS implementations can work across different platforms, environments, and storage backends while maintaining interoperability - and provide affordances to enable change in storage providers
this left intentionally blank
This section is non-normative.
Formal security considerations section covering threat models, security requirements, and implementation guidance for secure LWS deployments.
The recommendations described in Best Current Practice for OAuth 2.0 Security [ RFC9700 ] apply to this specification.
This section is non-normative.
Transport Layer Security (TLS) is an important mechanism to prevent against tampering, spoofing, and information disclosure. TLS-protected communication can be verified according to [ RFC6125 ]. Implementation security considerations can be found in "Recommendations for Secure Use of Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS)" [ RFC9325 ].
This section is non-normative.
Bearer tokens and digital credentials are vulnerable to theft and replay. Mitigations include using a reasonably short lifetime, binding tokens to a particular audience, and storing tokens securely.
aud
claim,
can
rely
on
that
binding
to
protect
against
token
replay.
Applications
that
handle
credentials
with
an
unrestricted
audience
need
to
be
careful
when
sending
these
credentials
to
other
entities,
especially
untrusted
authorization
servers.
If
a
credential
issuer
is
unable
to
restrict
the
audience
of
a
token,
clients
can
use
a
mechanism
such
as
OAuth
2.0
Token
Exchange
[
RFC8693
]
to
create
audience-constrained
credentials
before
interacting
with
an
authorization
server
in
a
different
security
domain.
localStorage
,
in
URLs,
or
in
logs,
that
token
is
more
susceptible
to
an
exfiltration
attack.
This section is non-normative.
Privacy implications of the LWS Protocol, including data minimization, user consent, and privacy-preserving implementation patterns.
Credentials carry information about users and agents. While digital signatures can protect against tampering, it is possible for clients or third parties to read the values inside an unencrypted credential.
As a result, credential issuers are encouraged to create tokens that contain only the information necessary for authentication or authorization, and to avoid including sensitive attributes unless required.
In general, it is an anti-pattern to write unencrypted credential data to a log. In cases where this is necessary, implementations can truncate or hash a credential to preserve the privacy of the credential subject.
When using pseudonymous identifiers in JWTs, a storage server may still be able to correlate requests from the same agent over time. To preserve user privacy in this case, a client application can request a batch issuance of JWTs where each JWT is used only one time. This does not prevent the storage server from using other information such as similarities in JWT content or originating IP address to correlate requests. When using pseudonymous identifiers, the authorization server will need to be careful not to issue the same identifier more than once.
This section is non-normative.
This specification adds the following value to the "Well-Known URIs" registry established by RFC 5785 [ RFC5785 ].
This
specification
registers
the
application/lws+json
media
type
specifically
for
identifying
documents
conforming
to
the
Linked
Web
Storage
container
format.
application/lws+json
media
type
are
required
to
conform
to
all
of
the
requirements
for
the
application/json
media
type
and
are
therefore
subject
to
the
same
encoding
considerations
specified
in
Section
11
of
[
RFC8259
].
Note that while the Linked Web Storage format uses JSON-LD conventions, there are a number of constraints and additional requirements for LWS implementations that justify the use of a specific media type.
Because
LWS
containers
can
be
considered
a
restricted
profile
of
JSON-LD,
implementations
SHOULD
consider
the
application/ld+json;
profile="https://www.w3.org/ns/lws/v1"
media
type
as
equivalent
to
application/lws+json
.
Referenced in:
Referenced in: