Stores API
Endpoints for managing bookstore profiles, settings, and operations.
List Stores
Get a list of all bookstores.
GET /stores
Authentication
None required
Query Parameters
latitude(optional) - User's latitude for distance calculationlongitude(optional) - User's longitude for distance calculationradius(optional) - Search radius in miles (default: 25)limit(optional) - Number of results (default: 20)offset(optional) - Pagination offset (default: 0)
Response
{
"stores": [
{
"id": "660e8400-e29b-41d4-a716-446655440001",
"name": "Downtown Books",
"slug": "downtown-books",
"description": "Your neighborhood independent bookstore since 1995",
"logoUrl": "https://cdn.bookwish.app/stores/downtown-books-logo.jpg",
"bannerUrl": "https://cdn.bookwish.app/stores/downtown-books-banner.jpg",
"primaryColor": "#2c5f8d",
"addressLine1": "123 Main St",
"city": "Springfield",
"state": "IL",
"postalCode": "62701",
"country": "US",
"phone": "+1-555-0123",
"email": "info@downtownbooks.com",
"distance": 2.4,
"followerCount": 342,
"createdAt": "2023-08-15T10:00:00Z"
}
],
"total": 1,
"limit": 20,
"offset": 0
}
Errors
500 InternalServerError- Server error
Example
curl "https://api.bookwish.app/stores?latitude=39.7817&longitude=-89.6501&radius=10"
Get Store
Get detailed information about a specific store.
GET /stores/:slug
Authentication
None required
Path Parameters
slug- Store slug
Response
{
"id": "660e8400-e29b-41d4-a716-446655440001",
"name": "Downtown Books",
"slug": "downtown-books",
"description": "Your neighborhood independent bookstore since 1995. We specialize in literary fiction, local authors, and children's books.",
"logoUrl": "https://cdn.bookwish.app/stores/downtown-books-logo.jpg",
"bannerUrl": "https://cdn.bookwish.app/stores/downtown-books-banner.jpg",
"primaryColor": "#2c5f8d",
"addressLine1": "123 Main St",
"addressLine2": null,
"city": "Springfield",
"state": "IL",
"postalCode": "62701",
"country": "US",
"phone": "+1-555-0123",
"email": "info@downtownbooks.com",
"website": "https://downtownbooks.com",
"hours": {
"monday": "9:00 AM - 7:00 PM",
"tuesday": "9:00 AM - 7:00 PM",
"wednesday": "9:00 AM - 7:00 PM",
"thursday": "9:00 AM - 8:00 PM",
"friday": "9:00 AM - 8:00 PM",
"saturday": "10:00 AM - 6:00 PM",
"sunday": "12:00 PM - 5:00 PM"
},
"customDomain": "shop.downtownbooks.com",
"customDomainStatus": "ACTIVE",
"followerCount": 342,
"inventoryCount": 8456,
"ownerUserId": "550e8400-e29b-41d4-a716-446655440000",
"createdAt": "2023-08-15T10:00:00Z",
"updatedAt": "2024-03-20T14:30:00Z"
}
Errors
404 NotFound- Store not found500 InternalServerError- Server error
Example
curl "https://api.bookwish.app/stores/downtown-books"
Get My Store
Get the authenticated user's owned store.
GET /stores/my
Authentication
Required (Bearer token)
Response
{
"id": "660e8400-e29b-41d4-a716-446655440001",
"name": "Downtown Books",
"slug": "downtown-books",
"description": "Your neighborhood independent bookstore since 1995",
"logoUrl": "https://cdn.bookwish.app/stores/downtown-books-logo.jpg",
"bannerUrl": "https://cdn.bookwish.app/stores/downtown-books-banner.jpg",
"primaryColor": "#2c5f8d",
"addressLine1": "123 Main St",
"city": "Springfield",
"state": "IL",
"postalCode": "62701",
"country": "US",
"phone": "+1-555-0123",
"email": "info@downtownbooks.com",
"customDomain": "shop.downtownbooks.com",
"customDomainStatus": "ACTIVE",
"ownerUserId": "550e8400-e29b-41d4-a716-446655440000",
"createdAt": "2023-08-15T10:00:00Z"
}
Errors
401 Unauthorized- Not authenticated404 NotFound- User does not have a store500 InternalServerError- Server error
Lookup Store by Domain
Lookup a store by its custom domain.
GET /stores/lookup-by-domain?domain={domain}
Authentication
None required
Query Parameters
domain(required) - Custom domain to lookup
Response
{
"store": {
"id": "660e8400-e29b-41d4-a716-446655440001",
"slug": "downtown-books",
"name": "Downtown Books",
"customDomain": "shop.downtownbooks.com",
"customDomainStatus": "ACTIVE"
}
}
Errors
400 ValidationError- Missing domain parameter404 NotFound- No store found for domain500 InternalServerError- Server error
Create Store
Create a new bookstore (requires Bookstore tier).
POST /stores
Authentication
Required (Bearer token - Bookstore tier)
Request Body
{
"name": "My Bookstore",
"slug": "my-bookstore",
"description": "A cozy independent bookstore",
"addressLine1": "456 Oak Ave",
"city": "Springfield",
"state": "IL",
"postalCode": "62702",
"country": "US",
"phone": "+1-555-0456",
"email": "info@mybookstore.com",
"primaryColor": "#3a7ca5"
}
Response
{
"id": "660e8400-e29b-41d4-a716-446655440002",
"name": "My Bookstore",
"slug": "my-bookstore",
"description": "A cozy independent bookstore",
"addressLine1": "456 Oak Ave",
"city": "Springfield",
"state": "IL",
"postalCode": "62702",
"country": "US",
"phone": "+1-555-0456",
"email": "info@mybookstore.com",
"primaryColor": "#3a7ca5",
"ownerUserId": "550e8400-e29b-41d4-a716-446655440000",
"createdAt": "2024-03-21T09:00:00Z"
}
Errors
400 ValidationError- Invalid request body or slug already taken401 Unauthorized- Not authenticated403 Forbidden- Insufficient tier (requires Bookstore tier)500 InternalServerError- Server error
Update Store
Update store details.
PUT /stores/:slug
Authentication
Required (Bearer token - store owner only)
Path Parameters
slug- Store slug
Request Body
{
"description": "Updated description",
"phone": "+1-555-0789",
"hours": {
"monday": "10:00 AM - 6:00 PM",
"tuesday": "10:00 AM - 6:00 PM",
"wednesday": "10:00 AM - 6:00 PM",
"thursday": "10:00 AM - 6:00 PM",
"friday": "10:00 AM - 8:00 PM",
"saturday": "10:00 AM - 8:00 PM",
"sunday": "Closed"
}
}
Response
{
"id": "660e8400-e29b-41d4-a716-446655440001",
"name": "Downtown Books",
"slug": "downtown-books",
"description": "Updated description",
"phone": "+1-555-0789",
"hours": {
"monday": "10:00 AM - 6:00 PM",
"tuesday": "10:00 AM - 6:00 PM",
"wednesday": "10:00 AM - 6:00 PM",
"thursday": "10:00 AM - 6:00 PM",
"friday": "10:00 AM - 8:00 PM",
"saturday": "10:00 AM - 8:00 PM",
"sunday": "Closed"
},
"updatedAt": "2024-03-21T10:30:00Z"
}
Errors
400 ValidationError- Invalid request body401 Unauthorized- Not authenticated403 Forbidden- Not the store owner404 NotFound- Store not found500 InternalServerError- Server error
Upload Store Logo
Upload a store logo image.
POST /stores/:slug/logo
Authentication
Required (Bearer token - store owner only)
Path Parameters
slug- Store slug
Request Body
- Content-Type:
multipart/form-data - Field name:
logo - Accepted formats: JPG, PNG
- Max file size: 5MB
- Recommended size: 500x500px
Response
{
"logoUrl": "https://cdn.bookwish.app/stores/downtown-books-logo.jpg"
}
Errors
400 ValidationError- Invalid file format or size401 Unauthorized- Not authenticated403 Forbidden- Not the store owner404 NotFound- Store not found500 InternalServerError- Server error
Upload Store Banner
Upload a store banner image.
POST /stores/:slug/banner
Authentication
Required (Bearer token - store owner only)
Path Parameters
slug- Store slug
Request Body
- Content-Type:
multipart/form-data - Field name:
banner - Accepted formats: JPG, PNG
- Max file size: 5MB
- Recommended size: 1920x400px
Response
{
"bannerUrl": "https://cdn.bookwish.app/stores/downtown-books-banner.jpg"
}
Errors
400 ValidationError- Invalid file format or size401 Unauthorized- Not authenticated403 Forbidden- Not the store owner404 NotFound- Store not found500 InternalServerError- Server error
Get Store Clubs
Get book clubs hosted by a store.
GET /stores/:slug/clubs
Authentication
None required
Path Parameters
slug- Store slug
Response
{
"clubs": [
{
"id": "770e8400-e29b-41d4-a716-446655440002",
"name": "Downtown Mystery Book Club",
"description": "Monthly mystery novel discussions",
"isPublic": true,
"memberCount": 18,
"storeId": "660e8400-e29b-41d4-a716-446655440001",
"createdAt": "2024-01-15T10:00:00Z"
}
]
}
Errors
404 NotFound- Store not found500 InternalServerError- Server error
Get Store Challenges
Get reading challenges hosted by a store.
GET /stores/:slug/challenges
Authentication
None required
Path Parameters
slug- Store slug
Response
{
"challenges": [
{
"id": "880e8400-e29b-41d4-a716-446655440003",
"name": "2024 Local Authors Challenge",
"description": "Read 12 books by local authors in 2024",
"goal": 12,
"participantCount": 67,
"storeId": "660e8400-e29b-41d4-a716-446655440001",
"createdAt": "2023-12-01T09:00:00Z"
}
]
}
Errors
404 NotFound- Store not found500 InternalServerError- Server error
Get Store Website Config
Get store configuration for custom website (used by Next.js storefronts).
GET /stores/:slug/website-config
Authentication
None required
Path Parameters
slug- Store slug
Response
{
"store": {
"id": "660e8400-e29b-41d4-a716-446655440001",
"name": "Downtown Books",
"slug": "downtown-books",
"description": "Your neighborhood independent bookstore since 1995",
"branding": {
"logoUrl": "https://cdn.bookwish.app/stores/downtown-books-logo.jpg",
"bannerUrl": "https://cdn.bookwish.app/stores/downtown-books-banner.jpg",
"primaryColor": "#2c5f8d"
},
"contact": {
"addressLine1": "123 Main St",
"addressLine2": null,
"city": "Springfield",
"state": "IL",
"postalCode": "62701",
"country": "US",
"phone": "+1-555-0123",
"email": "info@downtownbooks.com"
},
"hours": {
"monday": "9:00 AM - 7:00 PM",
"tuesday": "9:00 AM - 7:00 PM",
"wednesday": "9:00 AM - 7:00 PM",
"thursday": "9:00 AM - 8:00 PM",
"friday": "9:00 AM - 8:00 PM",
"saturday": "10:00 AM - 6:00 PM",
"sunday": "12:00 PM - 5:00 PM"
},
"domain": {
"custom": "shop.downtownbooks.com",
"status": "ACTIVE"
}
}
}
Errors
404 NotFound- Store not found500 InternalServerError- Server error
Get Wishlist Demand
Get books wishlisted by Home Store users (store owner only).
GET /stores/:slug/wishlist-demand
Authentication
Required (Bearer token - store owner only)
Path Parameters
slug- Store slug
Response
{
"books": [
{
"book_id": "bb0e8400-e29b-41d4-a716-446655440006",
"title": "The Catcher in the Rye",
"authors": ["J.D. Salinger"],
"wishlist_count": 23,
"inventory_status": {
"quantity": 3,
"in_stock": true
}
},
{
"book_id": "bb0e8400-e29b-41d4-a716-446655440007",
"title": "To Kill a Mockingbird",
"authors": ["Harper Lee"],
"wishlist_count": 18,
"inventory_status": {
"quantity": 0,
"in_stock": false
}
}
]
}
Errors
401 Unauthorized- Not authenticated403 Forbidden- Not the store owner404 NotFound- Store not found500 InternalServerError- Server error
Get Store Earnings
Get earnings summary (affiliate commissions + pool payouts).
GET /stores/:slug/earnings
Authentication
Required (Bearer token - store owner only)
Path Parameters
slug- Store slug
Response
{
"earnings": {
"affiliateCommissions": {
"pendingCents": 12450,
"paidCents": 45600,
"totalCents": 58050
},
"poolPayouts": {
"pendingCents": 8900,
"paidCents": 23400,
"totalCents": 32300
},
"total": {
"pendingCents": 21350,
"paidCents": 69000,
"totalCents": 90350
}
}
}
Errors
401 Unauthorized- Not authenticated403 Forbidden- Not the store owner404 NotFound- Store not found500 InternalServerError- Server error
Get Affiliate Commissions
Get detailed affiliate commission payouts.
GET /stores/:slug/affiliate-commissions
Authentication
Required (Bearer token - store owner only)
Path Parameters
slug- Store slug
Query Parameters
status(optional) - Filter by status:pendingorpaid
Response
{
"payouts": [
{
"id": "payout-001",
"orderId": "order-001",
"order": {
"orderNumber": "ORD-2024-001234",
"totalCents": 3298,
"createdAt": "2024-03-20T10:30:00Z"
},
"commissionCents": 330,
"status": "paid",
"paidAt": "2024-03-25T09:00:00Z",
"createdAt": "2024-03-20T10:35:00Z"
}
]
}
Errors
401 Unauthorized- Not authenticated403 Forbidden- Not the store owner404 NotFound- Store not found500 InternalServerError- Server error
Get Pool Payouts
Get Home Store Pool payouts.
GET /stores/:slug/pool-payouts
Authentication
Required (Bearer token - store owner only)
Path Parameters
slug- Store slug
Response
{
"payouts": [
{
"id": "pool-001",
"poolMonth": "2024-03",
"payoutAmountCents": 8900,
"status": "pending",
"createdAt": "2024-04-01T00:00:00Z"
},
{
"id": "pool-002",
"poolMonth": "2024-02",
"payoutAmountCents": 12300,
"status": "paid",
"paidAt": "2024-03-05T10:00:00Z",
"createdAt": "2024-03-01T00:00:00Z"
}
]
}
Errors
401 Unauthorized- Not authenticated403 Forbidden- Not the store owner404 NotFound- Store not found500 InternalServerError- Server error
Verify Custom Domain
Initiate custom domain verification process.
POST /stores/:slug/domain/verify
Authentication
Required (Bearer token - store owner only)
Path Parameters
slug- Store slug
Request Body
{
"domain": "shop.mybookstore.com"
}
Response
{
"store": {
"id": "660e8400-e29b-41d4-a716-446655440001",
"customDomain": "shop.mybookstore.com",
"customDomainStatus": "PENDING"
},
"instructions": {
"message": "Add the following DNS record to verify domain ownership",
"record": {
"type": "CNAME",
"name": "shop.mybookstore.com",
"value": "downtown-books.bookwish.store"
},
"note": "Verification may take up to 48 hours"
}
}
Errors
400 ValidationError- Invalid or missing domain401 Unauthorized- Not authenticated403 Forbidden- Not the store owner404 NotFound- Store not found500 InternalServerError- Server error
Check Domain Status
Check custom domain verification status.
GET /stores/:slug/domain/status
Authentication
Required (Bearer token - store owner only)
Path Parameters
slug- Store slug
Response
{
"domain": "shop.mybookstore.com",
"status": "ACTIVE",
"verifiedAt": "2024-03-20T14:30:00Z",
"message": "Domain is verified and active"
}
Domain Status Values
NONE- No custom domain configuredPENDING- Verification in progressVERIFIED- Domain verifiedACTIVE- Domain verified and active
Errors
401 Unauthorized- Not authenticated403 Forbidden- Not the store owner404 NotFound- Store not found500 InternalServerError- Server error
Remove Custom Domain
Remove a custom domain from the store.
DELETE /stores/:slug/domain
Authentication
Required (Bearer token - store owner only)
Path Parameters
slug- Store slug
Response
{
"success": true,
"message": "Custom domain removed"
}
Errors
401 Unauthorized- Not authenticated403 Forbidden- Not the store owner404 NotFound- Store not found500 InternalServerError- Server error