Introduction
Welcome to the Sqish URL Shortener API documentation. This simple yet powerful API allows you to programmatically shorten long URLs into concise https://www.sqish.uk/...
links, perfect for sharing in space-constrained environments like SMS or social media.
This document provides information on authentication, endpoints, request/response formats, and code examples to help you integrate Sqish URL shortening into your applications.
Authentication
Access to the Sqish URL Shortener API is controlled via API keys. You must include your unique API key in every request.
You can generate and manage your API keys from your Sqish URL Shortener Dashboard.
API Endpoint
All API requests should be directed to the following endpoint using the POST HTTP method:
POST https://www.sqish.uk/api.php
Request Format
Requests can be sent with a Content-Type
header of either application/x-www-form-urlencoded
or application/json
. Parameters should be included in the request body accordingly.
Parameters
Parameter | Type | Required | Description |
---|---|---|---|
api_key |
String | Yes | Your unique Sqish URL Shortener API key obtained from the dashboard. |
url |
String | Yes | The full URL you wish to shorten. It must include the scheme (e.g., http:// or https:// ) and should be URL-encoded if necessary. |
password |
String | No | An optional password to protect the shortened link. Minimum 6 characters if provided. |
max_clicks |
Integer | No | An optional positive integer representing the maximum number of times the link can be clicked before it becomes inactive. Leave blank or null for unlimited clicks. |
Response Format
The API always responds with JSON content (Content-Type: application/json
).
Success Response
A successful request will result in an HTTP 201 Created
status code and a JSON body similar to this:
{
"status": "success",
"message": "Successfully Shortened",
"short_url": "https://www.sqish.uk/aBcDeF",
"original_url": "https://www.example.com/your-long-url",
"password_protected": true, // Only present if a password was set
"max_clicks": 100 // Only present if a click limit was set
}
status
: Always "success" for successful operations.message
: A confirmation message.short_url
: The complete shortened URL generated by Sqish URL Shortener.original_url
: The original URL that was shortened.password_protected
(Optional): Included and set totrue
if a password was successfully applied to the link.max_clicks
(Optional): Included with the integer value if a maximum click limit was successfully applied.
If the URL was already shortened by the same user (and no password/max_clicks were specified in the new request), the API might return a 200 OK
with a slightly different message indicating the existing link is being returned (behaviour depends on server implementation).
Error Response
If there's an issue, the API will typically return an appropriate HTTP status code (e.g., 400, 401, 403, 500) and a JSON body detailing the error:
{
"status": "error",
"message": "Specific error message explaining the problem. [Optional: More details]"
}
status
: Always "error".message
: A human-readable description of the error(s). Multiple errors might be concatenated.
Common error messages include:
API key is required.
(401)Invalid API key.
(403)Invalid or missing URL parameter. Ensure it includes http:// or https://
(400)Password must be at least 6 characters long.
(400)Max Clicks must be a positive whole number (or leave blank/null for unlimited).
(400)An internal database error occurred.
(500)An unexpected server error occurred.
(500)
Code Examples
Replace YOUR_API_KEY_HERE
with your actual key and adjust the URL and optional parameters.
cURL
Basic request:
curl -X POST https://www.sqish.uk/api.php \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "api_key=YOUR_API_KEY_HERE" \
--data-urlencode "url=https://www.example.com/a/very/long/path"
Request with password and max clicks:
curl -X POST https://www.sqish.uk/api.php \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "api_key=YOUR_API_KEY_HERE" \
--data-urlencode "url=https://www.example.com/another/long/path" \
--data-urlencode "password=secret123" \
--data-urlencode "max_clicks=50"
Request using JSON payload:
curl -X POST https://www.sqish.uk/api.php \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"api_key": "YOUR_API_KEY_HERE",
"url": "https://www.example.com/json/request/url",
"password": "jsonPassword!",
"max_clicks": 25
}'
PHP (using cURL)
<?php
$apiKey = 'YOUR_API_KEY_HERE';
$urlToShorten = 'https://www.example.com/php/example';
$apiUrl = 'https://www.sqish.uk/api.php';
// --- Request Data ---
$postData = [
'api_key' => $apiKey,
'url' => $urlToShorten,
// --- Optional ---
// 'password' => 'phpSecurePwd',
// 'max_clicks' => 10
];
// --- Send Request ---
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $apiUrl);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData)); // Use http_build_query for form-urlencoded
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Accept: application/json']);
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); // Keep true for production
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$err = curl_error($ch);
curl_close($ch);
// --- Handle Response ---
if ($err) {
echo "cURL Error: " . $err;
} else {
echo "HTTP Status: " . $httpCode . "\n";
$data = json_decode($response, true);
if ($data === null) {
echo "Error: Invalid JSON received from server.\n";
echo "Raw Response: " . $response;
} elseif (isset($data['status']) && $data['status'] === 'success') {
echo "Short URL: " . ($data['short_url'] ?? 'N/A') . "\n";
if (isset($data['password_protected']) && $data['password_protected']) {
echo "Password protection applied.\n";
}
if (isset($data['max_clicks'])) {
echo "Max clicks set to: " . $data['max_clicks'] . "\n";
}
} else {
echo "API Error: " . ($data['message'] ?? 'Unknown error') . "\n";
}
}
?>
Python (using Requests)
import requests
import json
api_key = 'YOUR_API_KEY_HERE'
url_to_shorten = 'https://www.example.com/python/request/example'
api_url = 'https://www.sqish.uk/api.php'
payload = {
'api_key': api_key,
'url': url_to_shorten,
# --- Optional ---
# 'password': 'pySecurePassword',
# 'max_clicks': 20
}
headers = {
# Use 'application/x-www-form-urlencoded' if sending as form data
'Content-Type': 'application/x-www-form-urlencoded',
'Accept': 'application/json'
}
try:
# Send as form data (requests handles encoding)
response = requests.post(api_url, data=payload, headers=headers, timeout=15)
# Or send as JSON:
# headers['Content-Type'] = 'application/json'
# response = requests.post(api_url, data=json.dumps(payload), headers=headers, timeout=15)
response.raise_for_status() # Raise HTTPError for bad responses (4xx or 5xx)
data = response.json()
if data.get('status') == 'success' and 'short_url' in data:
print(f"Success! Short URL: {data['short_url']}")
if data.get('password_protected'):
print("Password protection applied.")
if data.get('max_clicks') is not None:
print(f"Max clicks set to: {data['max_clicks']}")
else:
print(f"API Error: {data.get('message', 'Unknown error')}")
except requests.exceptions.HTTPError as http_err:
print(f"HTTP error occurred: {http_err}")
try:
print(f"Error details: {response.json()}") # Try to print JSON error details
except json.JSONDecodeError:
print(f"Raw response: {response.text}")
except requests.exceptions.RequestException as req_err:
print(f"Request failed: {req_err}")
except json.JSONDecodeError:
print("Failed to decode JSON response.")
print(f"Raw response: {response.text}")
JavaScript (Browser Fetch API)
const apiUrl = 'https://www.sqish.uk/api.php';
// WARNING: Do not expose your real API key in client-side code!
const apiKey = 'YOUR_API_KEY_HERE_BUT_REALLY_DONT_DO_THIS';
const urlToShorten = 'https://www.example.com/fetch/example/long/url';
const formData = new URLSearchParams();
formData.append('api_key', apiKey);
formData.append('url', urlToShorten);
// --- Optional ---
// formData.append('password', 'jsPass123');
// formData.append('max_clicks', '15');
fetch(apiUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Accept': 'application/json'
},
body: formData.toString() // Send as form-urlencoded
})
.then(async response => { // Make the callback async to use await for json parsing
const responseBody = await response.json(); // Try to parse JSON regardless of status
if (!response.ok) {
// Throw an error with message from JSON body if available
throw new Error(responseBody.message || `HTTP error ${response.status}`);
}
return responseBody; // Return parsed JSON
})
.then(data => {
if (data.status === 'success' && data.short_url) {
console.log('Short URL:', data.short_url);
if (data.password_protected) {
console.log('Password protection applied.');
}
if (data.max_clicks !== undefined) { // Check if key exists
console.log('Max clicks:', data.max_clicks);
}
// Use the short URL in your application
} else {
// This part might not be reached if error was thrown above, but good as fallback
console.error('API Error:', data.message || 'Unknown error from API');
}
})
.catch(error => {
console.error('Fetch Error:', error.message || error);
});
/*
// Example sending as JSON (less common from browser JS for simple POST)
fetch(apiUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json', // Set Content-Type to JSON
'Accept': 'application/json'
},
body: JSON.stringify({ // Stringify the data object
api_key: apiKey,
url: urlToShorten,
// password: 'jsPass123',
// max_clicks: 15
})
})
.then(...) // Rest of the promise chain is similar
.catch(...);
*/