[ Skills ]
Lab Nocturne Images works natively with CLI agents through skills. Install once, and your agent can upload, list, and manage images with natural language.
Install
Add image skills to your agent with a single command:
npx skills install jjenkins/agent-image-skillsAvailable Skills
Once installed, your agent has access to the following skills:
| Skill | Trigger | Description |
|---|---|---|
image-upload | "upload this image" | Upload an image and get back a CDN URL |
image-files | "list my images" | List uploaded files with pagination and sorting |
image-stats | "show my usage" | View storage, bandwidth, and quota usage |
image-delete | "delete this image" | Soft-delete a file by ID |
image-key | "get an API key" | Generate a test API key instantly |
Compatibility: Works with Claude Code, OpenClaw, and any CLI agent that supports skills.
[ API Documentation ]
Everything below works with skills or raw HTTP. Install the skills above for the fastest path, or use curl if you prefer working directly with the API.
Quick Start
Get from zero to first upload in under 60 seconds:
curl https://images.labnocturne.com/key{
"api_key": "ln_test_...",
"type": "test",
"message": "Test key created! Files are deleted after 7 days."
}curl -X POST https://images.labnocturne.com/upload \
-H "Authorization: Bearer {{API_KEY}}" \
-F "[email protected]"{
"id": "img_01arz3ndektsv4rrffq69g5fav",
"url": "https://images.labnocturne.com/i/01ARZ3NDEKTSV4RRFFQ69G5FAV.jpg",
"size": 245680,
"uploaded_at": "2024-12-02T10:30:00Z"
}<img src="https://images.labnocturne.com/i/01ARZ3NDEKTSV4RRFFQ69G5FAV.jpg" />Authentication
All authenticated endpoints require a Bearer token in the Authorization header. Test keys start with ln_test_, live keys with ln_live_.
Authorization: Bearer {{API_KEY}}GET /key
Generate a test API key instantly. No email or payment required. Test keys have 100MB storage, 1GB bandwidth, and files auto-delete after 7 days.
Request
Authentication: None required
curl https://images.labnocturne.com/keyResponse
{
"api_key": "{{API_KEY}}",
"type": "test",
"message": "Test key created! Files are deleted after 7 days.",
"limits": {
"max_file_size_mb": 10,
"storage_mb": 100,
"bandwidth_gb_per_month": 1,
"rate_limit_per_hour": 100
},
"docs": "https://images.labnocturne.com/docs"
}Errors
{
"error": {
"message": "Failed to generate API key. Please try again.",
"type": "internal_error",
"code": "key_generation_failed"
}
}POST /upload
Upload an image file and get back a CDN URL. Supports JPG, PNG, GIF, WebP, and SVG formats.
Request
Authentication: Required (Bearer token)
Content-Type: multipart/form-data
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
file | file | Yes | Image file (jpg, png, gif, webp, svg). Max 10MB for test keys, 100MB for paid. |
curl -X POST https://images.labnocturne.com/upload \
-H "Authorization: Bearer {{API_KEY}}" \
-F "[email protected]"Response
{
"id": "img_01arz3ndektsv4rrffq69g5fav",
"url": "https://images.labnocturne.com/i/01ARZ3NDEKTSV4RRFFQ69G5FAV.jpg",
"size": 245680,
"uploaded_at": "2024-12-02T10:30:00Z"
}Errors
{
"error": {
"message": "Invalid API key",
"type": "unauthorized",
"code": "invalid_api_key"
}
}{
"error": {
"message": "File type not supported. Allowed: jpg, png, gif, webp, svg",
"type": "invalid_file_type",
"code": "unsupported_file_type"
}
}{
"error": {
"message": "File size exceeds limit for test keys (10MB). Upgrade to increase limits.",
"type": "file_too_large",
"code": "file_size_exceeded",
"docs": "https://images.labnocturne.com/docs#rate-limits"
}
}{
"error": {
"message": "Rate limit exceeded. Limit: 100 requests/hour. Resets at 2025-12-04T02:46:24Z.",
"type": "rate_limit_exceeded",
"code": "rate_limit_exceeded",
"limit": 100,
"reset_at": "2025-12-04T02:46:24Z"
}
}GET /i/:ulid.:ext
Retrieve a file via our global CDN. This is a public endpoint (no authentication required). Files are served with optimal caching and global distribution for fast delivery.
Request
Authentication: None required
URL Pattern: /i/{ULID}.{ext}
curl https://images.labnocturne.com/i/01ARZ3NDEKTSV4RRFFQ69G5FAV.jpgResponse
Returns a 302 Found redirect to the CDN URL. Images are cached globally for optimal performance and fast delivery worldwide.
Response Headers
Cache-Control: public, max-age=31536000, immutable Content-Type: image/jpegErrors
Returns a 1x1 transparent PNG for better UX in <img> tags.
DELETE /i/:id
Delete a file. You can only delete files you own.
Request
Authentication: Required (Bearer token)
Path Parameter: id - File ID in img_* format
curl -X DELETE https://images.labnocturne.com/i/img_01arz3ndektsv4rrffq69g5fav \
-H "Authorization: Bearer {{API_KEY}}"Response
{
"success": true,
"message": "File deleted successfully"
}Errors
{
"error": {
"message": "Invalid API key",
"type": "unauthorized",
"code": "invalid_api_key"
}
}{
"error": {
"message": "File not found",
"type": "not_found",
"code": "file_not_found"
}
}GET /files
List all files for your account with pagination and sorting options.
Request
Authentication: Required (Bearer token)
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | integer | 100 | Number of files to return (max 100) |
offset | integer | 0 | Number of files to skip |
sort | string | uploaded_at_desc | Sort order: uploaded_at_desc, uploaded_at_asc, size_desc, size_asc |
curl "https://images.labnocturne.com/files?limit=10&offset=0&sort=uploaded_at_desc" \
-H "Authorization: Bearer {{API_KEY}}"Response
{
"files": [
{
"id": "img_01arz3ndektsv4rrffq69g5fav",
"url": "https://images.labnocturne.com/i/01ARZ3NDEKTSV4RRFFQ69G5FAV.jpg",
"filename": "photo.jpg",
"size": 245680,
"mime_type": "image/jpeg",
"uploaded_at": "2024-12-02T10:30:00Z"
}
],
"pagination": {
"total": 42,
"limit": 10,
"offset": 0,
"next": "https://images.labnocturne.com/files?limit=10&offset=10"
}
}Errors
{
"error": {
"message": "Invalid sort order. Must be one of: uploaded_at_desc, uploaded_at_asc, size_desc, size_asc",
"type": "invalid_request",
"code": "invalid_sort_order"
}
}GET /stats
Get comprehensive usage statistics including storage, bandwidth, API requests, and quotas.
Request
Authentication: Required (Bearer token)
curl https://images.labnocturne.com/stats \
-H "Authorization: Bearer {{API_KEY}}"Response
{
"storage": {
"used_bytes": 12582912,
"used_mb": 12.0,
"quota_bytes": 104857600,
"quota_mb": 100.0,
"percentage_used": 12.0
},
"files": {
"count": 42,
"quota": null
},
"bandwidth": {
"used_bytes": 0,
"used_mb": 0.0,
"quota_bytes": 1073741824,
"quota_mb": 1024.0,
"percentage_used": 0.0
},
"api_requests": {
"count": 5,
"quota": 100,
"period": "hour",
"resets_at": "2025-12-04T03:00:00Z"
},
"account": {
"key_type": "test",
"created_at": "2024-12-01T15:30:00Z"
}
}Error Handling
All API errors follow a consistent JSON format:
{
"error": {
"message": "Human-readable error message",
"type": "error_category",
"code": "machine_readable_error_code"
}
}Common Error Codes
| HTTP Status | Error Code | Description |
|---|---|---|
| 401 | invalid_api_key | API key is missing or invalid |
| 400 | missing_file | File parameter missing in upload request |
| 400 | unsupported_file_type | File type not supported |
| 404 | file_not_found | Requested file doesn't exist or was deleted |
| 413 | file_size_exceeded | File exceeds size limit for your plan |
| 429 | rate_limit_exceeded | Too many requests, wait for rate limit reset |
Rate Limit Headers
All authenticated endpoints return rate limit information in response headers:
X-RateLimit-Limit: 100 X-RateLimit-Remaining: 95 X-RateLimit-Reset: 1638460800When rate limited, a 429 Too Many Requests response includes a Retry-After header indicating seconds until reset.
Rate Limits & Quotas
Quotas vary by plan tier. Upgrade to increase your limits.
| Feature | Test | Starter | Pro |
|---|---|---|---|
| Storage | 100 MB | 10 GB | 100 GB |
| Bandwidth | 1 GB/month | 50 GB/month | 500 GB/month |
| Rate Limit | 100 requests/hour | 1,000 requests/hour | 10,000 requests/hour |
| Max File Size | 10 MB | 100 MB | 100 MB |
| Retention | 7 days | Unlimited | Unlimited |
| Price | Free | $9/month | $29/month |
IP-Based Rate Limits
To prevent abuse, test key generation is rate limited per IP address:
- Test Key Generation: 5 keys per hour per IP address
- Response Code: 429 Too Many Requests when exceeded
- Reset: Limits reset hourly
Note: IP-based limits apply only to GET /key. Authenticated API requests are limited by your plan's quota (shown above).
Need more? Check out our pricing page for plan details and upgrade options.