Access points

In this guide, we’ll use different scenarios to go through the REST API methods (detailing the different headers and basic request bodies) you can use to interact with the Carbon LDP platform when creating or modifying Access Points.

We have created a Postman Collection with all the examples featured in this documentation. The examples for this section are contained in the access-points folder.

Relationships in Carbon LDP

Of course, the power of link data relies on the linking of resources. Therefore, a Linked Data Platform must be capable of handling these links or relations between resources in an ordered manner. To achieve this, Carbon LDP divides the relationships into two kinds:

  • Parent-child relation (hard link)
  • Membership relation (soft link)

The more you know…

Links in Carbon LDP are not limited to your application’s domain, therefore you can use readily existing models and public data that form the Semantic Web to enrich your application’s content.

 

To get a better insight into the specifics of relationships in Carbon LDP, see Relationships in Carbon LDP.

For any Carbon LDP document, if you don’t modify the ldp:hasMemberRelation property, a set of member documents will be maintained in the property ldp:members.

Imagine you created a document that represents a project your company is developing called “Project X”. Now, you want to know which employees will be a part of that project, so you use a soft link to relate them and add them as ldp:members in your “Project X” document. As the project begins you want to link it to different tasks that are standardized in your company. If you add the tasks in the same ldp:members property, you would have an array of documents some of which represent a person and others a task.

To prevent this from happening, while allowing you to maintain multiple lists of members per document, Carbon LDP uses Access Points.

What is an Access Point?

Access points are special documents, whose purpose is to maintain a list of members for another document. Documents can have an unlimited number of access points, removing the limitation of lists of members they can maintain. Always remember that access points work as member managers for documents. Therefore, they do not contain member documents themselves.

Furthermore, just as regular documents, access points can maintain unlimited properties in the form of values, links or fragments. However, bear in mind that the most important properties to maintain in an access point are the ones that manage membership relations: ldp:membershipResource, ldp:hasMemberRelation, and ldp:isMemberOfRelation.

The more you know…

A Carbon LDP Access Point can be regarded as equivalent to an LDP Direct Container.

 

To get a better insight into the basic parts that conform a Carbon LDP Access Point, see Access Point model.

Now let’s see how you can interact with access points in Carbon LDP through REST methods.

Create an Access Point

Creating an access point is similar to creating a document. However, there are certain differences you should pay attention to.

First, when creating an access point you should focus on configuring the properties used to manage relationships within documents:

  • ldp:hasMemberRelation
  • ldp:membershipResource
  • ldp:isMemberOfRelation

Beware that once an access point has been created these properties cannot be modified. Therefore, pay close attention to them when creating your access point and be sure that they have been correctly configured.

Also, we’ll need some test documents to experiment relating them. You can use the requests stored in our Postman Collection in the access-point folder.

Let’s create a “project-x” document with the following body:

(This document will work as our container document in this example.)

{
    "@context": {
        "ex": { "@id": "http://example.org/ns#" },
        "xsd": { "@id": "http://www.w3.org/2001/XMLSchema#" },
        "ex:name": {
            "@type": "xsd:string"
        }
    },
    "@id": "",
    "@type": [ "ex:Project" ],
    "ex:name": "Project X"
}
@prefix ex:  <http://example.org/ns#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

<>{
    <>
        a ex:Project;
        ex:name "Project X" .
}

Let’s also create a “john-doe” employee that will take part of the Project X with the following body:

(This document will work as our member document in this example.)

{
    "@context": {
        "ex": { "@id": "http://example.org/ns#" },
        "xsd": { "@id": "http://www.w3.org/2001/XMLSchema#" },
        "ex:name": {
            "@type": "xsd:string"
        }
    },
    "@id": "",
    "@type": [ "ex:Person" ],
    "ex:name": "John Doe"
}
@prefix ex:  <http://example.org/ns#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

<>{
    <>
        a ex:Person;
        ex:name "John Doe" .
}

If you can’t recall how to create a Carbon LDP document, see Create a Document.

Issue a POST request through HTTP in order to create our first basic access point.

