Skip to content

Getting Started

Skapi is a serverless backend API for your web application.

To enable backend features, first create a project at skapi.com.

Creating a Project

  1. Sign up for an account at skapi.com.
  2. Log in, name your project, and choose a region. Click Create.

For BunnyQuery users

BunnyQuery projects are fully compatible with Skapi. Your project will appear in both your BunnyQuery and Skapi project lists.

For HTML Projects

For vanilla HTML projects, load Skapi using a script tag and initialize the library as shown below. Add the Skapi script and initialize the Skapi class in the <head> of each page that uses Skapi. Use the exact Project ID of your Skapi project when initializing the library.

html
<!-- index.html -->
<!DOCTYPE html>
<script src="https://cdn.jsdelivr.net/npm/skapi-js@latest/dist/skapi.js"></script>
<script>
    // Replace "<Project ID>" with your actual project ID
    const skapi = new Skapi("<Project ID>");
</script>

Replace the placeholder

<Project ID> is a placeholder, including the angle brackets.

Replace the entire string with your actual Project ID from the Skapi dashboard. For example:

js
const skapi = new Skapi("abc123defg456hij78-9klmnop012qrstu345vwxyz");

Every example in these docs uses the same "<Project ID>" placeholder. Replace it wherever you copy an example.

The Project ID is a unique identifier for your Skapi project.

Example format: "xxxxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxx"

For SPA Projects

To use Skapi in a Single Page Application (SPA) such as Vue, React, or Angular, install skapi-js with npm.

sh
$ npm i skapi-js

Then import the library in your main JavaScript file:

javascript
// main.js
import { Skapi } from "skapi-js";
const skapi = new Skapi("<Project ID>");

export { skapi }

// You can now import skapi from anywhere in your project.

For TypeScript Projects

Skapi includes TypeScript support, so you can import both the class and related types.

typescript
import { Skapi } from 'skapi-js';
import type { RecordData, DatabaseResponse } from 'skapi-js';

const skapi = new Skapi("<Project ID>");
let databaseRecords: DatabaseResponse<RecordData>;

Node.js (CommonJS)

To use Skapi in Node.js (CommonJS), import the library as shown below:

javascript
const { Skapi } = require('skapi-js');
const skapi = new Skapi("<Project ID>");

Node.js (ESM)

javascript
import { Skapi } from 'skapi-js';
const skapi = new Skapi("<Project ID>");

Note: When running Skapi in Node.js, browser-specific features such as WebSocket, WebRTC, and Notifications are not available.

Get Connection Information

After your client connects to Skapi, call getConnectionInfo() to retrieve connection details.

html
<!-- index.html -->
<!DOCTYPE html>
<script src="https://cdn.jsdelivr.net/npm/skapi-js@latest/dist/skapi.js"></script>
<script>
    const skapi = new Skapi("<Project ID>");
</script>
<script>
skapi.getConnectionInfo().then(info => {
    console.log(info);
    /*
    Returns:
    {
        project_id: "Public project ID of the connected project",
        user_ip: "Connected user's IP address",
        user_agent: "Connected user agent",
        user_location: "Connected user's country code",
        service_name: "Your Project Name",
        service_description: "Your project description",
        version: 'x.x.x', // Skapi library version
        ai_agent: "AI agent instructions set for the project",
        conf: {
            freeze_database: boolean, // Database is read only
            prevent_signup: boolean, // Signup is blocked
            prevent_inquiry: boolean, // Inquiry is blocked
            prevent_anonymous: boolean // Anonymous users cannot write to the database
        }
    }
    */
   window.alert(`Connected to ${info.service_name}`);
});
</script>
javascript
import { skapi } from '../location/of/your/main.js';
skapi.getConnectionInfo().then(info => {
    console.log(info);
    /*
    Returns:
    {
        project_id: "Public project ID of the connected project",
        user_ip: "Connected user's IP address",
        user_agent: "Connected user agent",
        user_location: "Connected user's country code",
        service_name: "Your Project Name",
        service_description: "Your project description",
        version: 'x.x.x', // Skapi library version
        ai_agent: "AI agent instructions set for the project",
        conf: {
            freeze_database: boolean, // Database is read only
            prevent_signup: boolean, // Signup is blocked
            prevent_inquiry: boolean, // Inquiry is blocked
            prevent_anonymous: boolean // Anonymous users cannot write to the database
        }
    }
    */
   window.alert(`Connected to ${info.service_name}`);
});

