Copyright © IBM Corporation 2012. This document is available under the W3C Document License. See the W3C Intellectual Rights Notice and Legal Disclaimers for additional information.
A set of best practices and simple approach for a read-write Linked Data architecture, based on HTTP access to web resources that describe their state using RDF.
This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications can be found in the W3C technical reports index at http://www.w3.org/TR/.
This document is a part of the Linked Data Basic Profile Submission, which comprises two documents:
By publishing this document, W3C acknowledges that the Submitting Members have made a formal Submission request to W3C for discussion. Publication of this document by W3C indicates no endorsement of its content by W3C, nor that W3C has, is, or will be allocating any resources to the issues addressed by it. This document is not the product of a chartered W3C group, but is published as potential input to the W3C Process. A W3C Team Comment has been published in conjunction with this Member Submission. Publication of acknowledged Member Submissions at the W3C site is one of the benefits of W3C Membership. Please consult the requirements associated with Member Submissions of section 3.3 of the W3C Patent Policy. Please consult the complete list of acknowledged W3C Member Submissions.
This document describes the use of HTTP for accessing, updating, creating and deleting resources from servers that expose their resources as Linked Data. It provides some new rules as well as clarifications and extensions of the four rules of Linked Data [4Rules]
1. Use URIs as names for things
2. Use HTTP URIs so that people can look up those names
3. When someone looks up a URI, provide useful information, using the standards (RDF*, SPARQL)
4. Include links to other URIs. so that they can discover more things
The best practices and anti-patterns covered in this document are:
Resources - a summary of the HTTP and RDF standard techniques and best practices that you should use, and anti-patterns you should avoid, when constructing clients and servers that read and write linked data.
Containers - defines resources that allow new resources to be created using HTTP POST and existing resources to be found using HTTP GET.
Additionally, it is the intention of this document to enable additional rules and layered groupings of rules, such as additional profiles. The scope is intentionally narrow to provide a set of key rules for reading and writing Linked Data that most, if not all, other profiles will depend on and implementations will support.
Terminology is based on W3C's Architecture of the World Wide Web [WEBARCH] and Hyper-text Transfer Protocol [RFC2616]
Conformance is defined in accordance with the use of the words MUST, MUST NOT, SHOULD, SHOULD NOT, MAY and RECOMMENDED as described in RFC 2119 [RFC2119] .
Conformance statements on BPR representations apply to servers and clients that either create or generate representations that represent the state of a BPR.
			Sample resource representations are provided in text/turtle
			format [TURTLE].
		
Commonly used namespace prefixes:
@prefix dcterms: <http://purl.org/dc/terms/>. @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>. @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>. @prefix bp: <http://open-services.net/ns/basicProfile#>. @prefix xsd: <http://www.w3.org/2001/XMLSchema#>.
Basic Profile Resources (BPRs) are HTTP resources that conform to the simple patterns and conventions in this section. HTTP requests to access, modify, create or delete BPRs are accepted and processed by BPR servers. Most BPRs are domain-specific resources that contain data for an entity in some domain, which could be commercial, governmental, scientific, religious, or other.
Some of the rules defined in this document provide clarification and refinement of the base Linked Data rules [4Rules], others address additional needs.
The rules for Basic Profile Resources address basic questions such as:
The following sections define the rules and guidelines for use of BPRs.
rdf:type to
			represent the concept of type. The use of non-standard type
			predicates, as well as dcterms:type, is
			discouraged. [DC-RDF]
		rdf:type
			set explicitly.  This makes the representations much more useful to
			client applications that don’t support inferencing.
		| URI | Description | 