Create the POST request

Create the following HTTP request to create a basic access point.

POST http://localhost:8083/project-x/

HTTP Header Value Required/Optional
Content-Type application/ld+json
or
application/trig
Required
Prefer http://www.w3.org/ns/ldp#Container; rel=interaction-model Optional
Accept application/ld+json
or
application/trig
Optional (default is text/turtle)
Slug participants Optional
{
    "@context": {
        "c": { "@id": "https://carbonldp.com/ns/v1/platform#" },
        "ex": { "@id": "http://example.org/ns#" },
        "ldp": { "@id": "http://www.w3.org/ns/ldp#" }
    },
    "@id": "",
    "@type": [ "c:AccessPoint" ],
    "ldp:hasMemberRelation": {
        "@id": "ex:participant"
    }
}
@prefix c: <https://carbonldp.com/ns/v1/platform#> .
@prefix ex: <http://example.org/ns#> .
@prefix ldp: <http://www.w3.org/ns/ldp#> .

<>{
    <>
        a c:AccessPoint ;
        ldp:hasMemberRelation ex:participant .
}

Review the POST request

It is important that before issuing this request, you understand all its parts. Next, you’ll get more information about each part in the request.

Content-Type

Since the request method is POST it requires a body. Therefore, the Content-Type HTTP header tells the platform what kind of content to expect in the body of the request. In the examples we use either JSON-LD (application/ld+json) or TriG (application/trig) RDF Dataset Languages because they are brief and also support named graphs. Whether you decide to use JSON-LD or the TriG language, you’ll find that each one provides their own advantages. If you’re familiar with JSON objects and JavaScript you might find JSON-LD easier to understand. On the other hand, you might find TriG a bit less verbose and easier to read when it comes to identifying specific RDF structures.

Note that Carbon LDP also supports other content types for RDF such as:

  • Turtle: text/turtle
  • RDF XML: application/rdf+xml
Prefer

The Prefer header uses a link relation to specify the interaction model of the target resource. When you issue a request, you are targeting a specific resource where your request will be applied; in this case the project-x/ resource. By specifying its interaction model, we’re defining how we want this resource to behave.

In Carbon LDP resources can behave as either Documents (RDFSource) or Containers. When you’re creating an access point, you want the target resource to behave as a Container. Because we’re adding an access point resource to the document, we need it to behave like a container, as opposed to a RDFSource. Carbon LDP supports the following interaction model values for the Prefer header:

  • http://www.w3.org/ns/ldp#Container; rel=interaction-model
  • http://www.w3.org/ns/ldp#RDFSource; rel=interaction-model

ldp:Container is the default interaction model used by the platform. Therefore, the inclusion of this header in the request is optional.

Accept

Once your request gets executed by the platform, you might get a response body from the Carbon LDP server. In this case we recommend you define the Accept header to receive this body in a known format; it’s simpler to be consistent and use the same format used to send the request body. If this header is not defined Carbon LDP will send a response in Turtle (text/turtle) by default. Note that Carbon LDP can send response bodies in other formats, such as:

  • JSON-LD: application/ld+json
  • TriG: application/trig
  • RDF XML: application/rdf+xml
  • Binary: application/x-binary-rdf
  • N-Triples: application/n-triples
  • N3: text/n3, text/rdf+n3
  • Trix: application/trix
  • N-Quads: application/n-quads, text/x-nquads, text/nquads
  • JSON-RDF: application/rdf+json
Slug

The Slug header is intended to give the server a hint about how to mint a new URI for the resource being created. If a slug is not provided, Carbon LDP will generate a random number when minting the URI. In this case, however, we’re specifying a preference to use participants. Therefore, if it is available for use, the server will mint the following URI:

http://localhost:8083/project-x/participants/

If the URI you’re trying to create already exists, the platform will respond with a 409 Conflict HTTP status code. Keep in mind that URIs are unique identifiers, therefore, the platform will not allow you to create a duplicate resource.

Body

The body of the request is a graph of triples written in the RDF syntax matching the Content-Type header.

