# Permissioned IPFS

## Access Routes

Cherty uses access routes for permissioned IPFS resources, establishing a role-based permission system defining user access. An access route has the following properties:

<table><thead><tr><th width="129">Property</th><th>Value</th></tr></thead><tbody><tr><td><strong>cid</strong></td><td>The content identifier of the resource with permissions being defined in this access route.</td></tr><tr><td><strong>owner</strong></td><td>A <a href="/pages/qUpPKoajvBClZ6xLVeuE#public-account-object">Public Account Object</a> corresponding to the owner of this access route.</td></tr><tr><td><strong>admins</strong></td><td>An array of public account objects defining admins, who are able to add or remove viewers from this access route.</td></tr><tr><td><strong>viewers</strong></td><td>An array of public account objects defining users who are able to view this resource.</td></tr></tbody></table>

The interpretation of an access route is that the CID's data is "copied to" the owner's account and they are able manage permissions for this copy. If another user establishes an access route for the same data, they are able to independently manage access. Thus, multiple access routes for the same CID may exist but they must have different owners.

For security, it is necessary that an access route may not be created owned by an account unless that account either (1) provides the data, or (2) is listed as a viewer or admin on another access route for the same data. Thus, possession of a CID is not sufficient to gain access to the data represented by that CID.

## Usage Examples

See [permissioned-ipfs api examples](https://github.com/devonian-ai/permissioned-ipfs/blob/main/api_examples.js) for a demo of how to use these endpoints.

To learn more about how Cherty handles identity, see [Authentication](/authentication.md).

### Upload data: /api/upload

```
https://cherty.io/api/upload
```

**Type**: POST

**Protected:** Yes (requires authorization header)

**Accepts:** Data stream

**Returns:** CID

This route uploads data and stores it to your account, then returns the CID.&#x20;

```javascript
const fileData = fs.readFileSync('earthrise.jpeg');
const uploadResponse = await axios.post(
    `https://cherty.io/api/binary_data_upload`, fileData, {
    headers: {
    'Content-Type': 'application/octet-stream',
    'Authorization': `Bearer ${API_KEY}`,
    },
})

console.log('File uploaded successfully');
console.log('CID:', uploadResponse.data.cid);
```

### Download Data: /api/file/cid

**Type:** GET

**Protected:** Yes (requires authorization header)

**Accepts:** CID

**Returns:** Binary data stream

This route takes a CID and, if you have access, retrieves the data.

```javascript
const downloadResponse = await axios.get(
    `https://cherty.io/api/file/${earthrise_CID}`, {
        headers: {
            Authorization: `Bearer ${API_KEY}`,
        },
        responseType: 'arraybuffer',
    })
const buffer = Buffer.from(downloadResponse.data, 'binary');
fs.writeFileSync('downloadedData.jpeg', buffer);
```

### List Access Routes: /api/access\_routes/CID

**Type:** GET

**Protected:** Yes (requires authorization header)

**Accepts:** CID

**Returns:** Binary data stream

View permissions for a given CID. This route accepts a CID and returns all [access routes](#access-routes) visible to the authenticated account (ie. all routes where this account is the owner, or an admin or viewer).

```javascript
const accessRoutesResponse = await fetch(`https://cherty.io/api/access_routes/${fileCID}`, {
        headers: {
          Authorization: `Bearer ${API_KEY}`,
        },
      });
    const accessRoutes = await accessRoutesResponse.json();
    console.log(accessRoutes);
```

Example response:

```json
[
  {
    cid: 'bafkreiebdtqimpnqwt5magb2xdxg3b3q5wisyene4ujo5o6p73c5d2jqka',
    owner: {
      name: 'Alan Ransil',
      profile_photo: 'bafkreigne6x4pbih6cpvsoapjqn7t5a6wvrk47r4dzufnjazt56pjh4f6a',
      organization: 'Devonian Systems',
      id_object: [Object],
      id_CID: 'bafkreictbqkffrjs4jklzrm3ijszkmz5rcx3malvc3jkkvgyv7unhq2ddi'
    },
    admins: [],
    viewers: []
  }
]
```

### Edit Permissions: /api/edit\_permissions

**Type:** GET

**Protected:** yes

**Accepts:** CID, Owner, Permissions Object, Mode ('add' / 'remove' / 'subtract')

Permissions object contains **admins** and **viewers** keys. Each is an array with either [id\_objects or id\_cids](/authentication.md#identity-representation) or a mix of the two. Example:

```json
const permissions_object = {
        admins: [{"id": "113160473128016495295", "method": "google-oauth2"}],
        viewers: ['bafkreictbqkffrjs4jklzrm3ijszkmz5rcx3malvc3jkkvgyv7unhq2ddi']
    };
```

Add mode will add the listed admins and viewers to the existing permissions, remove mode will remove them if they currently have access, and set mode will replace the existing permissions with the new list.

```javascript
const editPermissionsData = {
        cid: fileCID,
        owner: id_cid,
        permissions_object,
        mode: 'add'
      };
    
    const editPermissionsResponse = await axios.post(
        `https://cherty.io/api/edit_permissions`, editPermissionsData, {
            headers: {
                Authorization: `Bearer ${API_KEY}`,
            },
        });
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.cherty.io/permissioned-ipfs.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