|---|---|
| http://www.w3.org/2001/XMLSchema#boolean | Boolean type as specified by XSD Boolean | 
| http://www.w3.org/2001/XMLSchema#date | Date type as specified by XSD date | 
| http://www.w3.org/2001/XMLSchema#dateTime | Date and Time type as specified by XSD dateTime | 
| http://www.w3.org/2001/XMLSchema#decimal | Decimal number type as specified by XSD Decimal | 
| http://www.w3.org/2001/XMLSchema#double | Double floating-point number type as specified by XSD Double | 
| http://www.w3.org/2001/XMLSchema#float | Floating-point number type as specified by XSD Float | 
| http://www.w3.org/2001/XMLSchema#integer | Integer number type as specified by XSD Integer | 
| http://www.w3.org/2001/XMLSchema#string | String type as specified by XSD String | 
| http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral | Literal XML value as specified by RDF | 
ETag
			header values.
		application/rdf+xml
			representation of the requested BPR.
		text/turtle
			representation of the requested BPR.
		rdf:type.
		rdf:type values
			of a given BPR may change over time.
		There are no additional requirements on HTTP POST for BPRs.
dcterms:modified
			and dcterms:creator that are never under
			client control - BPR servers MUST ignore any values of these
			properties that are provided by the client. Any BPR servers that wish
			to support a more sophisticated merge of data provided by the client
			with existing state stored on the server for a resource MUST use HTTP
			PATCH, not HTTP PUT.
		If-Match
			header and HTTP ETags to ensure it isn’t
			modifying a resource that has changed since the client last retrieved
			its representation. BPR servers SHOULD require the HTTP If-Match header and HTTP ETags
			to detect collisions. BPR servers MUST respond with status code 412
			(Condition Failed) if ETags fail to match if there are no other
			errors with the request. [RFC2616]
		rdf:type, datatypes of
			predicates and number of occurrences of predicates in triples, but
			servers SHOULD minimize those restrictions.  In other words, BPR
			servers need to enable simple modification of BPRs. Enforcement of
			more complex constraints will greatly restrict the types of clients
			that can modify resources. For some server applications, excessive
			constraints on modification of resources may be required.
		Allow”.
		rdf:type, datatypes of
			predicates and number of occurrences of predicates in triples – but
			server enforcement of detailed, domain-specific constraints will
			greatly restrict the types of clients who can update resources.
		
			This section summarizes some well-known RDF vocabularies that MUST be
			used in Basic Profile Resources wherever a resource needs to use a
			predicate whose meaning matches one of these. For example, if a BP
			resource has a description, and the application semantic of that
			description is compatible with dcterms:description,
			then dcterms:description MUST be used. If
			needed, additional application-specific predicates MAY be used. A
			specification for a domain that is based on BP may require one or
			more of these properties for a particular resource type. The Range
			column in the tables below identify the RECOMMENDED rdfs:range
			for the properties.
		
			URI: http://purl.org/dc/terms/
		
| Property | Range | Comment | 
| dcterms:contributor | dcterms:Agent | |
| dcterms:creator | dcterms:Agent | |
| dcterms:created | xsd:dateTime | |
| dcterms:description | rdf:XMLLiteral | Descriptive text about the resource represented as rich text in
						XHTML format. SHOULD include only content that is valid and suitable inside an XHTML <div>element. | 
| dcterms:identifier | rdfs:Literal | |
| dcterms:modified | xsd:dateTime | |
| dcterms:relation | rdfs:Resource | The HTTP URI of a related resource. This is the predicate to use when you don't know what else to use. If you know more specifically what sort of relationship it is, use a more specific predicate. | 
| dcterms:subject | rdfs:Resource | |
| dcterms:title | rdf:XMLLiteral | A name given to the resource. Represented as rich text in XHTML
						format. SHOULD include only content that is valid inside an XHTML <span>element. | 
			The predicate dcterms:type SHOULD NOT be
			used, instead use rdf:type. [DC-RDF].
		
			URI: http://www.w3.org/1999/02/22-rdf-syntax-ns#
		
| Property | Range | Comment | 
| rdf:type | rdfs:Class | he type or types of the resource | 
			URI: http://www.w3.org/2000/01/rdf-schema#
		