Please note that the platform automatically configures the property ldp:membershipResource, therefore when you add member documents to the recently created access point they will be added in the document you targeted in your request.

In this case, we are stating that the resource we are creating has a c:AccessPoint type. This will allow the platform to add other types access points have, as well as configuring the special properties we mentioned at the begining of this section.

Also, we are defining the ldp:hasMemberRelation property (as ex:participant) so that the member documents are added to the container document using that property.

This request body is the simplest graph you can use to configure an access point in Carbon LDP. However, you can include other properties to achieve more complex configurations.

For example, this request body will only create a one way relation between the container document and the members added to it. If you look at the member document you will not find any reference to the container document. To achieve a bilateral relation you must also configure in your access point the ldp:isMemberOfRelation property with the property where the container document will be referenced in the member document.

Also, since this case exemplifies the simplest request body required to create an access point, only the properties that manage relationships are mentioned. However, remember that access points are just a special type of document, therefore, they can contain as many additional properties as you desire.

If there is anything from the request body you don’t understand you can check the JSON-LD or TriG W3C specifications, which Carbon LDP complies to.

Issue the POST request

A successful request will result in HTTP status code 201 Created.

HTTP Header Value
ETag “342258740”
Location http://localhost:8083/project-x/participants/

As part of the response headers:

  • The ETag header will confirm the time of the access point’s creation.
  • The Location header will provide the server minted URI for the new access point.

Member Management

Once you have created an access point, Carbon LDP let’s you add and remove members to it. It is important that you remember that these changes will be reflected in the container document (ldp:membershipResource in the access point). Within this section we will review examples on how to either add or remove members from your container documents using access points. To achieve this, Carbon LDP implements two methods that execute via REST requests in the platform:

  • https://carbonldp.com/ns/v1/platform#AddMemberAction
  • https://carbonldp.com/ns/v1/platform#RemoveMemberAction

Let’s see how you can access both of these methods through REST requests.

Add a member

Following our previous example where we created an access point, now we will add a member to our document. In this case, we mentioned we want to use the access point to link the employees participating in a project with the document that represents said project. So, let’s add the employee “John Doe” as a member of the document “Project X” in the ex:participant property.

When adding a member you are modifying the access point in a particular way. Therefore, this is done through a PUT request. Issue a PUT request through HTTP in order to add a member to our access point.

Create the PUT request

Create the following HTTP request to add a member to the project-x/participants/ access point.

PUT http://localhost:8083/project-x/participants/

HTTP Header Value Required/Optional
Content-Type application/ld+json
or
application/trig
Required
Prefer http://www.w3.org/ns/ldp#Container; rel=interaction-model Required
Accept application/ld+json
or
application/trig
Optional (default is text/turtle)
{
    "@context": {
        "@base": "http://localhost:8083/",
        "c": { "@id": "https://carbonldp.com/ns/v1/platform#" }
    },
    "@id": "_:b0",
    "@type": [ "c:AddMemberAction" ],
    "c:targetMember": {
        "@id": "john-doe/"
    }
}
@base <http://localhost:8083/> .
@prefix c: <https://carbonldp.com/ns/v1/platform#> .
@prefix ex: <http://example.org/ns#> .

_:b0
    a c:AddMemberAction ;
    c:targetMember <john-doe/> .

Review the PUT request

It is important that before issuing this request, you understand all its parts. Next, you’ll get more information about each part in the request.

Content-Type

Since the request method is PUT it requires a body. Therefore, the Content-Type HTTP header tells the platform what kind of content to expect in the body of the request. In the examples we use either JSON-LD (application/ld+json) or TriG (application/trig) RDF Dataset Languages because they are brief and also support named graphs. Whether you decide to use JSON-LD or the TriG language, you’ll find that each one provides their own advantages. If you’re familiar with JSON objects and JavaScript you might find JSON-LD easier to understand. On the other hand, you might find TriG a bit less verbose and easier to read when it comes to identifying specific RDF structures.

Note that Carbon LDP also supports other content types for RDF such as:

  • Turtle: text/turtle
  • RDF XML: application/rdf+xml
