Skip to main content

Collections Admin API

The Collections Admin API allows gallery administrators to create and manage curated product collections. Collections can be manual, smart (rule-based), or hybrid.

Authentication

Requires Supabase authentication with admin role:

Authorization: Bearer <access_token>

Additionally, RLS policies enforce admin-only access.


Collection Types

Manual Collections

Hand-curated collections where admin explicitly adds products:

{
"type": "manual",
"name": "Staff Picks",
"description": "Our favorite pieces this month"
}
  • Pros: Complete control, editorial curation
  • Cons: Requires manual maintenance
  • Use cases: Featured collections, seasonal picks, editor's choice

Smart Collections

Auto-populated based on rules (future feature):

{
"type": "smart",
"name": "Under $100",
"rules": {
"price_max": 100,
"gallery_eligible": true,
"is_active": true
}
}
  • Pros: Automatic updates, scales well
  • Cons: Less editorial control
  • Use cases: Price ranges, new arrivals, artist categories

Hybrid Collections

Combination of manual curation and smart rules:

{
"type": "hybrid",
"name": "Affordable Abstract Art",
"rules": { "price_max": 150 },
"manualInclusions": ["prod_001", "prod_002"]
}
  • Pros: Best of both worlds
  • Cons: More complex to manage
  • Use cases: Curated subcategories, themed collections with price limits

Endpoints

List Collections

Retrieves all gallery collections with item counts.

Endpoint: GET /api/admin/collections

Authentication: Required (admin only)

Query Parameters:

ParameterTypeDescription
is_activebooleanFilter by active status
typestringFilter by type (manual, smart, hybrid)

Response:

{
"collections": [
{
"id": "coll_001",
"slug": "staff-picks",
"name": "Staff Picks",
"description": "Our favorite pieces this month",
"type": "manual",
"isActive": true,
"featuredImage": "https://...",
"itemCount": 12,
"createdAt": "2024-01-15T10:00:00Z",
"updatedAt": "2024-01-20T14:30:00Z"
}
]
}

Example Request:

curl https://gallery.artbase.studio/api/admin/collections \
-H "Authorization: Bearer <admin_token>"

Get Collection Details

Retrieves a specific collection with all items.

Endpoint: GET /api/admin/collections/{id}

URL Parameters:

ParameterTypeDescription
idstringCollection UUID

Response:

{
"collection": {
"id": "coll_001",
"slug": "staff-picks",
"name": "Staff Picks",
"description": "Our favorite pieces this month",
"type": "manual",
"isActive": true,
"featuredImage": "https://...",
"items": [
{
"id": "item_001",
"productId": "prod_001",
"position": 1,
"product": {
"id": "prod_001",
"name": "Abstract Painting #5",
"price": 150.00,
"images": ["https://..."],
"org_id": "org_abc",
"organizations": {
"name": "Jane Smith Studio"
}
}
}
],
"createdAt": "2024-01-15T10:00:00Z",
"updatedAt": "2024-01-20T14:30:00Z"
}
}

Example Request:

curl https://gallery.artbase.studio/api/admin/collections/coll_001 \
-H "Authorization: Bearer <admin_token>"

Create Collection

Creates a new gallery collection.

Endpoint: POST /api/admin/collections

Request Body:

{
"slug": "spring-collection",
"name": "Spring Collection 2024",
"description": "Fresh and vibrant artwork celebrating spring",
"type": "manual",
"isActive": true,
"featuredImage": "https://cdn.example.com/spring.jpg"
}

Request Parameters:

FieldTypeRequiredDescription
slugstringYesURL-friendly identifier (must be unique)
namestringYesDisplay name
descriptionstringNoCollection description
typestringYes"manual", "smart", or "hybrid"
isActivebooleanNoActive status (default: true)
featuredImagestringNoCollection cover image URL
rulesobjectConditionalRequired if type is "smart" or "hybrid"

Response:

{
"collection": {
"id": "coll_002",
"slug": "spring-collection",
"name": "Spring Collection 2024",
"description": "Fresh and vibrant artwork celebrating spring",
"type": "manual",
"isActive": true,
"featuredImage": "https://cdn.example.com/spring.jpg",
"createdAt": "2024-03-01T09:00:00Z",
"updatedAt": "2024-03-01T09:00:00Z"
}
}

Example Request:

curl -X POST https://gallery.artbase.studio/api/admin/collections \
-H "Authorization: Bearer <admin_token>" \
-H "Content-Type: application/json" \
-d '{
"slug": "spring-collection",
"name": "Spring Collection 2024",
"description": "Fresh artwork for spring",
"type": "manual",
"isActive": true
}'

Error Responses:

StatusErrorDescription
400Name, slug, and type are requiredMissing fields
400Collection with this slug already existsDuplicate slug
401UnauthorizedNot logged in
403ForbiddenNot an admin