| Property | Range | Comment | 
| rdfs:member | rdfs:Resource | |
| rdfs:label | rdfs:Resource | Only use this in vocabulary documents, to define the name of the vocabulary term. | 
Many HTTP applications and sites have organizing concepts that partition the overall space of resources into smaller containers. Blog posts are grouped into blogs, wiki pages are grouped into wikis, and products are grouped into catalogs. Each resource created in the application or site is created within an instance of one of these container-like entities, and users can list the existing artifacts within one. Containers answer some basic questions, which are:
			This document defines the representation and behavior of containers
			that address these issues. The set of members of a container is
			defined by a set of triples in its representation (and state) called
			the membership triples. The membership triples of a container all
			have the same subject and predicate – the objects of the membership
			triples define the members of the container. The subject of the
			membership triples is called the membership subject and the predicate
			is called the membership predicate. In the simplest cases, the
			membership subject will be the BPC resource itself, but it does not
			have to be. The membership predicate is also variable and will often
			be a predicate from the server application vocabulary or the rdfs:member predicate.
		
This document includes a set of guidelines for using POST to create new resources and add them to the list of members of a container. This document also explains how to include information about each member in the container’s own representation and how to paginate the container representation if it gets too big.
The following illustrates a very simple container with only three members and some information about the container (the fact that it is a container and a brief title):
# The following is the representation of
#    http://example.org/container1
@prefix dcterms: <http://purl.org/dc/terms/>.
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
@prefix bp: <http://open-services.net/ns/basicProfile#>.
<http://example.org/container1>
   a bp:Container;
   dcterms:title "A very simple container";
   rdfs:member
      <http://example.org/container1/member1>,
      <http://example.org/container1/member2>,
      <http://example.org/container1/member3>.
This example is very straightforward - the
				membership predicate is rdfs:member and the membership subject is the container
				itself. A POST to this container will create a new resource
				and add it to the list of members by adding a new membership triple
				to the container.
Sometimes it is useful to use a subject
				other than the container itself as the membership subject and to use
				a predicate other than rdfs:member as the membership predicate, as illustrated
				below.
# The following is the representation of
#   http://example.org/netWorth/nw1/assetContainer
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
@prefix bp: <http://open-services.net/ns/basicProfile#>.
@prefix o: <http://example.org/ontology/>.
<http://example.org/netWorth/nw1/assetContainer>
   a bp:Container;
   bp:membershipSubject <http://example.org/netWorth/nw1>;
   bp:membershipPredicate o:asset.
<http://example.org/netWorth/nw1>
   a o:NetWorth;
   o:asset
      <http://example.org/netWorth/nw1/assetContainer/a1>,
      <http://example.org/netWorth/nw1/assetContainer/a2>.
			The essential structure of the container is
				the same, but in this example, the membership subject is not the
				container itself – it is a separate net worth resource. The
				membership predicate is o:asset – a predicate from the domain model. A POST to
				this container will create a new asset and add it to the list of
				members by adding a new membership triple to the container. You
				might wonder why we didn’t just make http://example.org/netWorth/nw1 a container and POST
				the new asset directly there. That would be a fine design if http://example.org/netWorth/nw1 had only assets, but if it has separate
				predicates for assets and liabilities, that design will not work
				because it is unspecified to which predicate the POST should add a
				membership triple. Having separate http://example.org/netWorth/nw1/assetContainer and http://example.org/netWorth/nw1/liabilityContainer container resources allows both assets and
				liabilities to be created.
		
In this example, clients cannot simply guess which resource is the membership subject and which predicate is the membership predicate, so the example includes this information in triples whose subject is the BPC resource itself.
In many – perhaps most – applications involving containers, it is desirable for the client to be able to get information about each container member without having to do a GET on each one. BPC allows servers to include this information directly in the representation of the container. The server decides the amount of data about each member that is provided. Some common strategies include providing a fixed number of standard properties, or providing the entire RDF representation of each member resource, or providing nothing. The server application domain and its use-cases will determine how much information is required.
Continuing on from the net worth example, there will be additional triples for the member resources (assets) in the representation:
# The following is the representation of
#	 http://example.org/netWorth/nw1/assetContainer
@prefix dcterms: <http://purl.org/dc/terms/>.
@prefix rdfs:    <http://www.w3.org/2000/01/rdf-schema#>.
@prefix bp:      <http://open-services.net/ns/basicProfile#>.
@prefix o:       <http://example.org/ontology/>.
<http://example.org/netWorth/nw1/assetContainer>
   a bp:Container;
   dcterms:title "The assets of JohnZSmith";
   bp:membershipSubject <http://example.org/netWorth/nw1>;
   bp:membershipPredicate o:asset.