Prefer

The Prefer header uses a link relation to specify the interaction model of the target resource. When you issue a request, you are targeting a specific resource where your request will be applied; in this case the participants/ resource. By specifying its interaction model, we’re defining how we want this resource to behave.

In Carbon LDP resources can behave as either Documents (RDFSource) or Containers. When you’re managing a container’s members through an access point, you want the target resource to interact as a Container. Because we’re adding a member resource to the container, we need it to behave like a container as opposed to an RDFSource. Carbon LDP supports the following interaction model values for the Prefer header:

  • http://www.w3.org/ns/ldp#Container; rel=interaction-model
  • http://www.w3.org/ns/ldp#RDFSource; rel=interaction-model
Accept

Once your request gets executed by the platform, you might get a response body from the Carbon LDP server. In this case we recommend you define the Accept header to receive this body in a known format; it’s simpler to be consistent and use the same format used to send the request body. If this header is not defined Carbon LDP will send a response in Turtle (text/turtle) by default. Note that Carbon LDP can send response bodies in other formats, such as:

  • JSON-LD: application/ld+json
  • TriG: application/trig
  • RDF XML: application/rdf+xml
  • Binary: application/x-binary-rdf
  • N-Triples: application/n-triples
  • N3: text/n3, text/rdf+n3
  • Trix: application/trix
  • N-Quads: application/n-quads, text/x-nquads, text/nquads
  • JSON-RDF: application/rdf+json
Body

The body of the request is a graph of at least one BNode written in the RDF syntax matching the Content-Type header.

In this case we are defining the BNode’s type as c:AddMemberAction which is the method we want the platform to perform. Furthermore, the BNode you define should also include at least one c:targetMember with the URI of the document you want to add as a member. In this case, http://localhost:8083/john-doe/.

If you want to add multiple documents as members in a single request you can do this by adding multiple c:targetMember properties.

If there is anything from the request body you don’t understand you can check the JSON-LD or TriG W3C specifications, which Carbon LDP complies to.

Issue the PUT request

A successful request will result in HTTP status code 204 No Content.

HTTP Header Value
ETag “342258740”

As part of the response headers:

  • The ETag header will confirm the member’s addition to the document the access point belongs to.

Remove a member

Following our previous example where we added a member through our access point, now we will remove it from our document. In this case, we will remove the employee “John Doe” as a member of the document “Project X” in the ex:participant property.

When removing a member you are modifying the access point in a particular way. Therefore, this is done through a DELETE request. Issue a DELETE request through HTTP in order to remove a member from our access point.

Create the DELETE request

Create the following HTTP request to remove a member that has been added through the project-x/participants/ access point.

DELETE http://localhost:8083/project-x/participants/

HTTP Header Value Required/Optional
Content-Type application/ld+json
or
application/trig
Required
Prefer http://www.w3.org/ns/ldp#Container; rel=interaction-model Required
Prefer include=https://carbonldp.com/ns/v1/platform#PreferSelectedMembershipTriples Required
Prefer omit=https://carbonldp.com/ns/v1/platform#PreferMembershipTriples Required
Accept application/ld+json
or
application/trig
Optional (default is text/turtle)
{
    "@context": {
        "@base": "http://localhost:8083/",
        "c": { "@id": "https://carbonldp.com/ns/v1/platform#" }
    },
    "@id": "_:b0",
    "@type": [ "c:RemoveMemberAction" ],
    "c:targetMember": {
        "@id": "john-doe/"
    }
}
@base <http://localhost:8083/> .
@prefix c: <https://carbonldp.com/ns/v1/platform#> .
@prefix ex: <http://example.org/ns#> .

_:b0
    a c:RemoveMemberAction ;
    c:targetMember <john-doe/> .

Review the DELETE request

It is important that before issuing this request, you understand all its parts. Next, you’ll get more information about each part in the request.

Content-Type

