{
  "info": {
    "_postman_id": "kiyohr-mobile-api-2026",
    "name": "KiyoHR Mobile API (Flutter TimeX)",
    "description": "Postman collection matching KiyoHR_TimeX_Flutter mobile app API calls against Laravel HRMS SaaS.\n\nBase URL: {{base_url}} (default http://127.0.0.1:8000/api)\nAuth: Bearer token from login — set {{token}} via Login requests or collection variable. Tokens persist until POST /auth/logout (no server expiry when SANCTUM expiration is null; login does not revoke other devices' tokens).\n\nTenant scoping is automatic from authenticated user company_id (no X-Tenant header).\n\nImport with: postman/KiyoHR_Mobile_API.postman_environment.json",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "auth": {
    "type": "bearer",
    "bearer": [
      {
        "key": "token",
        "value": "{{token}}",
        "type": "string"
      }
    ]
  },
  "event": [
    {
      "listen": "prerequest",
      "script": {
        "type": "text/javascript",
        "exec": [
          ""
        ]
      }
    }
  ],
  "variable": [
    {
      "key": "base_url",
      "value": "http://127.0.0.1:8000/api"
    },
    {
      "key": "token",
      "value": ""
    },
    {
      "key": "email",
      "value": "employee@example.com"
    },
    {
      "key": "password",
      "value": "password"
    },
    {
      "key": "user_id",
      "value": "1"
    },
    {
      "key": "company_id",
      "value": "1"
    },
    {
      "key": "face_data_sample",
      "value": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAABAAEDASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAv/xAAUEAEAAAAAAAAAAAAAAAAAAAAA/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAX/xAAUEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwCwAA//2Q=="
    }
  ],
  "item": [
    {
      "name": "Auth",
      "item": [
        {
          "name": "Login (email/password)",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const json = pm.response.json();",
                  "if (json.token) {",
                  "  pm.collectionVariables.set('token', json.token);",
                  "  pm.environment.set('token', json.token);",
                  "}",
                  "if (json.user && json.user.id) {",
                  "  pm.collectionVariables.set('user_id', String(json.user.id));",
                  "  pm.environment.set('user_id', String(json.user.id));",
                  "}",
                  "if (json.user && json.user.company_id) {",
                  "  pm.collectionVariables.set('company_id', String(json.user.company_id));",
                  "  pm.environment.set('company_id', String(json.user.company_id));",
                  "}"
                ]
              }
            }
          ],
          "request": {
            "auth": { "type": "noauth" },
            "method": "POST",
            "header": [
              { "key": "Content-Type", "value": "application/json" },
              { "key": "Accept", "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"email\": \"{{email}}\",\n  \"password\": \"{{password}}\"\n}"
            },
            "url": "{{base_url}}/auth/login",
            "description": "Flutter: AppVariables.authLogin — stores Bearer token in {{token}}."
          }
        },
        {
          "name": "Login (legacy alias /hrms/login)",
          "request": {
            "auth": { "type": "noauth" },
            "method": "POST",
            "header": [
              { "key": "Content-Type", "value": "application/json" },
              { "key": "Accept", "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"email\": \"{{email}}\",\n  \"password\": \"{{password}}\"\n}"
            },
            "url": "{{base_url}}/hrms/login",
            "description": "Same handler as /auth/login. Legacy Vue app path; not used by current Flutter constants."
          }
        },
        {
          "name": "Face Login (no Bearer required)",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const json = pm.response.json();",
                  "if (json.token) {",
                  "  pm.collectionVariables.set('token', json.token);",
                  "  pm.environment.set('token', json.token);",
                  "}"
                ]
              }
            }
          ],
          "request": {
            "auth": { "type": "noauth" },
            "method": "POST",
            "header": [
              { "key": "Content-Type", "value": "application/json" },
              { "key": "Accept", "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"face_data\": \"{{face_data_sample}}\",\n  \"email\": \"{{email}}\"\n}"
            },
            "url": "{{base_url}}/face/login",
            "description": "Public route. Optional company_id and email to narrow face match. Workforce/employee accounts only."
          }
        },
        {
          "name": "Get Current User",
          "request": {
            "method": "GET",
            "header": [{ "key": "Accept", "value": "application/json" }],
            "url": "{{base_url}}/auth/user"
          }
        },
        {
          "name": "Logout",
          "request": {
            "method": "POST",
            "header": [{ "key": "Accept", "value": "application/json" }],
            "url": "{{base_url}}/auth/logout"
          }
        },
        {
          "name": "Forgot Password",
          "request": {
            "auth": { "type": "noauth" },
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"email\": \"{{email}}\"\n}"
            },
            "url": "{{base_url}}/auth/forgot-password"
          }
        }
      ]
    },
    {
      "name": "Attendance",
      "item": [
        {
          "name": "Today",
          "request": {
            "method": "GET",
            "header": [{ "key": "Accept", "value": "application/json" }],
            "url": "{{base_url}}/attendance/today",
            "description": "Flutter dashboard — today's record or status not_clocked_in."
          }
        },
        {
          "name": "History (date range)",
          "request": {
            "method": "GET",
            "header": [{ "key": "Accept", "value": "application/json" }],
            "url": {
              "raw": "{{base_url}}/attendance?from=2026-06-01&to=2026-06-30&per_page=100",
              "host": ["{{base_url}}"],
              "path": ["attendance"],
              "query": [
                { "key": "from", "value": "2026-06-01" },
                { "key": "to", "value": "2026-06-30" },
                { "key": "per_page", "value": "100" }
              ]
            }
          }
        },
        {
          "name": "Clock In (token + device metadata)",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Content-Type", "value": "application/json" },
              { "key": "Accept", "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"user_id\": {{user_id}},\n  \"company_id\": {{company_id}},\n  \"device_type\": \"mobile\",\n  \"platform\": \"Android\",\n  \"user_agent\": \"Postman KiyoHR Mobile\",\n  \"browser\": \"Postman KiyoHR Mobile\",\n  \"ip_address\": \"0.0.0.0\"\n}"
            },
            "url": "{{base_url}}/attendance/clock-in",
            "description": "Flutter sends extra metadata fields; Laravel AttendanceController also accepts latitude/longitude only. Extra fields are ignored server-side."
          }
        },
        {
          "name": "Clock Out (token + device metadata)",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Content-Type", "value": "application/json" },
              { "key": "Accept", "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"user_id\": {{user_id}},\n  \"company_id\": {{company_id}},\n  \"device_type\": \"mobile\",\n  \"platform\": \"Android\",\n  \"user_agent\": \"Postman KiyoHR Mobile\",\n  \"browser\": \"Postman KiyoHR Mobile\",\n  \"ip_address\": \"0.0.0.0\"\n}"
            },
            "url": "{{base_url}}/attendance/clock-out"
          }
        },
        {
          "name": "Clock In (minimal — Laravel validation)",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Content-Type", "value": "application/json" },
              { "key": "Accept", "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"latitude\": 0.0,\n  \"longitude\": 0.0\n}"
            },
            "url": "{{base_url}}/attendance/clock-in",
            "description": "Matches integration test payload in Flutter test/integration/local_laravel_api_test.dart"
          }
        },
        {
          "name": "Clock In (legacy alias /attendance/login)",
          "request": {
            "method": "POST",
            "header": [{ "key": "Accept", "value": "application/json" }],
            "url": "{{base_url}}/attendance/login",
            "description": "Flutter fallback when /face/attendance fails with 401/404/422. Empty body."
          }
        },
        {
          "name": "Clock Out (legacy alias /attendance/logout)",
          "request": {
            "method": "POST",
            "header": [{ "key": "Accept", "value": "application/json" }],
            "url": "{{base_url}}/attendance/logout"
          }
        },
        {
          "name": "Today Attendance Details (legacy)",
          "request": {
            "method": "GET",
            "header": [{ "key": "Accept", "value": "application/json" }],
            "url": "{{base_url}}/hrm/today-attendance-details"
          }
        },
        {
          "name": "Monthly Summary (legacy)",
          "request": {
            "method": "GET",
            "header": [{ "key": "Accept", "value": "application/json" }],
            "url": {
              "raw": "{{base_url}}/self/summary-month?month=6&year=2026",
              "host": ["{{base_url}}"],
              "path": ["self", "summary-month"],
              "query": [
                { "key": "month", "value": "6" },
                { "key": "year", "value": "2026" }
              ]
            }
          }
        }
      ]
    },
    {
      "name": "Face",
      "item": [
        {
          "name": "Face Attendance — Clock In (public)",
          "request": {
            "auth": { "type": "noauth" },
            "method": "POST",
            "header": [
              { "key": "Content-Type", "value": "application/json" },
              { "key": "Accept", "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"mode\": \"login\",\n  \"face_data\": \"{{face_data_sample}}\",\n  \"company_id\": {{company_id}},\n  \"email\": \"{{email}}\"\n}"
            },
            "url": "{{base_url}}/face/attendance",
            "description": "No Bearer required. mode: login | logout. Flutter camera screen primary path."
          }
        },
        {
          "name": "Face Attendance — Clock Out (public)",
          "request": {
            "auth": { "type": "noauth" },
            "method": "POST",
            "header": [
              { "key": "Content-Type", "value": "application/json" },
              { "key": "Accept", "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"mode\": \"logout\",\n  \"face_data\": \"{{face_data_sample}}\",\n  \"company_id\": {{company_id}},\n  \"email\": \"{{email}}\"\n}"
            },
            "url": "{{base_url}}/face/attendance"
          }
        },
        {
          "name": "Face Sync",
          "request": {
            "method": "GET",
            "header": [{ "key": "Accept", "value": "application/json" }],
            "url": "{{base_url}}/face/sync"
          }
        },
        {
          "name": "Face Register",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Content-Type", "value": "application/json" },
              { "key": "Accept", "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"user_id\": {{user_id}},\n  \"face_data\": \"{{face_data_sample}}\",\n  \"overwrite\": true,\n  \"is_update\": true\n}"
            },
            "url": "{{base_url}}/face/register"
          }
        }
      ]
    },
    {
      "name": "Users",
      "item": [
        {
          "name": "List Users (face enrollment)",
          "request": {
            "method": "GET",
            "header": [{ "key": "Accept", "value": "application/json" }],
            "url": "{{base_url}}/users",
            "description": "Returns JSON array (not paginated wrapper). Managers see company users; staff see self only."
          }
        },
        {
          "name": "Users Missing Faces",
          "request": {
            "method": "GET",
            "header": [{ "key": "Accept", "value": "application/json" }],
            "url": "{{base_url}}/users/missing-faces"
          }
        },
        {
          "name": "Show User",
          "request": {
            "method": "GET",
            "header": [{ "key": "Accept", "value": "application/json" }],
            "url": "{{base_url}}/users/{{user_id}}"
          }
        }
      ]
    },
    {
      "name": "HR Modules (API available, not in Flutter UI yet)",
      "item": [
        {
          "name": "Leaves — List",
          "request": {
            "method": "GET",
            "header": [{ "key": "Accept", "value": "application/json" }],
            "url": "{{base_url}}/leaves"
          }
        },
        {
          "name": "Employees — List",
          "request": {
            "method": "GET",
            "header": [{ "key": "Accept", "value": "application/json" }],
            "url": "{{base_url}}/employees"
          }
        },
        {
          "name": "My Payslip",
          "request": {
            "method": "GET",
            "header": [{ "key": "Accept", "value": "application/json" }],
            "url": "{{base_url}}/payroll/my-payslip"
          }
        },
        {
          "name": "Subscription Status",
          "request": {
            "method": "GET",
            "header": [{ "key": "Accept", "value": "application/json" }],
            "url": "{{base_url}}/subscription/status"
          }
        }
      ]
    }
  ]
}