<http://example.org/netWorth/nw1>
   a o:NetWorth;
   o:asset
      <http://example.org/netWorth/nw1/assetContainer/a1>,
      <http://example.org/netWorth/nw1/assetContainer/a3>,
      <http://example.org/netWorth/nw1/assetContainer/a2>.
<http://example.org/netWorth/nw1/assetContainer/a1>
   a o:Stock;
   o:value 10000.
<http://example.org/netWorth/nw1/assetContainer/a2>
   a o:Bond;
   o:value 20000.
<http://example.org/netWorth/nw1/assetContainer/a3>
   a o:RealEstateHolding;
   o:value 300000.
The representation of a container that has many members will be large. There are several important cases where clients need to access only the non-member properties of the container. Since retrieving the whole container representation to get this information may be onerous for clients and cause unnecessary overhead on servers, it is desired to define a way to retrieve only the non-member property values. Defining for each BPC a corresponding resource, called the “non-member resource”, whose state is a subset of the state of the container, does this.
The example listed here only show a simple case where only a few simple non-member properties are retrieved. In real world situations more complex cases are likely, such as those that add other predicates to containers, for example providing validation information and associating SPARQL endpoints.
			Here is an example requesting the non-member properties of a
			container identified by the URL http://example.org/container1
			and adding the query string ?non-member-properties :
		
Request:
GET /container1?non-member-properties HTTP/1.1 Host: example.org Accept: text/turtle; charset=UTF-8
Response:
HTTP/1.1 200 OK Content-Type: text/turtle; chartset=UTF-8 ETag: "_87e52ce291112" Content-Length: 325 @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>. @prefix dcterms: <http://purl.org/dc/terms/>. @prefix bp: <http://open-services.net/ns/basicProfile#>. <http://example.org/container1> a bp:Container; dcterms:title "A Basic Profile Container of Acme Resources"; bp:membershipPredicate rdfs:member; dcterms:publisher <http://acme.com/>.
It sometimes happens that a container is too large to reasonably transmit its representation in a single HTTP response. This will be especially true if the container representation includes many triples from the representations of its members. A client may anticipate that a container will be too large - for example, a client tool that accesses defects may assume that an individual defect will usually be of sufficiently constrained size that it makes sense to request all of it at once, but that the container of all the defects ever created will typically be too big. Alternatively, a server may recognize that a container that has been requested is too big to return in a single message.
			To address this problem, BPCs may support a technique called Paging.  Paging can be achieved with a
			simple RDF pattern. For each container resource, <containerURL>, we define a new
			resource <containerURL>?firstPage.
			The triples in the representation of <containerURL>?firstPage
			are a subset of the triples in <containerURL>
			- same subject, predicate and object.
		
BPC servers may respond to requests for a container by redirecting the client to the first page resource – using a 303 “See Other” redirect to the actual URL for the page resource.
			Continuing on from the member information from the JohnZSmith net
			worth example, we’ll split the response across two pages.  The client
			requests the first page as http://example.org/netWorth/nw1/assetContainer?firstPage:
		