Since the request method is DELETE it can include a body. Therefore, the Content-Type HTTP header tells the platform what kind of content to expect in the body of the request. In the examples we use either JSON-LD (application/ld+json) or TriG (application/trig) RDF Dataset Languages because they are brief and also support named graphs. Whether you decide to use JSON-LD or the TriG language, you’ll find that each one provides their own advantages. If you’re familiar with JSON objects and JavaScript you might find JSON-LD easier to understand. On the other hand, you might find TriG a bit less verbose and easier to read when it comes to identifying specific RDF structures.

Note that Carbon LDP also supports other content types for RDF such as:

  • Turtle: text/turtle
  • RDF XML: application/rdf+xml
Prefer

The Prefer header uses a link relation to specify the interaction model of the target resource. When you issue a request, you are targeting a specific resource where your request will be applied; in this case the participants/ resource. By specifying its interaction model, we’re defining how we want this resource to behave.

In Carbon LDP resources can behave as either Documents (RDFSource) or Containers. When you’re managing a container’s members through an access point, you want the target resource to interact as a Container.Because we’re removing a member resource from the container, we need it to behave like a container as opposed to an RDFSource. Carbon LDP supports the following interaction model values for the Prefer header:

  • http://www.w3.org/ns/ldp#Container; rel=interaction-model
  • http://www.w3.org/ns/ldp#RDFSource; rel=interaction-model

Also, Carbon LDP allows the removal some member documents, without affecting all the members managed by an access point. To specify that we only want to affect certain members we need to include the following parameters:

  • include=https://carbonldp.com/ns/v1/platform#PreferSelectedMembershipTriples
  • omit=https://carbonldp.com/ns/v1/platform#PreferMembershipTriples

If you are not sure what these preferences mean you can read more about them here.

Accept

Once your request gets executed by the platform, you might get a response body from the Carbon LDP server. In this case we recommend you define the Accept header to receive this body in a known format; it’s simpler to be consistent and use the same format used to send the request body. If this header is not defined Carbon LDP will send a response in Turtle (text/turtle) by default. Note that Carbon LDP can send response bodies in other formats, such as:

  • JSON-LD: application/ld+json
  • TriG: application/trig
  • RDF XML: application/rdf+xml
  • Binary: application/x-binary-rdf
  • N-Triples: application/n-triples
  • N3: text/n3, text/rdf+n3
  • Trix: application/trix
  • N-Quads: application/n-quads, text/x-nquads, text/nquads
  • JSON-RDF: application/rdf+json
Body

The body of the request is a graph of at least one BNode written in the RDF syntax matching the Content-Type header.

In this case we are defining the BNode’s type as c:RemoveMemberAction which is the method we want the platform to perform. Furthermore, the BNode you define should also include at least one c:targetMember with the URI of the document you want to remove as a member. In this case, http://localhost:8083/john-doe/.

If you want to remove multiple documents as members in a single request you can do this by adding multiple c:targetMember properties.

If there is anything from the request body you don’t understand you can check the JSON-LD or TriG W3C specifications, which Carbon LDP complies to.

Issue the DELETE request

A successful request will result in HTTP status code 204 No Content.

HTTP Header Value
Date Thu, 21 Dec 2017 23:45:00 GMT

As part of the response headers:

  • The Date header will confirm the date and time when the member got removed from the document the access point belongs to.

Remove all members

The case can present itself where you have added multiple members through an access point and you might need to remove them all. While you could list them all in your request body as target members of the c:RemoveMemberAction method, this is not a scalable approach. Let’s see how you could achieve this in a simpler manner.

When removing a member you are modifying the access point in a particular way. Therefore, this is done through a DELETE request. Issue a DELETE request through HTTP in order to remove a member from our access point.

Create the DELETE request

Create the following HTTP request to remove all the members that have been added through the project-x/participants/ access point.

DELETE http://localhost:8083/project-x/participants/

HTTP Header Value Required/Optional
Prefer http://www.w3.org/ns/ldp#Container; rel=interaction-model Required
Prefer include=https://carbonldp.com/ns/v1/platform#PreferMembershipTriples Required
Prefer omit=https://carbonldp.com/ns/v1/platform#PreferSelectedMembershipTriples Optional
If-Match “1159301253” (latest ETag obtained from the resource) Optional
Accept application/ld+json
or
application/trig
Optional (default is text/turtle)

