Guides
Folders and tags
In short
A folder holds links, and each link sits in at most one folder. A tag is a coloured label, and a link can have many. You create both with the API, then send their ids when you create or update a link.
You need
- API key
- Read to list folders and tags. Write to create, change or delete them.
- Role
- Editor or admin to make changes. Any member can read.
- Plan
- Any plan, including Free. Each plan allows a set number of folders and tags.
Create a folder
Folder names can be up to 20 characters.
curl -X POST "https://app.clik.so/api/folders" \
-H "Authorization: Bearer $CLIKSO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Campaigns"
}'const res = await fetch("https://app.clik.so/api/folders", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.CLIKSO_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"name": "Campaigns"
}),
});
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.post(
"https://app.clik.so/api/folders",
headers={"Authorization": f"Bearer {os.environ['CLIKSO_API_KEY']}"},
json={
"name": "Campaigns",
},
)
print(response.status_code, response.json())Uses requests. Set CLIKSO_API_KEY first.
<?php
$body = <<<'JSON'
{
"name": "Campaigns"
}
JSON;
$ch = curl_init('https://app.clik.so/api/folders');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('CLIKSO_API_KEY'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => $body,
]);
$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"
"strings"
)
func main() {
body := strings.NewReader(`{
"name": "Campaigns"
}`)
req, err := http.NewRequest("POST", "https://app.clik.so/api/folders", body)
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("CLIKSO_API_KEY"))
req.Header.Set("Content-Type", "application/json")
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"
require "json"
uri = URI('https://app.clik.so/api/folders')
request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer #{ENV.fetch("CLIKSO_API_KEY")}"
request["Content-Type"] = "application/json"
request.body = {
'name' => 'Campaigns'
}.to_json
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(request)
end
puts response.code, response.bodyUses 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 {
String body = """
{
"name": "Campaigns"
}
""";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://app.clik.so/api/folders"))
.header("Authorization", "Bearer " + System.getenv("CLIKSO_API_KEY"))
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString(body))
.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("POST"), "https://app.clik.so/api/folders");
request.Headers.Authorization = new AuthenticationHeaderValue(
"Bearer", Environment.GetEnvironmentVariable("CLIKSO_API_KEY"));
request.Content = new StringContent(
"""
{
"name": "Campaigns"
}
""",
System.Text.Encoding.UTF8,
"application/json");
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());
headers = curl_slist_append(headers, "Content-Type: application/json");
const char* body = R"json({
"name": "Campaigns"
})json";
std::string response;
curl_easy_setopt(curl, CURLOPT_URL, "https://app.clik.so/api/folders");
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body);
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.
{
"status": 201,
"success": true,
"message": "Created",
"data": {
"id": "6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e",
"name": "Campaigns",
"created_at": "2026-10-09T09:30:00.000Z",
"updated_at": "2026-10-09T09:30:00.000Z",
"link_count": 0
}
}Keep the id. You use it to put links in the folder.
Create a tag
Tag names can be up to 10 characters. The colour is optional. If you send one, use a six-digit hex code like #3b82f6.
curl -X POST "https://app.clik.so/api/tags" \
-H "Authorization: Bearer $CLIKSO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "launch",
"color": "#3b82f6"
}'const res = await fetch("https://app.clik.so/api/tags", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.CLIKSO_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"name": "launch",
"color": "#3b82f6"
}),
});
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.post(
"https://app.clik.so/api/tags",
headers={"Authorization": f"Bearer {os.environ['CLIKSO_API_KEY']}"},
json={
"name": "launch",
"color": "#3b82f6",
},
)
print(response.status_code, response.json())Uses requests. Set CLIKSO_API_KEY first.
<?php
$body = <<<'JSON'
{
"name": "launch",
"color": "#3b82f6"
}
JSON;
$ch = curl_init('https://app.clik.so/api/tags');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('CLIKSO_API_KEY'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => $body,
]);
$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"
"strings"
)
func main() {
body := strings.NewReader(`{
"name": "launch",
"color": "#3b82f6"
}`)
req, err := http.NewRequest("POST", "https://app.clik.so/api/tags", body)
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("CLIKSO_API_KEY"))
req.Header.Set("Content-Type", "application/json")
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"
require "json"
uri = URI('https://app.clik.so/api/tags')
request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer #{ENV.fetch("CLIKSO_API_KEY")}"
request["Content-Type"] = "application/json"
request.body = {
'name' => 'launch',
'color' => '#3b82f6'
}.to_json
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(request)
end
puts response.code, response.bodyUses 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 {
String body = """
{
"name": "launch",
"color": "#3b82f6"
}
""";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://app.clik.so/api/tags"))
.header("Authorization", "Bearer " + System.getenv("CLIKSO_API_KEY"))
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString(body))
.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("POST"), "https://app.clik.so/api/tags");
request.Headers.Authorization = new AuthenticationHeaderValue(
"Bearer", Environment.GetEnvironmentVariable("CLIKSO_API_KEY"));
request.Content = new StringContent(
"""
{
"name": "launch",
"color": "#3b82f6"
}
""",
System.Text.Encoding.UTF8,
"application/json");
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());
headers = curl_slist_append(headers, "Content-Type: application/json");
const char* body = R"json({
"name": "launch",
"color": "#3b82f6"
})json";
std::string response;
curl_easy_setopt(curl, CURLOPT_URL, "https://app.clik.so/api/tags");
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body);
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.
{
"status": 201,
"success": true,
"message": "Created",
"data": {
"id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"name": "launch",
"color": "#3b82f6",
"created_at": "2026-10-09T09:30:00.000Z",
"updated_at": "2026-10-09T09:30:00.000Z",
"link_count": 0
}
}File and tag a link
Send folder_id and tags when you create a link, or later with an update. tags is a list of tag ids.
curl -X PUT "https://app.clik.so/api/links/3f6c1a2e-9b4d-4e8f-a1c2-7d9e0f1a2b3c" \
-H "Authorization: Bearer $CLIKSO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"folder_id": "6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e",
"tags": [
"1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d"
]
}'const res = await fetch("https://app.clik.so/api/links/3f6c1a2e-9b4d-4e8f-a1c2-7d9e0f1a2b3c", {
method: "PUT",
headers: {
Authorization: `Bearer ${process.env.CLIKSO_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"folder_id": "6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e",
"tags": [
"1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d"
]
}),
});
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.put(
"https://app.clik.so/api/links/3f6c1a2e-9b4d-4e8f-a1c2-7d9e0f1a2b3c",
headers={"Authorization": f"Bearer {os.environ['CLIKSO_API_KEY']}"},
json={
"folder_id": "6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e",
"tags": [
"1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
],
},
)
print(response.status_code, response.json())Uses requests. Set CLIKSO_API_KEY first.
<?php
$body = <<<'JSON'
{
"folder_id": "6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e",
"tags": [
"1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d"
]
}
JSON;
$ch = curl_init('https://app.clik.so/api/links/3f6c1a2e-9b4d-4e8f-a1c2-7d9e0f1a2b3c');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('CLIKSO_API_KEY'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => $body,
]);
$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"
"strings"
)
func main() {
body := strings.NewReader(`{
"folder_id": "6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e",
"tags": [
"1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d"
]
}`)
req, err := http.NewRequest("PUT", "https://app.clik.so/api/links/3f6c1a2e-9b4d-4e8f-a1c2-7d9e0f1a2b3c", body)
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("CLIKSO_API_KEY"))
req.Header.Set("Content-Type", "application/json")
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"
require "json"
uri = URI('https://app.clik.so/api/links/3f6c1a2e-9b4d-4e8f-a1c2-7d9e0f1a2b3c')
request = Net::HTTP::Put.new(uri)
request["Authorization"] = "Bearer #{ENV.fetch("CLIKSO_API_KEY")}"
request["Content-Type"] = "application/json"
request.body = {
'folder_id' => '6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e',
'tags' => [
'1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d'
]
}.to_json
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(request)
end
puts response.code, response.bodyUses 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 {
String body = """
{
"folder_id": "6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e",
"tags": [
"1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d"
]
}
""";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://app.clik.so/api/links/3f6c1a2e-9b4d-4e8f-a1c2-7d9e0f1a2b3c"))
.header("Authorization", "Bearer " + System.getenv("CLIKSO_API_KEY"))
.header("Content-Type", "application/json")
.method("PUT", HttpRequest.BodyPublishers.ofString(body))
.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("PUT"), "https://app.clik.so/api/links/3f6c1a2e-9b4d-4e8f-a1c2-7d9e0f1a2b3c");
request.Headers.Authorization = new AuthenticationHeaderValue(
"Bearer", Environment.GetEnvironmentVariable("CLIKSO_API_KEY"));
request.Content = new StringContent(
"""
{
"folder_id": "6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e",
"tags": [
"1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d"
]
}
""",
System.Text.Encoding.UTF8,
"application/json");
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());
headers = curl_slist_append(headers, "Content-Type: application/json");
const char* body = R"json({
"folder_id": "6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e",
"tags": [
"1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d"
]
})json";
std::string response;
curl_easy_setopt(curl, CURLOPT_URL, "https://app.clik.so/api/links/3f6c1a2e-9b4d-4e8f-a1c2-7d9e0f1a2b3c");
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body);
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.
The update answers with the whole link, now with its folder_id and full tags.
How the two fields behave on an update:
tagsreplaces the link’s whole tag list. Send every tag the link should keep.tags: []removes all tags. Leavetagsout, or sendnull, to keep them as they are.folder_id: nulltakes the link out of its folder.
Move many links at once
To put up to 100 links in one folder, use a bulk update:
curl -X PATCH "https://app.clik.so/api/links/bulk" \
-H "Authorization: Bearer $CLIKSO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"ids": [
"3f6c1a2e-9b4d-4e8f-a1c2-7d9e0f1a2b3c",
"5d4c3b2a-1f0e-4d9c-8b7a-6f5e4d3c2b1a"
],
"folder_id": "6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e"
}'const res = await fetch("https://app.clik.so/api/links/bulk", {
method: "PATCH",
headers: {
Authorization: `Bearer ${process.env.CLIKSO_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"ids": [
"3f6c1a2e-9b4d-4e8f-a1c2-7d9e0f1a2b3c",
"5d4c3b2a-1f0e-4d9c-8b7a-6f5e4d3c2b1a"
],
"folder_id": "6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e"
}),
});
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.patch(
"https://app.clik.so/api/links/bulk",
headers={"Authorization": f"Bearer {os.environ['CLIKSO_API_KEY']}"},
json={
"ids": [
"3f6c1a2e-9b4d-4e8f-a1c2-7d9e0f1a2b3c",
"5d4c3b2a-1f0e-4d9c-8b7a-6f5e4d3c2b1a",
],
"folder_id": "6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e",
},
)
print(response.status_code, response.json())Uses requests. Set CLIKSO_API_KEY first.
<?php
$body = <<<'JSON'
{
"ids": [
"3f6c1a2e-9b4d-4e8f-a1c2-7d9e0f1a2b3c",
"5d4c3b2a-1f0e-4d9c-8b7a-6f5e4d3c2b1a"
],
"folder_id": "6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e"
}
JSON;
$ch = curl_init('https://app.clik.so/api/links/bulk');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PATCH',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('CLIKSO_API_KEY'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => $body,
]);
$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"
"strings"
)
func main() {
body := strings.NewReader(`{
"ids": [
"3f6c1a2e-9b4d-4e8f-a1c2-7d9e0f1a2b3c",
"5d4c3b2a-1f0e-4d9c-8b7a-6f5e4d3c2b1a"
],
"folder_id": "6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e"
}`)
req, err := http.NewRequest("PATCH", "https://app.clik.so/api/links/bulk", body)
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("CLIKSO_API_KEY"))
req.Header.Set("Content-Type", "application/json")
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"
require "json"
uri = URI('https://app.clik.so/api/links/bulk')
request = Net::HTTP::Patch.new(uri)
request["Authorization"] = "Bearer #{ENV.fetch("CLIKSO_API_KEY")}"
request["Content-Type"] = "application/json"
request.body = {
'ids' => [
'3f6c1a2e-9b4d-4e8f-a1c2-7d9e0f1a2b3c',
'5d4c3b2a-1f0e-4d9c-8b7a-6f5e4d3c2b1a'
],
'folder_id' => '6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e'
}.to_json
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(request)
end
puts response.code, response.bodyUses 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 {
String body = """
{
"ids": [
"3f6c1a2e-9b4d-4e8f-a1c2-7d9e0f1a2b3c",
"5d4c3b2a-1f0e-4d9c-8b7a-6f5e4d3c2b1a"
],
"folder_id": "6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e"
}
""";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://app.clik.so/api/links/bulk"))
.header("Authorization", "Bearer " + System.getenv("CLIKSO_API_KEY"))
.header("Content-Type", "application/json")
.method("PATCH", HttpRequest.BodyPublishers.ofString(body))
.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("PATCH"), "https://app.clik.so/api/links/bulk");
request.Headers.Authorization = new AuthenticationHeaderValue(
"Bearer", Environment.GetEnvironmentVariable("CLIKSO_API_KEY"));
request.Content = new StringContent(
"""
{
"ids": [
"3f6c1a2e-9b4d-4e8f-a1c2-7d9e0f1a2b3c",
"5d4c3b2a-1f0e-4d9c-8b7a-6f5e4d3c2b1a"
],
"folder_id": "6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e"
}
""",
System.Text.Encoding.UTF8,
"application/json");
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());
headers = curl_slist_append(headers, "Content-Type: application/json");
const char* body = R"json({
"ids": [
"3f6c1a2e-9b4d-4e8f-a1c2-7d9e0f1a2b3c",
"5d4c3b2a-1f0e-4d9c-8b7a-6f5e4d3c2b1a"
],
"folder_id": "6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e"
})json";
std::string response;
curl_easy_setopt(curl, CURLOPT_URL, "https://app.clik.so/api/links/bulk");
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PATCH");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body);
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.
{
"status": 200,
"success": true,
"message": "Success",
"data": {
"updated_count": 2
}
}There is no bulk tagging. To tag many links, update them one by one.
Find links by folder or tag
Filter the link list with folder_id, tags, or both. tags takes tag ids, separated by commas. A link matches if it has at least one of them.
curl "https://app.clik.so/api/links?folder_id=6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e&tags=1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d&limit=20" \
-H "Authorization: Bearer $CLIKSO_API_KEY"const res = await fetch("https://app.clik.so/api/links?folder_id=6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e&tags=1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d&limit=20", {
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/links",
headers={"Authorization": f"Bearer {os.environ['CLIKSO_API_KEY']}"},
params={
"folder_id": "6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e",
"tags": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"limit": 20,
},
)
print(response.status_code, response.json())Uses requests. Set CLIKSO_API_KEY first.
<?php
$ch = curl_init('https://app.clik.so/api/links?folder_id=6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e&tags=1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d&limit=20');
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/links?folder_id=6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e&tags=1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d&limit=20", 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/links?folder_id=6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e&tags=1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d&limit=20')
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.bodyUses 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/links?folder_id=6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e&tags=1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d&limit=20"))
.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/links?folder_id=6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e&tags=1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d&limit=20");
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/links?folder_id=6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e&tags=1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d&limit=20");
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.
You get a page of links in data, and paging details in meta. See Manage links for paging.
Rename and delete
Rename a folder or a tag with PUT and the new value:
curl -X PUT "https://app.clik.so/api/tags/1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d" \
-H "Authorization: Bearer $CLIKSO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "promo",
"color": "#16a34a"
}'const res = await fetch("https://app.clik.so/api/tags/1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d", {
method: "PUT",
headers: {
Authorization: `Bearer ${process.env.CLIKSO_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"name": "promo",
"color": "#16a34a"
}),
});
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.put(
"https://app.clik.so/api/tags/1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
headers={"Authorization": f"Bearer {os.environ['CLIKSO_API_KEY']}"},
json={
"name": "promo",
"color": "#16a34a",
},
)
print(response.status_code, response.json())Uses requests. Set CLIKSO_API_KEY first.
<?php
$body = <<<'JSON'
{
"name": "promo",
"color": "#16a34a"
}
JSON;
$ch = curl_init('https://app.clik.so/api/tags/1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('CLIKSO_API_KEY'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => $body,
]);
$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"
"strings"
)
func main() {
body := strings.NewReader(`{
"name": "promo",
"color": "#16a34a"
}`)
req, err := http.NewRequest("PUT", "https://app.clik.so/api/tags/1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d", body)
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("CLIKSO_API_KEY"))
req.Header.Set("Content-Type", "application/json")
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"
require "json"
uri = URI('https://app.clik.so/api/tags/1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d')
request = Net::HTTP::Put.new(uri)
request["Authorization"] = "Bearer #{ENV.fetch("CLIKSO_API_KEY")}"
request["Content-Type"] = "application/json"
request.body = {
'name' => 'promo',
'color' => '#16a34a'
}.to_json
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(request)
end
puts response.code, response.bodyUses 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 {
String body = """
{
"name": "promo",
"color": "#16a34a"
}
""";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://app.clik.so/api/tags/1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d"))
.header("Authorization", "Bearer " + System.getenv("CLIKSO_API_KEY"))
.header("Content-Type", "application/json")
.method("PUT", HttpRequest.BodyPublishers.ofString(body))
.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("PUT"), "https://app.clik.so/api/tags/1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d");
request.Headers.Authorization = new AuthenticationHeaderValue(
"Bearer", Environment.GetEnvironmentVariable("CLIKSO_API_KEY"));
request.Content = new StringContent(
"""
{
"name": "promo",
"color": "#16a34a"
}
""",
System.Text.Encoding.UTF8,
"application/json");
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());
headers = curl_slist_append(headers, "Content-Type: application/json");
const char* body = R"json({
"name": "promo",
"color": "#16a34a"
})json";
std::string response;
curl_easy_setopt(curl, CURLOPT_URL, "https://app.clik.so/api/tags/1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d");
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body);
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.
{
"status": 200,
"success": true,
"message": "Success",
"data": {
"id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"name": "promo",
"color": "#16a34a",
"created_at": "2026-10-01T08:00:00.000Z",
"updated_at": "2026-10-09T09:30:00.000Z",
"link_count": 4
}
}Delete them like this:
curl -X DELETE "https://app.clik.so/api/folders/6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e" \
-H "Authorization: Bearer $CLIKSO_API_KEY"const res = await fetch("https://app.clik.so/api/folders/6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e", {
method: "DELETE",
headers: {
Authorization: `Bearer ${process.env.CLIKSO_API_KEY}`,
},
});
console.log(res.status); // 204 = done, no bodyUses fetch (Node 18+ or the browser). Set CLIKSO_API_KEY first.
import os
import requests
response = requests.delete(
"https://app.clik.so/api/folders/6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e",
headers={"Authorization": f"Bearer {os.environ['CLIKSO_API_KEY']}"},
)
print(response.status_code) # 204 = done, no bodyUses requests. Set CLIKSO_API_KEY first.
<?php
$ch = curl_init('https://app.clik.so/api/folders/6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'DELETE',
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; // 204 = done, no bodyUses the curl extension. Set CLIKSO_API_KEY first.
package main
import (
"fmt"
"io"
"net/http"
"os"
)
func main() {
req, err := http.NewRequest("DELETE", "https://app.clik.so/api/folders/6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e", 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/folders/6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e')
request = Net::HTTP::Delete.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 # 204 = done, no bodyUses 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/folders/6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e"))
.header("Authorization", "Bearer " + System.getenv("CLIKSO_API_KEY"))
.DELETE()
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode());
}
}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("DELETE"), "https://app.clik.so/api/folders/6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e");
request.Headers.Authorization = new AuthenticationHeaderValue(
"Bearer", Environment.GetEnvironmentVariable("CLIKSO_API_KEY"));
using var response = await client.SendAsync(request);
Console.WriteLine((int)response.StatusCode);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/folders/6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e");
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE");
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 204 No Content — an empty body means it worked.
Deleting a folder keeps its links. They simply move out of the folder. Deleting a tag removes it from every link, and you cannot undo it.
How many you can have
Folders and tags per workspace
- Folders
- 3
- Tags
- 5
| Limit | Free | Starter | Pro | Business |
|---|---|---|---|---|
| Folders | 3 | 6 | 15 | 40 |
| Tags | 5 | 10 | 20 | 50 |
An API key that tries to create one more than the plan allows gets 402 UPGRADE_REQUIRED.
What you get back
- List calls return an array in
data, sorted by name. Each item hasid,name,created_at,updated_atandlink_count. Tags also havecolor. - Create returns
201and the new folder or tag, withlink_count: 0. - Update returns
200and the changed folder or tag. - Delete returns
204with an empty body.
Tags always come with their real link_count. A single folder, from get or update, has no link_count, so use the list call to count a folder's links.
Common errors
UPGRADE_REQUIREDThe workspace already has as many folders or tags as its plan allows.Leave the field out, or upgrade the workspace.Leave the field out, or upgrade the workspace.FORBIDDENThe key has only Read permission, or its owner is a viewer.Check the key’s permission and your role. If you send Workspace-Id, it must match the key’s workspace.Check the key’s permission and your role. If you send Workspace-Id, it must match the key’s workspace.NOT_FOUNDNo folder or tag with that id in this workspace.Check the id. Ids from another workspace are never found.Check the id. Ids from another workspace are never found.VALIDATION_ERRORThe name is empty or too long, the colour is not #rrggbb, or a link update names a folder or tag id from another workspace.Fix the field and send the request again.Fix the field and send the request again.Good to know
- Folders are flat. There are no folders inside folders.
- A link sits in at most one folder, but it can have any number of tags.
- Folders and tags only organise links. They do not limit who can see them. Every member of the workspace sees every link.
- The bulk call moves links between folders, archives them or deletes them. It cannot add tags.
- Each call costs one request from the key’s per-minute limit. See Limits.