# The following is the representation of # http://example.org/netWorth/nw1/assetContainer?firstPage @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>. @prefix dcterms: <http://purl.org/dc/terms/>. @prefix bp: <http://open-services.net/ns/basicProfile#>. @prefix o: <http://example.org/ontology/>. <http://example.org/netWorth/nw1/assetContainer> a bp:Container; dcterms:title "The assets of JohnZSmith"; bp:membershipSubject <http://example.org/netWorth/nw1>; bp:membershipPredicate o:asset. <http://example.org/netWorth/nw1/assetContainer?firstPage> a bp:Page; bp:pageOf <http://example.org/netWorth/nw1/assetContainer>; bp:nextPage <http://example.org/netWorth/nw1/assetContainer?p=2>. <http://example.org/netWorth/nw1> a o:NetWorth; o:asset <http://example.org/netWorth/nw1/assetContainer/a1>, <http://example.org/netWorth/nw1/assetContainer/a4>, <http://example.org/netWorth/nw1/assetContainer/a3>, <http://example.org/netWorth/nw1/assetContainer/a2>. <http://example.org/netWorth/nw1/assetContainer/a1> a o:Stock; o:value 100.00. <http://example.org/netWorth/nw1/assetContainer/a2> a o:Cash; o:value 50.00. # server initially supplied no data for a3 and a4 in this response
The following example is the result of retrieving the representation for the next page:
# The following is the representation of
#  http://example.org/netWorth/nw1/assetContainer?p=2
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
@prefix dcterms: <http://purl.org/dc/terms/>.
@prefix bp: <http://open-services.net/ns/basicProfile#>.
@prefix o: <http://example.org/ontology/>.
<http://example.org/netWorth/nw1/assetContainer>
   a bp:Container;
   dcterms:title "The assets of JohnZSmith";
   bp:membershipSubject <http://example.org/netWorth/nw1>;
   bp:membershipPredicate o:asset.
<http://example.org/netWorth/nw1/assetContainer?p=2>
   a bp:Page;
   bp:pageOf <http://example.org/netWorth/nw1/assetContainer>;
   bp:nextPage rdf:nil.
<http://example.org/netWorth/nw1>
   a o:NetWorth;
   o:asset 
      <http://example.org/netWorth/nw1/assetContainer/a5>.
<http://example.org/netWorth/nw1/assetContainer/a5>
   a o:Stock;
   dcterms:title "Big Co.";
   o:value 200.02.
			In this example, there is only one member in the container in the
			final page.  To indicate this is the last page, a value of rdf:nil is used for the bp:nextPage
			predicate of the page resource.
		
BPC guarantees that any and all the triples about the members will be on the same page as the membership triple for the member.
			There are many cases where an ordering of the members of the
			container is important. BPC does not provide any particular support
			for server ordering of members in containers, because any client can
			order the members in any way it chooses based on the value of any
			available property of the members. In the example below, the value of
			the o:value predicate is present for each
			member, so the client can easily order the members according to the
			value of that property. In this way, BPC avoids the use of RDF
			constructs like Seq and List for expressing order.
		
			Order only becomes important for BPC servers when containers are
			paginated. If the server does not respect ordering when constructing
			pages, the client is forced to retrieve all pages before
			sorting the members, which would defeat the purpose of pagination. In
			cases where ordering is important, a BPC server exposes all the
			members on a page with a higher sort order than all members on the
			previous page and lower sort order than all the members on the next
			page. The BPC specification provides a predicate - bp:containerSortPredicates
			- that the server may use to communicate to the client which
			predicates were used for page ordering. Multiple predicate values may
			have been used for sorting, so the value of this predicate is an
			ordered list.
		
Here is an example container described previously, with representation for ordering of the assets:
# The following is the ordered representation of
#   http://example.org/netWorth/nw1/assetContainer
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
@prefix dcterms: <http://purl.org/dc/terms/>.
@prefix bp: <http://open-services.net/ns/basicProfile#>.
@prefix o: <http://example.org/ontology/>.
<http://example.org/netWorth/nw1/assetContainer>
   a bp:Container;
   dcterms:title "The assets of JohnZSmith";
   bp:membershipSubject <http://example.org/netWorth/nw1>;
   bp:membershipPredicate o:asset.
<http://example.org/netWorth/nw1/assetContainer?firstPage>
   a bp:Page;
   bp:pageOf <http://example.org/netWorth/nw1/assetContainer>;
   bp:containerSortPredicates (o:value).