Review the DELETE request

It is important that before issuing this request, you understand all its parts. Next, you’ll get more information about each part in the request.

Prefer

The Prefer header uses a link relation to specify the interaction model of the target resource. When you issue a request, you are targeting a specific resource where your request will be applied; in this case the participants/ resource. By specifying its interaction model, we’re defining how we want this resource to behave.

In Carbon LDP resources can behave as either Documents (RDFSource) or Containers. When you’re managing a container’s members through an access point, you want the target resource to interact as a Container. Because we’re removing a member resource from the container, we need it to behave like a container as opposed to an RDFSource. Carbon LDP supports the following interaction model values for the Prefer header:

  • http://www.w3.org/ns/ldp#Container; rel=interaction-model
  • http://www.w3.org/ns/ldp#RDFSource; rel=interaction-model

Also, Carbon LDP allows the removal of all the members managed by an access point in a single request. To specify that we want to affect all the members we need to include the following parameter:

  • include=https://carbonldp.com/ns/v1/platform#PreferMembershipTriples
  • omit=https://carbonldp.com/ns/v1/platform#PreferSelectedMembershipTriples

If you are not sure what these preferences mean you can read more about them here.

If-Match

The If-Match header allows you to ensure that the data you are modifying is accurate before changing anything within your document; this is necessary to maintain data consistency. Your application might not be the only one modifying the resource, so the platform needs a way to assure that no data is overridden when executing a request that modifies the resource.

To achieve this Carbon LDP uses ETags, therefore it only allows changes that won’t override each other. In case the ETags do not match, you should first execute a GET request, update your request with the new ETag, and retry it.

Accept

Once your request gets executed by the platform, you might get a response body from the Carbon LDP server. In this case we recommend you define the Accept header to receive this body in a known format; it’s simpler to be consistent and use the same format used to send the request body. If this header is not defined Carbon LDP will send a response in Turtle (text/turtle) by default. Note that Carbon LDP can send response bodies in other formats, such as:

  • JSON-LD: application/ld+json
  • TriG: application/trig
  • RDF XML: application/rdf+xml
  • Binary: application/x-binary-rdf
  • N-Triples: application/n-triples
  • N3: text/n3, text/rdf+n3
  • Trix: application/trix
  • N-Quads: application/n-quads, text/x-nquads, text/nquads
  • JSON-RDF: application/rdf+json

Issue the DELETE request

A successful request will result in HTTP status code 204 No Content.

HTTP Header Value
Date Thu, 21 Dec 2017 23:47:00 GMT

As part of the response headers:

  • The Date header will confirm the date and time when the members got removed from the container document the access point belongs to.

Please note that when issuing this request you will not delete the access point, and you can still manage members through it.

Retrieve an Access Point

Retrieving an access point can be useful when you need to review the properties that manage relationships between documents. Nevertheless, remember that the members the access point manages are contained within the container document that the property ldp:membershipResource indicates. Therefore, when reading an access point do not expect to find the members the access point has added to a document.

Retrieving an access point is the same process as retrieving a regular document. If you can’t recall how to retrieve a Carbon LDP document, see Retrieve a Document.

Delete an Access Point

Deleting an access point will not cause any effects to the members added or removed through the access point in a document. Therefore, deleting an access point is an action we do not recommend executing since it can cause issues in you container or member documents. In order to remove members from a document through an access point see Member Management. Also, remember that access points maintain a strong link with the document that contains them. Therefore, if a document is deleted from the platform then the access points it contains will be deleted as well.

Conclusion

This guide described the need for Carbon LDP access points and how to interact with them via the REST API. Normally, developers will prefer use of the Carbon LDP Workbench (GUI) and an SDK, which together simplify the process of building and working with the platform. Still, all functions of the platform can be accessed through the REST API and those developers who understand the REST API may find it advantageous to use in some cases.