{
  "name": "Rice Directory API",
  "version": "1.0.0",
  "description": "Global rice industry B2B directory API. Connects rice mills, exporters, importers, traders, brokers, and machinery suppliers.",
  "base_url": "https://server.rice.directory",
  "authentication": {
    "type": "Bearer Token (JWT)",
    "note": "Obtain a token via POST /api/auth/google. Pass as Authorization: Bearer <token>."
  },
  "endpoints": [
    {
      "group": "Businesses",
      "method": "GET",
      "path": "/api/businesses",
      "auth": false,
      "description": "List all active businesses with pagination.",
      "query_params": {
        "page": "number (default: 1)",
        "limit": "number (default: 20, max: 100)"
      },
      "response": {
        "data": "Business[]",
        "pagination": {
          "page": "number",
          "limit": "number",
          "total": "number",
          "totalPages": "number"
        }
      }
    },
    {
      "group": "Businesses",
      "method": "GET",
      "path": "/api/businesses/:slug",
      "auth": false,
      "description": "Get full business detail by slug. Contact information is only returned for authenticated requests.",
      "params": {
        "slug": "string — unique business identifier"
      },
      "response": {
        "data": "BusinessDetail (contacts[] empty when unauthenticated)"
      }
    },
    {
      "group": "Businesses",
      "method": "POST",
      "path": "/api/businesses/search",
      "auth": false,
      "description": "Search and filter businesses with composable filters.",
      "body": {
        "filters": {
          "query": "string (optional)",
          "country": "string (optional)",
          "city": "string (optional)",
          "business_type": "string[] (optional) — slugs e.g. [\"exporter\",\"rice-mill\"]",
          "rice_type": "string[] (optional)",
          "is_exporter": "boolean (optional)",
          "is_importer": "boolean (optional)",
          "is_verified": "boolean (optional)",
          "machinery_brand": "string (optional)"
        },
        "sort": "\"relevance\" | \"name\" | \"newest\" | \"oldest\" (default: relevance)",
        "page": "number (default: 1)",
        "limit": "number (default: 20)"
      },
      "response": {
        "data": "Business[]",
        "pagination": "Pagination"
      }
    },
    {
      "group": "Businesses",
      "method": "POST",
      "path": "/api/businesses",
      "auth": true,
      "description": "Create a new business listing.",
      "body": {
        "name": "string (required)",
        "description": "string (optional)",
        "website": "string (optional)",
        "country": "string (optional)",
        "city": "string (optional)",
        "province": "string (optional)",
        "address": "string (optional)",
        "year_established": "number (optional)",
        "employee_count": "string (optional)",
        "is_exporter": "boolean (default: false)",
        "is_importer": "boolean (default: false)",
        "business_types": "string[] — type slugs",
        "rice_types": "string[] — rice type slugs",
        "contacts": "Array<{ type: string; value: string; label?: string }>"
      },
      "response": {
        "data": "Business"
      }
    },
    {
      "group": "Businesses",
      "method": "PUT",
      "path": "/api/businesses/:id",
      "auth": true,
      "description": "Update a business. Only the owner or admin can update.",
      "params": {
        "id": "string — business UUID"
      },
      "body": "Partial<Business fields>",
      "response": {
        "data": "Business"
      }
    },
    {
      "group": "Businesses",
      "method": "DELETE",
      "path": "/api/businesses/:id",
      "auth": true,
      "description": "Soft-delete a business. Only the owner or admin can delete.",
      "params": {
        "id": "string — business UUID"
      },
      "response": {
        "message": "string"
      }
    },
    {
      "group": "Auth",
      "method": "POST",
      "path": "/api/auth/google",
      "auth": false,
      "description": "Exchange a Google OAuth authorization code for a JWT. Finds or creates the user.",
      "body": {
        "code": "string — OAuth authorization code from Google",
        "redirect_uri": "string — must match the URI used in the OAuth flow"
      },
      "response": {
        "user": "User",
        "token": "string — JWT (expires in 7 days)"
      }
    },
    {
      "group": "Auth",
      "method": "GET",
      "path": "/api/auth/me",
      "auth": true,
      "description": "Validate the current JWT and return the authenticated user.",
      "response": {
        "data": "User"
      }
    },
    {
      "group": "Leads",
      "method": "POST",
      "path": "/api/leads",
      "auth": false,
      "description": "Submit a contact inquiry to a business.",
      "body": {
        "business_id": "string (required)",
        "name": "string (required)",
        "email": "string (required)",
        "phone": "string (optional)",
        "company": "string (optional)",
        "message": "string (required)"
      },
      "response": {
        "data": "Lead"
      }
    },
    {
      "group": "Lookups",
      "method": "GET",
      "path": "/api/lookups/business-types",
      "auth": false,
      "description": "List all business type definitions.",
      "response": {
        "data": "BusinessType[]"
      }
    },
    {
      "group": "Lookups",
      "method": "GET",
      "path": "/api/lookups/rice-types",
      "auth": false,
      "description": "List all rice type definitions.",
      "response": {
        "data": "RiceType[]"
      }
    },
    {
      "group": "Lookups",
      "method": "GET",
      "path": "/api/lookups/countries",
      "auth": false,
      "description": "List all countries that have at least one active business.",
      "response": {
        "data": "string[]"
      }
    },
    {
      "group": "Lookups",
      "method": "GET",
      "path": "/api/lookups/cities",
      "auth": false,
      "description": "List cities, optionally filtered by country.",
      "query_params": {
        "country": "string (optional)"
      },
      "response": {
        "data": "string[]"
      }
    },
    {
      "group": "Uploads",
      "method": "POST",
      "path": "/api/uploads",
      "auth": true,
      "description": "Upload a file (logo, product image, certificate) to R2 storage. Multipart form data.",
      "body": {
        "file": "File — max 10 MB; allowed types: image/jpeg, image/png, image/webp, image/gif, application/pdf",
        "category": "string (optional) — e.g. \"logo\", \"gallery\", \"certificate\""
      },
      "response": {
        "url": "string — public URL of the uploaded file",
        "key": "string — R2 object key"
      }
    }
  ],
  "models": {
    "Business": {
      "id": "string (UUID)",
      "name": "string",
      "slug": "string",
      "description": "string | null",
      "website": "string | null",
      "logo_url": "string | null",
      "cover_image_url": "string | null",
      "country": "string | null",
      "city": "string | null",
      "province": "string | null",
      "is_exporter": "0 | 1",
      "is_importer": "0 | 1",
      "is_verified": "0 | 1",
      "is_featured": "0 | 1",
      "year_established": "number | null",
      "employee_count": "string | null",
      "view_count": "number",
      "owner_user_id": "string | null",
      "created_at": "ISO 8601 string",
      "type_names": "string (comma-separated, only on list endpoints)"
    },
    "BusinessDetail": "extends Business + { types, contacts (auth-only), rice_types, machinery, certifications, media }",
    "User": {
      "id": "string (UUID)",
      "email": "string",
      "name": "string",
      "avatar_url": "string | null",
      "role": "\"user\" | \"admin\""
    },
    "BusinessType": {
      "id": "string",
      "name": "string",
      "slug": "string",
      "description": "string | null",
      "icon": "string | null"
    },
    "RiceType": {
      "id": "string",
      "name": "string",
      "slug": "string",
      "category": "string | null"
    }
  },
  "errors": {
    "400": "Bad Request — validation error",
    "401": "Unauthorized — missing or invalid token",
    "403": "Forbidden — insufficient permissions",
    "404": "Not Found",
    "500": "Internal Server Error",
    "format": {
      "error": "string",
      "details": "Array<{ field: string; message: string }> (validation only)"
    }
  }
}