Getting Started with Grapheene's Sandbox

Test out Grapheene services in the Sandbox!

API Key privileges are specified using a series of flags on an API Key. The following table describes the flags supported by the system.This guide will get you started encrypting and decrypting data using Grapheene's Sandbox environment.an

Prerequisites

  1. An account with Grapheene. To get started reach out to us here

Accessing the Sandbox

An access link to the Sandbox is provided directly to you by Grapheene.

Authentication

Authentication within the sandbox is provided through the x-auth Header, using the API Key as the value.

"x-auth": "apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"

Available Endpoints

📘

Running Requests

When running requests from the examples below be sure to replace YOURINSTANCE with your specific instance provided to you by Grapheene.

Encrypt

POST /encrypt

Using the POST /encrypt endpoint you can encrypt your files and data.

Headers
{
    "Content-type": "multipart/form-data" | "application/json",
    "x-auth": "apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
}
Request Body
{
    "keyringname": "string",
    "data": "string" | Stream
}

Example: String Encrypt

const req = await fetch('https://api.YOURINSTANCE.grapheene.com/encrypt', {
    method: "POST",
    headers: {
        ["Content-type"]: "application/json",
        ["x-auth"]: "apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
    },
    body: JSON.stringify({
        keyringname: 'some keyring name',
        data: 'some string'
    })
})
url = 'https://api.YOURINSTANCE.grapheene.com/encrypt'
headers = {
    'Content-type': 'application/json',
    'x-auth': 'apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
}
data = {
    'keyringname': 'some keyring name',
    'data': 'some string'
}

response = requests.post(url, headers=headers, data=json.dumps(data))
req = response.json()

Example: JSON Response

{
  "encrypted": '...'
}

Example: File Encrypt using Streams

const fs = require('node:fs/promises')
const path = require('node:path')
const { pipeline } = require('node:stream/promises')
const fetch = require('node-fetch')
const FormData = require('form-data')

/* 
Set:
   * The Path to the file to encrypt
   * The Key Ring to use
*/
const FileToEncryptPath = path.join("....")
const KeyRing = "<key ring>"

async function main() {
    let fd = await fs.open(FileToEncryptPath)

    let form = new FormData()

   form.append('data', fd.createReadStream(path.join(__dirname, 'package.json')), {
        contentType: 'text/plain',
        name: 'data',
        filename: 'package.json'
    })

    form.append('keyringname', KeyRing)

    let res = await fetch('https://api.YOURINSTANCE.grapheene.com/encrypt', {
        method: 'POST',
        headers: {
            ["Content-type"]: "multipart/form-data" 
            ['x-auth']: 'apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX',
        },
        body: form
    })

    let encFd = await fs.open(path.join(__dirname, `${FileToEncryptPath}.enc`), 'w+')

    await pipeline(
        res.body,
        encFd.createWriteStream()
    )
}

main()
   .catch(err => {
      console.error(`Failed to encrypt file. Reason: ${err}`)
      process.exit(1)
   })
# Set:
#    * The Path to the file to encrypt
#    * The Key Ring to use
FileToEncryptPath = os.path.join("....")
KeyRing = "<key ring>"

def main():
    fd = open(FileToEncryptPath, 'rb')
    form = MultipartEncoder(
        fields={
            'data': ('data', fd, 'text/plain'),
            'keyringname': KeyRing
        }
    )
    res = requests.post(
        'https://api.YOURINSTANCE.grapheene.com/encrypt',
        headers={
            'Content-Type': form.content_type,
            'x-auth': 'apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
        },
        data=form
    )
    encFd = open(os.path.join(os.path.dirname(__file__), f'{FileToEncryptPath}.enc'), 'wb+')
    encFd.write(res.content)

try:
    main()