<http://example.org/netWorth/nw1>
   a o:NetWorth;
   o:asset
      <http://example.org/netWorth/nw1/assetContainer/a1>,
      <http://example.org/netWorth/nw1/assetContainer/a3>,
      <http://example.org/netWorth/nw1/assetContainer/a2>.
<http://example.org/netWorth/nw1/assetContainer/a1>
   a o:Stock;
   o:value 100.00.
<http://example.org/netWorth/nw1/assetContainer/a2>
   a o:Cash;
   o:value 50.00.
<http://example.org/netWorth/nw1/assetContainer/a3>
   a o:RealEstateHolding;
   o:value 300000.
			As you can see by the addition of the bp:containerSortPredicates 
			predicate, the o:value predicate is used
			to define the ordering of the results.  It is up to the domain model
			and server to determine the appropriate predicate to indicate the
			resource’s order within a page, and up to the client receiving this 
			representation to use that order in whatever way is appropriate, for 
			example to sort the data prior to presentation on a user interface.
		
rdfs:member predicate.
		bp:membershipSubject
			predicate that indicates the subject of the membership triples.
		rdfs:member, a BPC MUST contain one triple for the bp:membershipPredicate
			predicate that indicates the predicate of the membership triple.
		rdf:type
			of bp:Container, but it MAY have additional
			rdf:types.
		rdf:Bag,
			rdf:Seq and rdf:List.
		non-member-properties" on the query
			component of the BPC URL.  For example, if there is a BPC URL <containerURL>, the URL to request the
			non-membership properties would be <containerURL>?non-member-properties.
			 See section 5.1.2 Retrieving Non-member Properties for
			additional details. A BPC server that does not support a request to
			retrieve non-member resource properties via a Request-URI of “<containerURL>?non-member-properties”,
			MUST return a HTTP status code 404 (Not Found).
		<containerURL>”,
			the Request-URI of “<containerURL>?firstPage”, MUST return a HTTP status code 404 (Not
			Found).
		firstPage”
			on the query component of the BPC URL. For example, if there is a BPC
			URL <containerURL>, the URL to request
			the first page would be <containerURL>?firstPage.
			The representation for any page, including the first, will include
			the URL for the next page. See section 5.1.3 titled “Paging” for additional details.
		firstPage”
			query component of a request URL). This is also known as
			server-initiated paging. See section  5.1.3 Paging for
			additional details.
		rdf:type and object is bp:Page;
			it also SHOULD have 1 triple to indicate the container it is paging,
			whose  subject is the URL of the page, predicate is bp:pageOf,
			and object is the URL of the BPC.
		bp:nextPage and
			object being the URL for the subsequent page.
		bp:nextPage and object being rdf:nil.
		bp:containerSortPredicates
			predicate whose subject is that of the page and object is a list of
			BPC ordinal predicates.  The default ordering is ascending. The only
			ordinal predicate literal data types supported are those as defined
			by SPARQL SELECT’s ORDER BY clause [SPARQL].
		bp:containerSortPredicates’,
			the predicate used to indicate ordering, MUST NOT change between
			subsequent pages. If it does, ordering among members of a container
			across pages is undefined. See section 5.1.4 Ordering for
			additional details.
		The Basic Profile does not define how clients discover BPCs.
Location
			header set to the new resource’s URL.
		application/rdf+xml.
		text/turtle.
		rdf:type, datatypes of
			predicates and number of occurrences of predicates in triples - but
			server enforcement of detailed, domain-specific constraints will
			greatly restrict the types of clients that can create resources and
			therefore discouraged.
		<containerURL>?non-member-properties, which
			MAY exclude server managed properties such as bp:membershipSubject and bp:membershipPredicate.
		There are no additional requirements on HTTP HEAD.
Additional Contributors:
Arthur Ryman (IBM), Ian Green (IBM), Barbara McKee (IBM), Sally Hehir (IBM)