Advanced Settings

You can pass additional options when initializing the Skapi class.

new Skapi(...)

ts
class Skapi {
  constructor(
    project_id: string, // Skapi project ID. The legacy service ID + owner ID pair is still accepted.
    options?: {
        autoLogin?: boolean;        // Default: true
        refetchServiceInfo?: boolean;// Default: false. Bypasses cached project info and always fetch new project info on load.
        requestBatchSize?: number;  // Default: 30. Maximum number of requests processed per batch.
        encryption?: boolean | { // Default: false. Encrypts the data of private records in the browser. Can only be set here, on initialization. HTTPS required.
            iterations?: number;             // Default: 600000. PBKDF2 cost. Minimum 100000.
            minPasswordLength?: number;      // Default: 0 (off). Refuses to set up encryption for a shorter password.
            persistDevice?: boolean;         // Default: true. Stays unlocked across page reloads on that device.
            recovery?: 'code' | 'none';      // Default: 'code'. Issues a one-time recovery code.
            trustPolicy?: 'tofu' | 'strict'; // Default: 'tofu'. How a recipient's public key is trusted when sharing.
            withheld?: 'null' | 'sentinel';  // Default: 'null'. What data is set to when a record cannot be decrypted.
            table?: string;                  // Default: '__skapi__keyring'. Reserved table that stores the user's keyring.
        };
        eventListener?: {
            onLogin?: (user: UserProfile | null) => void; // Fires on initial page load (after Skapi initializes), on login/logout, and when a session expires. The callback receives a UserProfile object if the user is logged in; otherwise, it receives null.
            onUserUpdate?: (user: UserProfile | null) => void; // Fires on initial page load (after Skapi initializes), on login/logout, when a session expires, and when the user's profile is updated. The callback receives a UserProfile object if the user is logged in; otherwise, it receives null.
            onBatchProcess?: (process: {
                batchToProcess: number; // Number of batches left to process
                itemsToProcess: number; // Number of items left to process
                completed: any[]; // Results completed in this batch
            }) => void;
        }
    }) {
    ...
  }
  ...
}

Options overview:

  • autoLogin (boolean, default: true)

    • Automatically restores the user's session on page load.
    • See: Auto Login
  • requestBatchSize (number, default: 30)

    • Maximum number of requests processed per batch.
  • encryption (boolean | object, default: false)

    • Encrypts the data of the records saved to access_group: 'private', in the browser, before it reaches the database. The contents of the files attached to those records are encrypted as well.
    • This only takes effect when it is set here, when the Skapi class is initialized. There is no method that turns encryption on afterwards, so when this option is left out, the instance saves the data of every record as plain text for its entire lifetime.
    • Enabling it later does not go back and encrypt the records that were already saved as plain text.
    • Setting it to true uses the default settings. Pass an object to change them:
      • iterations (number, default: 600000): PBKDF2 cost of deriving the key from the user's password. Minimum 100000.
      • minPasswordLength (number, default: 0, off): refuses to set up encryption for a password shorter than this. The strength of the encryption is capped by the user's password, so it is worth setting.
      • persistDevice (boolean, default: true): keeps encryption unlocked across page reloads on that device.
      • recovery ('code' | 'none', default: 'code'): issues a one-time recovery code, which is the only way for the user to reach their data again after a password reset.
      • trustPolicy ('tofu' | 'strict', default: 'tofu'): how a recipient's public key is trusted when a record is shared. 'strict' requires the key to be pinned before the first share.
      • withheld ('null' | 'sentinel', default: 'null'): what data is set to when a record cannot be decrypted. 'sentinel' returns a placeholder object carrying the reason instead of null.
      • table (string, default: '__skapi__keyring'): the reserved table that stores the user's keyring.
    • See: Encrypting Private Record Data
  • eventListener (callbacks for key events)

    • onLogin(user: UserProfile | null)

      • Fires on initial page load (after Skapi initializes), on login/logout, and when a session expires. The callback receives a UserProfile object if the user is logged in; otherwise, it receives null.
      • See: Listening to Login/Logout Status
    • onUserUpdate(user: UserProfile | null)

      • Fires on initial page load (after Skapi initializes), on login/logout, when a session expires, and when the user's profile is updated. The callback receives a UserProfile object if the user is logged in; otherwise, it receives null.
      • See: Listening to User Profile Updates
    • onBatchProcess(process)

      • Fires each time Skapi completes processing a request batch.

Type reference: See UserProfile.