except Exception as err:
    print(f"Failed to encrypt file. Reason: {err}")
    exit(1

Decrypt

POST /decrypt

Using the POST /decrypt endpoint you can decrypt your encrypted files and data.

Headers
{
    "Content-type": "multipart/form-data" | "application/json",
    "x-auth": "apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
}
Request Body
{
    "keyringname": "string",
    "data": "string" | Stream
}

Example: String Decrypt

const req = await fetch('https://api.YOURINSTANCE.grapheene.com/decrypt', {
    method: "POST",
    headers: {
        ["Content-type"]: "application/json",
        ["x-auth"]: "apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
    },
    body: JSON.stringify({
        keyringname: 'some keyring name',
        data: 'some encrypted string'
    })
})
url = 'https://api.YOURINSTANCE.grapheene.com/decrypt'
headers = {
    'Content-type': 'application/json',
    'x-auth': 'apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
}
data = {
    'keyringname': 'some keyring name',
    'data': 'some encrypted string'
}

response = requests.post(url, headers=headers, data=json.dumps(data))
req = response.json()

Example: JSON Response

{
  "decrypted": '...'
}

Example: File Encrypt using Streams

const fs = require('node:fs/promises')
const path = require('node:path')
const { pipeline } = require('node:stream/promises')
const fetch = require('node-fetch')
const FormData = require('form-data')

/* 
Set:
   * The Path to the file to encrypt
   * The Key Ring to use
*/
const FileToDecryptPath = path.join("....")
const KeyRing = "<key ring>"


async function main() {
   let encOpen = await fs.open(FileToDecryptPath, 'r')

   let dform = new FormData()

   dform.append('data', encOpen.createReadStream(), {
      contentType: 'text/plain',
      name: 'data',
      filename: 'package.json'
   })

   dform.append('keyringname', KeyRing)

   res = await fetch('https://api.YOURINSTANCE.grapheene.com/decrypt', {
      method: 'POST',
      headers: {
         ["Content-type"]: "multipart/form-data"
         ['x-auth']: 'apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
      },
      body: dform
   })

   // Assuming text file
   let decFd = await fs.open(path.join(__dirname, `${FileToDecryptPath}.dec.txt`), 'w+')
   let write = await decFd.createWriteStream()

   await pipeline(res.body, write)
}

main()
   .catch(err => {
      console.error(`Failed to decrypt file. Reason: ${err}`)
      process.exit(1)
   })
# Set:
#    * The Path to the file to encrypt
#    * The Key Ring to use
FileToDecryptPath = os.path.join("....")
KeyRing = "<key ring>"

def main():
    encOpen = open(FileToDecryptPath, 'rb')
    dform = FormData()
    dform.add_field('data', encOpen, content_type='text/plain', filename='package.json')
    dform.add_field('keyringname', KeyRing)
    res = requests.post('https://api.YOURINSTANCE.grapheene.com/decrypt', headers={
        'x-auth': 'apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
    }, files=dform)
    # Assuming text file
    decFd = open(os.path.join(os.path.dirname(__file__), f'{FileToDecryptPath}.dec.txt'), 'wb')
    write = decFd
    shutil.copyfileobj(res.raw, write)

try:
    main()
except Exception as err:
    print(f'Failed to decrypt file. Reason: {err}')
    exit(1)

Key Ring Management

Using the Key Ring Management endpoints you can create and view your Key Rings, and rotate your Keys.

POST /keyrings

Using thePOST /keyrings endpoint you can generate new Key Rings to encrypt your data with.

🔒

Endpoint Permission Requirements

keyring.create: true
Headers
{
    "Content-type": "application/json",
    "x-auth": "apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
}
Request Body
{
    "name": "string",
    "algo": "aes256",
    "keyData": {
           "key" : "<32-bytes UTF8 alphanumeric string w/special characters >",
           "iv": "<16-bytes UTF8 alphanumeric string w/special>"
        }
}

Example: Create a KeyRing

const req = await fetch('https://api.YOURINSTANCE.grapheene.com/keyrings', {
    method: "POST",
    headers: {
        ["Content-type"]: "application/json",
        ["x-auth"]: "apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
    },
    body: JSON.stringify({
        name: 'key-ring-name',
        algo: 'aes256',
        keyData: {
           key : "<32 alphanumeric string w/special characters >",
           iv: "<16 alphanumeric string w/special>"
        }
    })
})
req = requests.post('https://api.YOURINSTANCE.grapheene.com/keyrings', 
                    headers={
                        "Content-type": "application/json",
                        "x-auth": "apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
                    },
                    json={
                        "name": "key-ring-name",
                        "algo": "aes256",
                        "keyData": {
                            "key": "<32 alphanumeric string w/special characters >",
                            "iv": "<16 alphanumeric string w/special>"
                        }
                    })

Example: JSON Response to Creating a KeyRing

{
   "ring": {
      "id":"...",
      "name":"...",
      "publicKey":"...",
      "privateKey": "..."
   }
}

GET /keyrings

Using the GET /keyrings endpoint you can retrieve a listing if all Key Rings and the keyrings details such as ID, name, created, updated, etc.

🔒

Endpoint Permission Requirements

keyring.\*.read: true
Headers
{
    "Content-type": "application/json",
    "x-auth": "apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
}

Example: Request to Retrieve All KeyRings

const req = await fetch('https://api.YOURINSTANCE.grapheene.com/keyrings', {
    method: "GET",
    headers: {
        ["Content-type"]: "application/json",
        ["x-auth"]: "apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
    }
})
req = requests.get('https://api.YOURINSTANCE.grapheene.com/keyrings', 
                   headers={
                       "Content-type": "application/json",
                       "x-auth": "apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
                   })

Example: JSON Response to Retrieving All KeyRings

{
    "rings": [
        {
        "id": "...",
        "name": "...",
        "publicKey": "...",
        "activeKey": "...",
        "activeAlgorithm": "...",
        "createdAt": "...",
        "updatedAt": "..."
        },
        ...
    ]
}

GET /keyrings/:keyringid

Using the GET /keyrings/:keyringid endpoint you can retrieve a Key Ring by name or ID.

📘

Request Behavior

By default, the request provided below will get the Key Ring by name.

Passing in the query string of id=true, will adjust the request to retrieve the Key Ring by ID instead.

🔒

Endpoint Permission Requirements

keyring.\*.read: true 
keyring.<ring-name>.read: true
Headers
{
    "Content-type": "application/json",
    "x-auth": "apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
}

Example: Request to Retrieve KeyRing by Name

const req = await fetch('https://api.YOURINSTANCE.grapheene.com/keyrings/<keyring-name-or-id>' + new URLSearchParams({id: false}), {
    method: "GET",
    headers: {
        ["Content-type"]: "application/json",
        ["x-auth"]: "apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
    }
})
req = requests.get('https://api.YOURINSTANCE.grapheene.com/keyrings/<keyring-name-or-id>' + 
                   '?' + 
                   '&'.join(['{}={}'.format(k, v) for k, v in {'id': False}.items()]), 
                   headers={
                       "Content-type": "application/json",
                       "x-auth": "apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
                   })

Example:JSON Response to Retrieving KeyRing by Name

{
    "ring": {
        "id": "keyring-XXXXX",
        "name": "default",
        "publicKey": "...",
        "activeKey": "key-XXXXXXX",
        "activeAlgorithm": "aes256",
        "createdAt": "2023-04-21T03:54:04.715Z",
        "updatedAt": "2023-04-21T03:54:04.715Z"
    }
}

POST /rotate

Using the rotate endpoint you can change the Key used within a specific Key Ring.

🔒

Endpoint Permission Requirements

keyring.*.rotate: true 
keyring.<ring-name>.rotate: true
Headers
{
    "Content-type": "application/json",
    "x-auth": "apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
}
Request Body
{
    "keyringname": "string"
}
data = {
    "keyringname": "string"
}

Example: Rotating a Key

res = await fetch('https://api.YOURINSTANCE.grapheene.com/rotate', {
   method: 'POST',
   headers: {
      ['Content-type']: "application/json"
      ['x-auth']: 'apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
   },
   body: JSON.stringify({
    keyringname: 'some keyring name'
   })
})
res = requests.post('https://api.YOURINSTANCE.grapheene.com/rotate', 
                    headers={
                        "Content-type": "application/json",
                        "x-auth": "apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
                    },
                    json={
                        "keyringname": "some keyring name"

Example: JSON Response when Rotating a Key

{
    "message": "Key Ring [keyringname] has a new active key"
}

User Management

Using the User Management endpoints you can create and view your users within the system.

POST /user

Using thePOST /users endpoint you can generate new User. When a new User is created, you also have the option of creating an API Key for the user in the same request.

Headers
{
    "Content-type": "application/json",
    "x-auth": "apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
}
Request Body
{
    "email": "string",
    "firstName": "string",
    "lastName": "string",
    "key": {
        "flags": {
            // Example permission flag. Add as many here as needed.
            // See table below for the list of available entitlements
            "keyring.default.read": true
        }  
    },
    // Freeform tagging object.
    // Data added here enables with integrating with external systems
    "props": {}
}

Example: Request for Creating a User

const req = await fetch('https://api.YOURINSTANCE.grapheene.com/users', {
    method: "POST",
    headers: {
        ["Content-type"]: "application/json",
        ["x-auth"]: "apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
    },
    body: {
         email: '<email>',
         firstName: '<firstName>',
         lastName: '<lastName>',
         key: {
            flags: {
                // grant permissions to the user, full list detailed below. 
                "keyring.<keyringname>.create": true
            },
            props: {
                // service based tags
                service: "<some service or application>",
                ...
            }
         }, 
         props: 'object'
    }
})
url = 'https://api.YOURINSTANCE.grapheene.com/users'
headers = {
    "Content-type": "application/json",
    "x-auth": "apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
}
data = {
    "email": '<email>',
    "firstName": '<firstName>',
    "lastName": '<lastName>',
    "key": {
        "flags": {
            # grant permissions to the user, full list detailed below.
            "keyring.<keyringname>.create": True
        },
        "props": {
            # service based tags
            "service": "<some service or application>",
            ...
        }
    },
    "props": 'object'
}
req = requests.post(url, headers=headers, data=json.dumps(data))

Example: JSON Response for Creating a User

{
    "id": "...",
    "name": "..."
}

GET /users

Using theGet /users endpoint you can retrieve a listing of all current users.

Headers
{
    "Content-type": "application/json",
    "x-auth": "apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
}

Example: Request for Retrieving All Users

const req = await fetch(`https://api.YOURINSTANCE.grapheene.com/users`, {
    method: "GET",
    headers: {
        ["Content-type"]: "application/json",
        ["x-auth"]: "apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
    }
})
url = 'https://api.YOURINSTANCE.grapheene.com/users'
headers = {
    "Content-type": "application/json",
    "x-auth": "apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
}
req = requests.get(url, headers=headers)

Example: JSON Response for Retrieving All Users

[
    {
        "email": "[email protected]",
        "firstName": "User",
        "lastName": "One",
        "keys": [
            "apikeyid-xxxx"
        ],
        "props": {}
    },
        {
        "email": "[email protected]",
        "firstName": "User",
        "lastName": "Two",
        "keys": [
            "apikeyid-xxxx"
        ],
        "props": {}
    }
]

GET /users/:email

Using theGet /users/:email endpoint you can retrieve a specific user by the users associated email.

Headers
{
    "Content-type": "application/json",
    "x-auth": "apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
}

Example: Request to Retrieve User by Email

const req = await fetch(`https://api.YOURINSTANCE.grapheene.com/users/[email protected]`, {
    method: "GET",
    headers: {
        ["Content-type"]: "application/json",
        ["x-auth"]: "apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
    }
})
url = 'https://api.YOURINSTANCE.grapheene.com/users/[email protected]'
headers = {
    "Content-type": "application/json",
    "x-auth": "apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
}
req = requests.get(url, headers=headers)

Example: JSON Response for Retrieving a User by Email

{
    "email": "[email protected]",
    "firstName": "Happy",
    "lastName": "User",
    "keys": [
        "apikeyid-xxxx-xxxxx-xxxx"
    ],
    "props": {}
}

Delete /users/:email

Using theDelete /users/:email endpoint you can delete a specific user by the users associated email.

Headers
{
    "Content-type": "application/json",
    "x-auth": "apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
}

Example: Request to Delete User by Email

const req = await fetch(`https://api.YOURINSTANCE.grapheene.com/users/[email protected]`, {
    method: "DELETE",
    headers: {
        ["Content-type"]: "application/json",
        ["x-auth"]: "apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
    }
})
url = 'https://api.YOURINSTANCE.grapheene.com/users/[email protected]'
headers = {
    "Content-type": "application/json",
    "x-auth": "apikey-XXXXXXXX"
}
req = requests.delete(url, headers=headers)

Example: JSON Response for Deleting a User by Email

{
   "email": "[email protected]",
   "firstName": "Delete",
   "lastName": "Me",
   "keys": [
      // All user API Keys have been disabled
      "apikeyid-xxxxx"
   ],
   "props": {}
}

API Key Management

Using the API Key Management endpoints you can create, view and update your API Keys.

📘

API Keys

All API Keys are tied to a user or service account.

Note that API Keys are never deleted, but can be set to inactive. This is to ensure a proper audit trail is available for all activities that are generated from an API Key.

POST /apikey

Using thePOST /apikey endpoint you can generate API Key.

❗️

Warning

The only time a user will see their API Key is when it is first created.

Headers
{
    "Content-type": "application/json",
    "x-auth": "apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
}

Example: Creating an API Key

const req = await fetch(`https://api.YOURINSTANCE.grapheene.com/apikey`, {
    method: "POST",
    headers: {
        ["Content-type"]: "application/json",
        ["x-auth"]: "apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
    },
    body: {
      user: "[email protected]",
      flags: {
         "keyring.default.encrypt": true,
         "keyring.default.decrypt": true
      },
      props: {
         "some": "metadata"
      }
    }
})
req = requests.post("https://api.YOURINSTANCE.grapheene.com/apikey", 
                    headers={
                        "Content-type": "application/json",
                        "x-auth": "apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
                    },
                    json={
                        "user": "[email protected]",
                        "flags": {
                            "keyring.default.encrypt": True,
                            "keyring.default.decrypt": True
                        },
                        "props": {
                            "some": "metadata"
                        }
                    })

Example: JSON Response from Creating an API Key

{
    "key": "apikey-xxxx",
    "keyid": "apikeyid-xxxx",
    "createdAt": "2023-04-21T17:04:08.336Z",
    "active": true,
    "flags": {
        "keyring.default.encrypt": true,
        "keyring.default.decrypt": true,
    },
    "props": {
        "some": "metadata"
    }
}

GET /apikey

Using theGET /apikey endpoint you can retrieve a listing of all your API Keys.

Headers
{
    "Content-type": "application/json",
    "x-auth": "apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
}

Example: Retreiving all API Keys

const req = await fetch(`https://api.YOURINSTANCE.grapheene.com/apikey`, {
    method: "GET",
    headers: {
        ["Content-type"]: "application/json",
        ["x-auth"]: "apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
    }
})
req = requests.get("https://api.YOURINSTANCE.grapheene.com/apikey", 
                   headers={
                       "Content-type": "application/json",
                       "x-auth": "apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
                   })

Example: JSON Response from Retrieving all API Keys

[
    {
        "keyid": "apikeyid-xxxxx",
        "createdAt": "2023-04-21T16:53:14.300Z",
        "active": true,
        "flags": {
            "keyring.*.decrypt": true,
            "keyring.*.encrypt": true,
        },
        "props": {
            "email": "[email protected]"
        }
    },
    {
        "keyid": "apikeyid-xxxxx",
        "createdAt": "2023-04-21T16:57:37.418Z",
        "active": false,
        "flags": {
            "keyring.*.read": true
        },
        "props": {
            "email": "[email protected]"
        }
    }
]

PUT /apikeyid

Using thePUT /apikeyid endpoint you can update the current status, props, flags and other details for a specific API Key.

This request is flexible as it can update or delete values, which is controlled with the op property. Nested properties are supported.

op can be:

  • "update": This will update properties that already exist, or add new ones
  • "delete": This will remove properties that exist
Headers
{
    "Content-type": "application/json",
    "x-auth": "apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
}

Example: Updating an API Key

const req = await fetch(`https://api.YOURINSTANCE.grapheene.com/apikeyid`, {
    method: "PUT",
    headers: {
        ["Content-type"]: "application/json",
        ["x-auth"]: "apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
    },
    body: {
      op: "update",           // Required
      apikeyid: "<key id>",   // Required
      active: true,           // Optiuonal
      flags: {                // Optional
         "keyring.delete.all": true
      },
      props: {                // Optional
         legalhold: true
      }
    }
})
req = requests.put("https://api.YOURINSTANCE.grapheene.com/apikeyid", 
                   headers={
                       "Content-type": "application/json",
                       "x-auth": "apikey-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
                   },
                   json={
                       "op": "update",
                       "apikeyid": "<key id>",
                       "active": True,
                       "flags": {
                           "keyring.delete.all": True
                       },
                       "props": {
                           "legalhold": True
                       }
                   })

Example: JSON Response from Updating an API Key

{
    "apikeyid": "apikeyid-xxxx",
    "createdAt": "2023-04-21T16:53:14.300Z",
    "active": true,
    "flags": {
        "keyring.*.rotate": true,
        "keyring.*.config.*": true,
        "keyring.*.read": true,
        "keyring.delete.all": true
    },
    "props": {
        "legalhold": true
    }
}

Data Streams

The backend system provides streaming data to provide insight into the data in the backend. This is useful for setting up alerting and monitoring, or to allow systems to update themselves in real time.

GET /stats/sse

Use theGET /stats/sse endpoint to stream for performance metrics when encrypting and decrypting data.

Example: Subscribing to the Activity Events

const EventSource = require('eventsource')
const eventSource = new EventSource('https://api.YOURINSTANCE.grapheene.com/stats/sse')

eventSource.onmessage({data} => {
    console.log('Key Server Event', JSON.parse(data))
})
from eventsource import EventSource

eventSource = EventSource('https://api.YOURINSTANCE.grapheene.com/stats/sse')
eventSource.onmessage = lambda data: print('Key Server Event', json.loads

Example: JSON SSE Response

{"op":"...","type":"...","timespanMs":"...","dataPreview":"..."}

GET /auth/sse

Use theGET /auth/sse endpoint to see User activity in stream. This stream provides the activity on what Key Ring, API Key, and user is performing.

Example: Subscribing to the User Activity Events

const EventSource = require('eventsource')
const eventSource = new EventSource('https://api.YOURINSTANCE.grapheene.com/auth/sse')

eventSource.onmessage({data} => {
    console.log('Key Server Event', JSON.parse(data))
})
response = requests.get('https://api.YOURINSTANCE.grapheene.com/auth/sse', stream=True)
for line in response.iter_lines():
    if line:
        print('Key Server Event', json.loads(line))

Example: JSON SSE Response

data: {"id":"activity-xxxx","keyId":"developer","props":{"action":"keyring.read.all","_auth":{"keyid":"developer","valid":true,"timestamp":1682095275851}}}


API Key Permissions

API Key privileges are specified using a series of flags on an API Key. The following table describes the flags supported by the system.

Below is a listing of all API Key Permissions and the permissions related Flag.

Allows the call to decrypt from ANY Key Ring

keyring.*.decrypt: true

Allows the Call to decrypt from the specified Key Ring

keyring.<key-ring-name>.decrypt: true

Allows the call to encrypt from any Key Ring

keyring.*.encrypt: true

Allows the call to encrypt from the specified Key Ring

keyring.<key-ring-name>.encrypt: true

Allows the call to read any Key Ring details

keyring.*.read": true

Allows the call to read the details of the specified Key Ring

keyring.<key-ring-name>.read: true

Allows the call to delete any Key Ring

keyring.*.delete: true

Allows the call to delete the specified Key Ring

keyring.<key-ring-name>.delete: true

Allows the call to rotate the key on any Key Ring

keyring.*.rotate: true

Allows the call to rotate the key on the specified Key Ring

keyring.<key-ring-name>.rotate: true

Allows the call to read and write the configuration of any Key Ring

keyring.*.config.*: true

Allows the call to read and write the configuration of the specified Key Ring

keyring.<key-ring-name>.config.*: true*

Allows the call to create any Key Ring

keyring.create: true

Allows the call to delete all Key Rings

keyring.delete.all: true