Developer docs

API reference / Links

Check a slug

GEThttps://app.clik.so/api/links/slug-check

In short

Tells you whether a short code is free on a domain, so you can check before you create a link.

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/links/slug-check?slug=summer-sale&domain=clik.is" \
  -H "Authorization: Bearer $CLIKSO_API_KEY"
const res = await fetch("https://app.clik.so/api/links/slug-check?slug=summer-sale&domain=clik.is", {
  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/slug-check",
    headers={"Authorization": f"Bearer {os.environ['CLIKSO_API_KEY']}"},
    params={
        "slug": "summer-sale",
        "domain": "clik.is",
    },
)

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

Uses requests. Set CLIKSO_API_KEY first.

<?php

$ch = curl_init('https://app.clik.so/api/links/slug-check?slug=summer-sale&domain=clik.is');
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/slug-check?slug=summer-sale&domain=clik.is", 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/slug-check?slug=summer-sale&domain=clik.is')
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/links/slug-check?slug=summer-sale&domain=clik.is"))
            .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/slug-check?slug=summer-sale&domain=clik.is");
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/slug-check?slug=summer-sale&domain=clik.is");
    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": {
    "available": true,
    "slug": "summer-sale"
  }
}

Other responses: 401 · 422 · 429

Query parameters

  • slugstringrequired

    The short code to check.

  • domainstring

    The domain to check it on. Defaults to clik.is.

    Default clik.is

What you get back

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

  • availablebooleanrequired

    true when no link uses this code on the domain right now and create would accept it.

  • slugstringrequired

    The code you asked about.

  • reasonstring

    Only when available is false for a reason other than "someone uses it". invalid_format: the code breaks the format rules (message says which). upgrade_required: a nested code (with /) on a plan without them — Starter and up have them (since 1.64.0). reserved: a reserved name on a Clikso domain. Added in 1.61.1; more values may appear.

    One of: invalid_format, upgrade_required, reserved

  • messagestring

    A short, plain sentence to show the user. Only with reason.

Common errors

401UNAUTHORIZEDThe API key is missing, malformed or unknown.
422VALIDATION_ERRORThe slug query parameter is missing.
429RATE_LIMITEDThe key went over its per-minute request limit.

Every code and what to do about it: Errors.

Good to know

  • available: true is a snapshot, not a reservation. Someone else can still take the code before you create the link, so handle 409 CONFLICT on create anyway.
  • A code create would refuse comes back as available: false with a reason: invalid_format (the code breaks the format rules — 3 to 30 letters, digits or hyphens, and / only as in acme/launch), upgrade_required (a nested code with / on a plan without them — Free; since 1.64.0) or reserved (an official-sounding name such as pricing on clik.is, or a nested code that starts with one). message says what to do, in plain English. It is still a 200.
  • The checks run in the order create runs them: format first, then the plan, then reserved names, then whether someone uses it.
  • A code someone already uses comes back as just available: false, with no reason.
  • domain defaults to clik.is.