Skip to main content

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 calculation
  • longitude (optional) - User's longitude for distance calculation
  • radius (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 found
  • 500 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 authenticated
  • 404 NotFound - User does not have a store
  • 500 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 parameter
  • 404 NotFound - No store found for domain
  • 500 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 taken
  • 401 Unauthorized - Not authenticated
  • 403 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 body
  • 401 Unauthorized - Not authenticated
  • 403 Forbidden - Not the store owner
  • 404 NotFound - Store not found
  • 500 InternalServerError - Server error

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 size
  • 401 Unauthorized - Not authenticated
  • 403 Forbidden - Not the store owner
  • 404 NotFound - Store not found
  • 500 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 size
  • 401 Unauthorized - Not authenticated
  • 403 Forbidden - Not the store owner
  • 404 NotFound - Store not found
  • 500 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 found
  • 500 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 found
  • 500 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 found
  • 500 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 authenticated
  • 403 Forbidden - Not the store owner
  • 404 NotFound - Store not found
  • 500 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 authenticated
  • 403 Forbidden - Not the store owner
  • 404 NotFound - Store not found
  • 500 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: pending or paid

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 authenticated
  • 403 Forbidden - Not the store owner
  • 404 NotFound - Store not found
  • 500 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 authenticated
  • 403 Forbidden - Not the store owner
  • 404 NotFound - Store not found
  • 500 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 domain
  • 401 Unauthorized - Not authenticated
  • 403 Forbidden - Not the store owner
  • 404 NotFound - Store not found
  • 500 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 configured
  • PENDING - Verification in progress
  • VERIFIED - Domain verified
  • ACTIVE - Domain verified and active

Errors

  • 401 Unauthorized - Not authenticated
  • 403 Forbidden - Not the store owner
  • 404 NotFound - Store not found
  • 500 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 authenticated
  • 403 Forbidden - Not the store owner
  • 404 NotFound - Store not found
  • 500 InternalServerError - Server error