Check Slug Availability
Check if a project slug is available before creating a project
Check Slug Endpoint
Validate whether a project slug is available for use in your organization. This endpoint is useful for providing real-time feedback in forms before attempting to create a project.
Endpoint
GET /api/projects/check-slugAuthentication
Requires authentication. Include your session token in the request headers:
Authorization: Bearer <session_token>Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
slug | string | Yes | The slug to check availability for |
excludeId | string | No | Project ID to exclude from the check (useful when updating) |
Request Examples
Check if a slug is available
curl -X GET "https://api.yourdomain.com/api/projects/check-slug?slug=my-new-project" \
-H "Authorization: Bearer YOUR_TOKEN"Check availability excluding current project (for updates)
curl -X GET "https://api.yourdomain.com/api/projects/check-slug?slug=my-new-project&excludeId=proj_123456789" \
-H "Authorization: Bearer YOUR_TOKEN"Response
Available Slug
{
"success": true,
"data": {
"available": true,
"slug": "my-new-project",
"suggestions": []
},
"message": "Slug is available"
}Unavailable Slug
{
"success": true,
"data": {
"available": false,
"slug": "my-project",
"suggestions": [
"my-project-2",
"my-project-2024",
"my-project-team"
]
},
"message": "Slug is not available"
}Response Fields
| Field | Type | Description |
|---|---|---|
available | boolean | Whether the slug can be used |
slug | string | The slug that was checked |
suggestions | array | Alternative slug suggestions if unavailable |
Slug Validation Rules
Slugs must follow these rules:
- 3-63 characters in length
- Only lowercase letters, numbers, and hyphens
- Must start with a letter
- Must end with a letter or number
- Cannot contain consecutive hyphens
- Must be unique per organization
Error Responses
Invalid Slug Format
{
"success": false,
"data": null,
"error": {
"code": "BAD_REQUEST",
"message": "Invalid slug format. Slug must be 3-63 characters, lowercase letters, numbers, and hyphens only."
}
}Missing Slug Parameter
{
"success": false,
"data": null,
"error": {
"code": "BAD_REQUEST",
"message": "Missing required parameter: slug"
}
}Unauthorized
{
"success": false,
"data": null,
"error": {
"code": "UNAUTHORIZED",
"message": "Authentication required"
}
}Frontend Integration Example
import { useState, useEffect, useCallback } from 'react';
import { debounce } from 'lodash';
function useSlugCheck() {
const [isAvailable, setIsAvailable] = useState<boolean | null>(null);
const [suggestions, setSuggestions] = useState<string[]>([]);
const [isChecking, setIsChecking] = useState(false);
const checkSlug = useCallback(
debounce(async (slug: string, excludeId?: string) => {
if (!slug || slug.length < 3) {
setIsAvailable(null);
return;
}
setIsChecking(true);
try {
const params = new URLSearchParams({ slug });
if (excludeId) params.append('excludeId', excludeId);
const response = await fetch(`/api/projects/check-slug?${params}`, {
headers: {
'Authorization': `Bearer ${getToken()}`
}
});
const result = await response.json();
if (result.success) {
setIsAvailable(result.data.available);
setSuggestions(result.data.suggestions);
}
} finally {
setIsChecking(false);
}
}, 300),
[]
);
return { isAvailable, suggestions, isChecking, checkSlug };
}
// Usage in a form component
function ProjectForm({ project }: { project?: Project }) {
const [slug, setSlug] = useState(project?.slug || '');
const { isAvailable, suggestions, isChecking, checkSlug } = useSlugCheck();
useEffect(() => {
checkSlug(slug, project?.id);
}, [slug, project?.id, checkSlug]);
return (
<form>
<div>
<label>Project Slug</label>
<input
type="text"
value={slug}
onChange={(e) => setSlug(e.target.value)}
placeholder="my-awesome-project"
/>
{isChecking && <span>Checking availability...</span>}
{!isChecking && isAvailable === true && (
<span className="text-green-600">Available</span>
)}
{!isChecking && isAvailable === false && (
<div>
<span className="text-red-600">Not available</span>
{suggestions.length > 0 && (
<div>
<p>Suggestions:</p>
<ul>
{suggestions.map((s) => (
<li key={s}>
<button type="button" onClick={() => setSlug(s)}>
{s}
</button>
</li>
))}
</ul>
</div>
)}
</div>
)}
</div>
</form>
);
}Rate Limits
- 60 requests per minute per user (higher than standard due to real-time validation use case)
Notes
- The slug check is scoped to your organization. A slug may be unavailable in your organization but available globally.
- Suggestions are generated by appending numbers, years, or common suffixes to the requested slug.
- The
excludeIdparameter is useful when editing an existing project and you want to allow keeping the current slug.