Developer docs

API reference / Workspace

Get workspace details

GEThttps://app.clik.so/api/workspace/bootstrap

In short

Returns your workspace's plan, limits, usage, folders, tags and domains in one call. It is the quickest way to learn what a key can do.

You need

API key
read permission or higher. See Authentication.
Role
Any member (viewer and up) in the key's workspace.
Plan
Any plan, including Free.

Example

curl "https://app.clik.so/api/workspace/bootstrap" \
  -H "Authorization: Bearer $CLIKSO_API_KEY"
const res = await fetch("https://app.clik.so/api/workspace/bootstrap", {
  headers: {
    Authorization: `Bearer ${process.env.CLIKSO_API_KEY}`,
  },
});

const data = await res.json();
console.log(res.status, data);

Uses fetch (Node 18+ or the browser). Set CLIKSO_API_KEY first.

import os
import requests

response = requests.get(
    "https://app.clik.so/api/workspace/bootstrap",
    headers={"Authorization": f"Bearer {os.environ['CLIKSO_API_KEY']}"},
)

print(response.status_code, response.json())

Uses requests. Set CLIKSO_API_KEY first.

<?php

$ch = curl_init('https://app.clik.so/api/workspace/bootstrap');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('CLIKSO_API_KEY'),
    ],
]);

$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);

echo $status, PHP_EOL, $response, PHP_EOL;

Uses the curl extension. Set CLIKSO_API_KEY first.

package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, err := http.NewRequest("GET", "https://app.clik.so/api/workspace/bootstrap", nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("CLIKSO_API_KEY"))

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	data, err := io.ReadAll(res.Body)
	if err != nil {
		panic(err)
	}
	fmt.Println(res.StatusCode, string(data))
}

Uses net/http. Set CLIKSO_API_KEY first.

require "net/http"

uri = URI('https://app.clik.so/api/workspace/bootstrap')
request = Net::HTTP::Get.new(uri)
request["Authorization"] = "Bearer #{ENV.fetch("CLIKSO_API_KEY")}"

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
  http.request(request)
end

puts response.code, response.body

Uses Net::HTTP. Set CLIKSO_API_KEY first.

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class Main {
    public static void main(String[] args) throws Exception {
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://app.clik.so/api/workspace/bootstrap"))
            .header("Authorization", "Bearer " + System.getenv("CLIKSO_API_KEY"))
            .GET()
            .build();

        HttpResponse<String> response = HttpClient.newHttpClient()
            .send(request, HttpResponse.BodyHandlers.ofString());

        System.out.println(response.statusCode());
        System.out.println(response.body());
    }
}

Uses java.net.http (Java 15+). Set CLIKSO_API_KEY first.

using System.Net.Http.Headers;

using var client = new HttpClient();
var request = new HttpRequestMessage(new HttpMethod("GET"), "https://app.clik.so/api/workspace/bootstrap");
request.Headers.Authorization = new AuthenticationHeaderValue(
    "Bearer", Environment.GetEnvironmentVariable("CLIKSO_API_KEY"));

using var response = await client.SendAsync(request);
Console.WriteLine((int)response.StatusCode);
Console.WriteLine(await response.Content.ReadAsStringAsync());

Uses HttpClient (C# 11+). Set CLIKSO_API_KEY first.

#include <cstdlib>
#include <iostream>
#include <string>
#include <curl/curl.h>

static size_t collect(char* data, size_t size, size_t n, void* out) {
    static_cast<std::string*>(out)->append(data, size * n);
    return size * n;
}

int main() {
    CURL* curl = curl_easy_init();
    if (!curl) return 1;

    const char* key = std::getenv("CLIKSO_API_KEY");
    std::string auth = std::string("Authorization: Bearer ") + (key ? key : "");
    struct curl_slist* headers = curl_slist_append(nullptr, auth.c_str());
    std::string response;

    curl_easy_setopt(curl, CURLOPT_URL, "https://app.clik.so/api/workspace/bootstrap");
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, collect);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);

    CURLcode rc = curl_easy_perform(curl);
    long status = 0;
    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &status);
    curl_slist_free_all(headers);
    curl_easy_cleanup(curl);

    if (rc != CURLE_OK) {
        std::cerr << curl_easy_strerror(rc) << std::endl;
        return 1;
    }
    std::cout << status << "\n" << response << std::endl;
    return 0;
}

