# Missio Customer API Documentation

## Overview

This API provides customer authentication and profile management for the Missio Shop Module. 
All endpoints require company identification via the `X-Company-Hash` header.

**Base URL:** `http://your-domain.com/api`

**Authentication:** Bearer Token (Laravel Sanctum)

**Required Headers:**
- `X-Company-Hash`: Company identifier (required for all requests)
- `Authorization`: Bearer token (required for authenticated endpoints)
- `Content-Type`: application/json (for POST/PUT requests)

---

## Table of Contents

1. [Authentication Endpoints](#authentication-endpoints)
   - [Signup](#1-signup)
   - [Login](#2-login)
   - [Refresh Token](#3-refresh-token)
   - [Logout](#4-logout)
2. [Profile Endpoints](#profile-endpoints)
   - [Get Profile](#5-get-profile)
   - [Update Profile](#6-update-profile)
3. [Address Endpoints](#address-endpoints)
   - [Get Addresses](#7-get-addresses)
   - [Update Addresses](#8-update-addresses)
4. [Error Handling](#error-handling)
5. [Status Codes](#status-codes)

---

## Authentication Endpoints

### 1. Signup

Create a new customer account.

**Endpoint:** `POST /auth/signup`

**Headers:**
```
X-Company-Hash: {company_hash}
Content-Type: application/json
```

**Request Body:**
```json
{
  "fname": "John",
  "lname": "Doe",
  "email": "john.doe@example.com",
  "password": "secret123",
  "username": "johndoe",
  "phone": "+1234567890",
  "address": "123 Main Street",
  "city": "Boston",
  "state": "MA",
  "country": "US",
  "zip_code": "02101"
}
```

**Required Fields:**
- `fname` (string, max: 100)
- `lname` (string, max: 100)
- `email` (email, max: 255, unique per company)
- `password` (string, min: 6)

**Optional Fields:**
- `username` (string, max: 150, unique per company) - defaults to email
- `phone` (string, max: 50)
- `address` (string)
- `city` (string)
- `state` (string)
- `country` (string) - defaults to "US"
- `zip_code` (string)

**Success Response (200):**
```json
{
  "status": "success",
  "message": "Signup successfully",
  "access_token": "1|abcdef123456...",
  "token_type": "Bearer",
  "customer": {
    "id": 1,
    "company_id": 5,
    "fname": "John",
    "lname": "Doe",
    "slug": "john-doe",
    "email": "john.doe@example.com",
    "username": "johndoe",
    "phone": "+1234567890",
    "address": "123 Main Street",
    "city": "Boston",
    "state": "MA",
    "country": "US",
    "zip_code": "02101",
    "status": "1",
    "email_verified_at": "2026-01-07 12:00:00",
    "created_at": "2026-01-07T12:00:00.000000Z",
    "updated_at": "2026-01-07T12:00:00.000000Z"
  },
  "company": {
    "id": 5,
    "name": "Acme Corporation"
  }
}
```

**Error Responses:**

Missing/Invalid Company Hash (422):
```json
{
  "status": "error",
  "message": "Missing or invalid X-Company-Hash header."
}
```

Validation Error (422):
```json
{
  "status": "error",
  "message": "The given data was invalid.",
  "errors": {
    "email": ["The email has already been taken."],
    "password": ["The password must be at least 6 characters."]
  }
}
```

---

### 2. Login

Authenticate an existing customer.

**Endpoint:** `POST /auth/login`

**Headers:**
```
X-Company-Hash: {company_hash}
Content-Type: application/json
```

**Request Body (Email):**
```json
{
  "email": "john.doe@example.com",
  "password": "secret123"
}
```

**Request Body (Username):**
```json
{
  "username": "johndoe",
  "password": "secret123"
}
```

**Required Fields:**
- `email` OR `username` (one is required)
- `password` (string)

**Success Response (200):**
```json
{
  "status": "success",
  "message": "Login successful",
  "access_token": "2|xyz789...",
  "token_type": "Bearer",
  "customer": {
    "id": 1,
    "company_id": 5,
    "fname": "John",
    "lname": "Doe",
    "email": "john.doe@example.com",
    "username": "johndoe",
    "phone": "+1234567890",
    "status": "1",
    "created_at": "2026-01-07T12:00:00.000000Z"
  },
  "company": {
    "id": 5,
    "name": "Acme Corporation"
  }
}
```

**Error Responses:**

Invalid Credentials (401):
```json
{
  "status": "error",
  "message": "Invalid credentials"
}
```

Inactive Account (403):
```json
{
  "status": "error",
  "message": "Your account is not active. Please contact support."
}
```

Missing Company Hash (422):
```json
{
  "status": "error",
  "message": "Missing or invalid X-Company-Hash header."
}
```

---

### 3. Refresh Token

Refresh the authentication token (revokes current token and issues new one).

**Endpoint:** `POST /auth/refresh`

**Headers:**
```
X-Company-Hash: {company_hash}
Authorization: Bearer {token}
Content-Type: application/json
```

**Request Body:** Empty

**Success Response (200):**
```json
{
  "status": "success",
  "message": "Token refreshed",
  "access_token": "3|newtoken123...",
  "token_type": "Bearer"
}
```

**Error Response (401):**
```json
{
  "status": "error",
  "message": "Unauthorized"
}
```

---

### 4. Logout

Revoke the current authentication token.

**Endpoint:** `POST /auth/logout`

**Headers:**
```
X-Company-Hash: {company_hash}
Authorization: Bearer {token}
Content-Type: application/json
```

**Request Body:** Empty

**Success Response (200):**
```json
{
  "status": "success",
  "message": "Logged out"
}
```

**Error Response (401):**
```json
{
  "status": "error",
  "message": "Unauthorized"
}
```

---

## Profile Endpoints

### 5. Get Profile

Retrieve the authenticated customer's profile.

**Endpoint:** `GET /me`

**Headers:**
```
X-Company-Hash: {company_hash}
Authorization: Bearer {token}
```

**Success Response (200):**
```json
{
  "status": "success",
  "message": "Profile",
  "customer": {
    "id": 1,
    "company_id": 5,
    "fname": "John",
    "lname": "Doe",
    "slug": "john-doe",
    "email": "john.doe@example.com",
    "username": "johndoe",
    "phone": "+1234567890",
    "address": "123 Main Street",
    "city": "Boston",
    "state": "MA",
    "country": "US",
    "zip_code": "02101",
    "about": "Software developer",
    "status": "1",
    "email_verified_at": "2026-01-07 12:00:00",
    "created_at": "2026-01-07T12:00:00.000000Z",
    "updated_at": "2026-01-07T12:00:00.000000Z"
  }
}
```

**Error Response (401):**
```json
{
  "status": "error",
  "message": "Unauthorized"
}
```

---

### 6. Update Profile

Update the authenticated customer's profile.

**Endpoint:** `PUT /me`

**Headers:**
```
X-Company-Hash: {company_hash}
Authorization: Bearer {token}
Content-Type: application/json
```

**Request Body:**
```json
{
  "fname": "John",
  "lname": "Smith",
  "phone": "+1987654321",
  "email": "john.smith@example.com",
  "username": "johnsmith",
  "address": "456 Oak Avenue",
  "city": "Cambridge",
  "state": "MA",
  "country": "US",
  "zip_code": "02139",
  "about": "Full stack developer",
  "photo": "/images/profile.jpg"
}
```

**Optional Fields:**
- `fname` (string, max: 100)
- `lname` (string, max: 100)
- `phone` (string, max: 50)
- `email` (email, max: 255)
- `username` (string, max: 150)
- `address` (string)
- `city` (string)
- `state` (string)
- `country` (string)
- `zip_code` (string)
- `about` (text)
- `photo` (string - path or URL)

**Success Response (200):**
```json
{
  "status": "success",
  "message": "Profile updated",
  "customer": {
    "id": 1,
    "company_id": 5,
    "fname": "John",
    "lname": "Smith",
    "slug": "john-smith",
    "email": "john.smith@example.com",
    "username": "johnsmith",
    "phone": "+1987654321",
    "address": "456 Oak Avenue",
    "city": "Cambridge",
    "state": "MA",
    "country": "US",
    "zip_code": "02139",
    "about": "Full stack developer",
    "updated_at": "2026-01-07T14:30:00.000000Z"
  }
}
```

**Error Responses:**

Validation Error (422):
```json
{
  "status": "error",
  "message": "The given data was invalid.",
  "errors": {
    "phone": ["The phone must not be greater than 50 characters."]
  }
}
```

---

## Address Endpoints

### 7. Get Addresses

Retrieve the authenticated customer's address information.

**Endpoint:** `GET /addresses`

**Headers:**
```
X-Company-Hash: {company_hash}
Authorization: Bearer {token}
```

**Success Response (200):**
```json
{
  "status": "success",
  "message": "Addresses",
  "addresses": {
    "address": "123 Main Street",
    "country": "US",
    "state": "MA",
    "city": "Boston",
    "zip_code": "02101"
  }
}
```

**Error Response (401):**
```json
{
  "status": "error",
  "message": "Unauthorized"
}
```

---

### 8. Update Addresses

Update the authenticated customer's address information.

**Endpoint:** `PUT /addresses`

**Headers:**
```
X-Company-Hash: {company_hash}
Authorization: Bearer {token}
Content-Type: application/json
```

**Request Body:**
```json
{
  "address": "456 Oak Avenue",
  "city": "Cambridge",
  "state": "MA",
  "country": "US",
  "zip_code": "02139"
}
```

**Optional Fields:**
- `address` (string, max: 500)
- `country` (string, max: 150)
- `state` (string, max: 150)
- `city` (string, max: 150)
- `zip_code` (string, max: 20)

**Success Response (200):**
```json
{
  "status": "success",
  "message": "Addresses updated",
  "addresses": {
    "address": "456 Oak Avenue",
    "country": "US",
    "state": "MA",
    "city": "Cambridge",
    "zip_code": "02139"
  }
}
```

**Error Responses:**

Validation Error (422):
```json
{
  "status": "error",
  "message": "The given data was invalid.",
  "errors": {
    "zip_code": ["The zip code must not be greater than 20 characters."]
  }
}
```

---

## Error Handling

### Common Error Responses

**Authentication Error (401):**
```json
{
  "status": "error",
  "message": "Unauthorized"
}
```

**Forbidden (403):**
```json
{
  "status": "error",
  "message": "Your account is not active. Please contact support."
}
```

**Validation Error (422):**
```json
{
  "status": "error",
  "message": "The given data was invalid.",
  "errors": {
    "field_name": ["Error message 1", "Error message 2"]
  }
}
```

**Server Error (500):**
```json
{
  "status": "error",
  "message": "Detailed error message"
}
```

---

## Status Codes

| Code | Meaning |
|------|---------|
| 200  | Success |
| 401  | Unauthorized - Invalid or missing token |
| 403  | Forbidden - Account inactive or insufficient permissions |
| 422  | Unprocessable Entity - Validation errors or missing X-Company-Hash |
| 500  | Internal Server Error |

---

## Authentication Flow

### Initial Setup
1. Obtain the company hash from your Missio instance
2. Set the `X-Company-Hash` header for all requests

### Registration Flow
1. Call `POST /auth/signup` with customer details and `X-Company-Hash`
2. Store the returned `access_token`
3. Use the token in `Authorization: Bearer {token}` header for authenticated requests

### Login Flow
1. Call `POST /auth/login` with email/username and password
2. Store the returned `access_token`
3. Use the token for subsequent authenticated requests

### Token Refresh
- Tokens don't expire by default with Sanctum
- Call `POST /auth/refresh` to revoke old token and get a new one
- Update stored token with the new value

### Logout
- Call `POST /auth/logout` to revoke the current token
- Clear stored token from client

---

## Notes for Frontend Developers

### Important Headers
- **Always include** `X-Company-Hash` header in every request
- Include `Authorization: Bearer {token}` for authenticated endpoints
- Use `Content-Type: application/json` for POST/PUT requests

### Token Management
- Store the access token securely (e.g., secure storage, not localStorage for web)
- Include token in Authorization header: `Bearer {token}`
- Handle 401 responses by redirecting to login
- Implement token refresh logic if needed

### Error Handling
- Check `status` field in response (`"success"` or `"error"`)
- Display validation errors from `errors` object
- Handle 422 status for validation errors
- Handle 401 for authentication issues
- Handle 403 for inactive accounts

### Customer Status
- `status = "1"`: Active account
- `status = "0"`: Inactive account (login will fail with 403)

### Email Verification
- Customers are auto-verified on signup (`email_verified_at` is set)
- Check `email_verified_at` field if you implement manual verification

### Username Handling
- Username defaults to email if not provided during signup
- Login accepts either email OR username

### Testing
1. Import the provided Postman collection
2. Set environment variables:
   - `base_url`: Your API base URL
   - `c_hash`: Your company hash
3. Run Signup or Login - token will be auto-captured
4. Test other authenticated endpoints

---

## Example Usage (JavaScript/Fetch)

### Signup
```javascript
const signup = async (userData) => {
  const response = await fetch('https://your-api.com/api/auth/signup', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-Company-Hash': 'your-company-hash'
    },
    body: JSON.stringify({
      fname: userData.firstName,
      lname: userData.lastName,
      email: userData.email,
      password: userData.password,
      phone: userData.phone
    })
  });
  
  const data = await response.json();
  
  if (data.status === 'success') {
    // Store token securely
    localStorage.setItem('token', data.access_token);
    return data.customer;
  } else {
    throw new Error(data.message);
  }
};
```

### Login
```javascript
const login = async (email, password) => {
  const response = await fetch('https://your-api.com/api/auth/login', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-Company-Hash': 'your-company-hash'
    },
    body: JSON.stringify({ email, password })
  });
  
  const data = await response.json();
  
  if (data.status === 'success') {
    localStorage.setItem('token', data.access_token);
    return data.customer;
  } else {
    throw new Error(data.message);
  }
};
```

### Get Profile
```javascript
const getProfile = async () => {
  const token = localStorage.getItem('token');
  
  const response = await fetch('https://your-api.com/api/me', {
    method: 'GET',
    headers: {
      'Authorization': `Bearer ${token}`,
      'X-Company-Hash': 'your-company-hash'
    }
  });
  
  const data = await response.json();
  
  if (data.status === 'success') {
    return data.customer;
  } else {
    throw new Error(data.message);
  }
};
```

### Update Profile
```javascript
const updateProfile = async (updates) => {
  const token = localStorage.getItem('token');
  
  const response = await fetch('https://your-api.com/api/me', {
    method: 'PUT',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${token}`,
      'X-Company-Hash': 'your-company-hash'
    },
    body: JSON.stringify(updates)
  });
  
  const data = await response.json();
  
  if (data.status === 'success') {
    return data.customer;
  } else {
    throw new Error(data.message);
  }
};
```

---

## Support

For questions or issues:
- Check the error message in the response
- Verify the `X-Company-Hash` header is correct
- Ensure Bearer token is valid for authenticated endpoints
- Contact your backend team for company-specific configuration