Update Collection

Updates an existing collection.

Endpoint: PATCH /api/admin/collections/{id}

Request Body (all fields optional):

{
"name": "Updated Name",
"description": "Updated description",
"isActive": false,
"featuredImage": "https://..."
}

Response:

{
"collection": {
"id": "coll_001",
"slug": "staff-picks",
"name": "Updated Name",
"updatedAt": "2024-03-15T12:00:00Z"
}
}

Example Request:

curl -X PATCH https://gallery.artbase.studio/api/admin/collections/coll_001 \
-H "Authorization: Bearer <admin_token>" \
-H "Content-Type: application/json" \
-d '{
"isActive": false
}'

Delete Collection

Deletes a collection and all its items.

Endpoint: DELETE /api/admin/collections/{id}

Response:

{
"success": true
}

Example Request:

curl -X DELETE https://gallery.artbase.studio/api/admin/collections/coll_001 \
-H "Authorization: Bearer <admin_token>"

Note: This cascades to delete all gallery_collection_items for this collection.


Add Product to Collection

Adds a product to a manual or hybrid collection.

Endpoint: POST /api/admin/collections/{id}/items

Request Body:

{
"productId": "prod_001",
"position": 5
}

Request Parameters:

FieldTypeRequiredDescription
productIdstringYesProduct UUID to add
positionnumberNoDisplay order (default: append to end)

Response:

{
"item": {
"id": "item_001",
"collectionId": "coll_001",
"productId": "prod_001",
"position": 5,
"createdAt": "2024-03-15T14:00:00Z"
}
}

Example Request:

curl -X POST https://gallery.artbase.studio/api/admin/collections/coll_001/items \
-H "Authorization: Bearer <admin_token>" \
-H "Content-Type: application/json" \
-d '{
"productId": "prod_001"
}'

Error Responses:

StatusErrorDescription
400Product ID requiredMissing productId
404Product not foundInvalid product ID
400Product not gallery eligibleProduct not curated for gallery
400Product already in collectionDuplicate entry

Remove Product from Collection

Removes a product from a collection.

Endpoint: DELETE /api/admin/collections/{id}/items/{itemId}

Response:

{
"success": true
}

Example Request:

curl -X DELETE https://gallery.artbase.studio/api/admin/collections/coll_001/items/item_001 \
-H "Authorization: Bearer <admin_token>"

Reorder Collection Items

Updates the display order of products in a collection.

Endpoint: PATCH /api/admin/collections/{id}/items/reorder

Request Body:

{
"items": [
{ "itemId": "item_001", "position": 1 },
{ "itemId": "item_002", "position": 2 },
{ "itemId": "item_003", "position": 3 }
]
}

Response:

{
"success": true,
"updatedCount": 3
}

Example Request:

curl -X PATCH https://gallery.artbase.studio/api/admin/collections/coll_001/items/reorder \
-H "Authorization: Bearer <admin_token>" \
-H "Content-Type: application/json" \
-d '{
"items": [
{ "itemId": "item_001", "position": 1 },
{ "itemId": "item_002", "position": 2 }
]
}'

Curation Best Practices

Collection Size

  • Small (5-10 items): Highly curated, editorial picks
  • Medium (15-25 items): Themed collections, artist groupings
  • Large (30+ items): Category collections, comprehensive showcases

Naming Conventions

Use clear, descriptive names:

  • ✅ "Abstract Expressionism"
  • ✅ "Under $100"
  • ✅ "New Artists This Month"
  • ❌ "Collection 1"
  • ❌ "Stuff"

Slug Formatting

Slugs must be:

  • Lowercase
  • Hyphen-separated
  • No special characters
  • Unique across all collections

Examples:

  • staff-picks
  • spring-2024
  • abstract-art

Collections display better with featured images:

  • Dimensions: 1200x630px (OG image size)
  • Format: JPG or PNG
  • Content: Representative artwork from collection or custom graphic
  • Hosting: Use Supabase Storage or CDN

Example Workflows

Creating a Seasonal Collection

// 1. Create collection
const collection = await fetch('/api/admin/collections', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
slug: 'winter-2024',
name: 'Winter Collection 2024',
description: 'Cozy and contemplative artwork for winter',
type: 'manual',
isActive: true,
}),
});

const { collection: newColl } = await collection.json();

// 2. Add products
const products = ['prod_001', 'prod_002', 'prod_003'];
for (let i = 0; i < products.length; i++) {
await fetch(`/api/admin/collections/${newColl.id}/items`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
productId: products[i],
position: i + 1,
}),
});
}

Deactivating Old Collections

// Deactivate last season's collection
await fetch(`/api/admin/collections/${oldCollId}`, {
method: 'PATCH',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
isActive: false,
}),
});

Next Steps