Uses libcurl. Set CLIKSO_API_KEY first.

Response 200
{
  "status": 200,
  "success": true,
  "message": "Success",
  "data": {
    "workspace_id": "8a1f2c3d-4b5e-4f60-9a7b-1c2d3e4f5a6b",
    "profile": {
      "id": "c4d5e6f7-a8b9-4c0d-9e1f-2a3b4c5d6e7f",
      "email": "asha@example.com",
      "display_name": "Asha Rao",
      "photo_url": "",
      "created_at": "2026-09-01T12:00:00.000Z"
    },
    "is_app_admin": false,
    "workspaces": [
      {
        "id": "8a1f2c3d-4b5e-4f60-9a7b-1c2d3e4f5a6b",
        "name": "Acme",
        "owner_id": "c4d5e6f7-a8b9-4c0d-9e1f-2a3b4c5d6e7f",
        "plan_type": "starter",
        "subscription_status": "active",
        "created_at": "2026-09-01T12:00:00.000Z",
        "updated_at": "2026-10-01T12:00:00.000Z",
        "role": "admin",
        "access_state": null,
        "access_state_since": null,
        "is_default": true,
        "default_since": null
      }
    ],
    "usage": {
      "workspace_id": "8a1f2c3d-4b5e-4f60-9a7b-1c2d3e4f5a6b",
      "links_created_this_month": 42,
      "clicks_this_month": 1873,
      "ai_analytics_today": 0,
      "ai_slug_gens_today": 3,
      "last_reset_ai": "2026-10-09",
      "last_reset_monthly": "2026-10-01",
      "next_reset": "2026-11-01T00:00:00.000Z",
      "updated_at": "2026-10-09T09:30:00.000Z",
      "plan_key": "starter",
      "plan_links_limit": 500,
      "plan_domains_limit": 2,
      "is_simulated": false
    },
    "subscription": {
      "plan": "starter",
      "plan_name": "Starter",
      "period": "monthly",
      "currency": "USD",
      "status": "active",
      "limits": {
        "linksPerMonth": 500,
        "clicksPerMonth": 20000,
        "customDomains": 2,
        "retentionDays": 90,
        "folders": 6,
        "tags": 10,
        "teamSeats": 2,
        "aiAnalyticsPerDay": 20,
        "aiSlugsPerDay": 30
      },
      "features": {
        "passwordProtection": true,
        "customQr": true,
        "deviceTargeting": false,
        "geoTargeting": false,
        "abTesting": false,
        "customOg": true,
        "apiAccess": true
      }
    },
    "folders": [
      {
        "id": "6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e",
        "name": "Campaigns",
        "created_at": "2026-10-01T08:00:00.000Z",
        "updated_at": "2026-10-01T08:00:00.000Z",
        "link_count": 12
      }
    ],
    "tags": [
      {
        "id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
        "name": "launch",
        "color": "#3b82f6",
        "created_at": "2026-10-01T08:00:00.000Z",
        "updated_at": "2026-10-01T08:00:00.000Z",
        "link_count": 4
      }
    ],
    "domains": [],
    "members": {
      "members": [],
      "invitations": []
    }
  }
}

Other responses: 401 · 403 · 429

What you get back

200 with the usual envelope — status, success, message, data. data has these fields:

  • workspace_idstring · uuidrequired

    The key's workspace.

  • profileobjectrequired

    The key creator's profile: id, email, display_name, photo_url, created_at.

  • is_app_adminboolean

    Internal flag. Ignore it.

  • workspacesarray of objectrequired

    The key's own workspace (an API key never sees the creator's other workspaces): id, name, owner_id, plan_type, subscription_status, role, timestamps, access_state — null for a normal workspace, awaiting_payment before its first payment, paused when it is read-only (its paid plan ended, or it stopped being the default) — and is_default, true when this is the workspace OWNER's default workspace (the one that stays free); for a member's key it reflects the owner's flag, not yours.

  • usageUsagerequired
  • usage.workspace_idstring · uuidrequired

    The workspace.

  • usage.links_created_this_monthintegerrequired

    Links created in the current monthly period and not deleted.

    Min 0

  • usage.clicks_this_monthintegerrequired

    Clicks in the current monthly period.

    Min 0

  • usage.ai_analytics_todayinteger

    AI analytics chat questions asked today (UTC).

    Min 0

  • usage.ai_slug_gens_todayinteger

    AI slug calls used today (UTC).

    Min 0

  • usage.last_reset_aistring · date or null

    The UTC date the daily AI counters were last reset.

  • usage.last_reset_monthlystring · date

    The first day of the current monthly period.

  • usage.next_resetstring · date-timerequired

    When the monthly counters reset.

  • usage.updated_atstring · date-time or null

    When the stored counters last changed.

  • usage.plan_keystringrequired

    The workspace's plan.

    One of: free, starter, pro, business

  • usage.plan_links_limitintegerrequired

    Links allowed per month. -1 means no limit.

  • usage.plan_domains_limitintegerrequired

    Custom domains allowed. -1 means no limit.

  • usage.is_simulatedboolean

    Internal testing flag. Always false for you.

  • subscriptionobjectrequired

    The plan: plan, plan_name, period, status, limits (links, clicks, domains, retention days, folders, tags, seats and AI quotas; -1 = no limit) and features (which paid features are on). subscription_id is always null for an API key.

  • foldersarray of Folderrequired

    Every folder, with link_count.

  • folders[].idstring · uuidrequired

    The folder's id.

  • folders[].namestringrequired

    The folder's name.

    Up to 20 characters

  • folders[].created_atstring · date-time or nullrequired

    When the folder was created.

  • folders[].updated_atstring · date-time or nullrequired

    When it last changed.

  • folders[].link_countinteger

    How many links are in the folder. Only in list results and on create.

    Min 0

  • tagsarray of Tagrequired

    Every tag, with link_count.

  • tags[].idstring · uuidrequired

    The tag's id.

  • tags[].namestringrequired

    The tag's name.

    Up to 10 characters

  • tags[].colorstringrequired

    The tag's colour as #rrggbb, or an empty string.

  • tags[].created_atstring · date-time or nullrequired

    When the tag was created.

  • tags[].updated_atstring · date-time or nullrequired

    When it last changed.

  • tags[].link_countintegerrequired

    How many links carry the tag.

    Min 0

  • domainsarray of Domainrequired

    The workspace's custom domains.

  • domains[].idstring · uuidrequired

    The domain's id. Send it as custom_domain_id to use the domain for a link.

  • domains[].workspace_idstring · uuidrequired

    The workspace it belongs to.

  • domains[].domain_namestringrequired

    The hostname, like links.example.com.

  • domains[].cloudflare_hostname_idstring or null

    Internal id at Clikso's network provider.

  • domains[].verification_detailsobject or null

    DNS setup details while the domain is being verified.

  • domains[].is_verifiedbooleanrequired

    true when the domain is set up and can be used for links.

  • domains[].ssl_statusstringrequired

    State of the domain's HTTPS certificate.

    One of: pending, active, failed

  • domains[].is_defaultbooleanrequired

    true for the workspace's default custom domain.

  • domains[].created_atstring · date-timerequired

    When the domain was added.

  • domains[].updated_atstring · date-timerequired

    When it last changed.

  • membersobject

    The workspace's members and pending invitations. With an API key, invitations come without their token.

Common errors

401UNAUTHORIZEDThe API key is missing, malformed or unknown.
403FORBIDDENThe Workspace-Id header names a different workspace than the key's.
429RATE_LIMITEDThe key went over its per-minute request limit.

Every code and what to do about it: Errors.

Good to know

  • workspace_id is the key's own workspace. A key always works on that one workspace.
  • subscription.limits uses -1 for "no limit".
  • With an API key, workspaces holds only the key's own workspace, pending invitations come without their token, and subscription.subscription_id is null.
  • This is a large response. If you only need numbers, Get usage is smaller.