---
# System prepended metadata

title: Detective V3 API Walkthrough

---

# Detective V3 API Walkthrough

This document provides a comprehensive guide to the Detective V3 API endpoints, including when to use them, required parameters, authorization requirements, and which test accounts to use.

---

## Test Accounts Reference

| Email | Role | 2FA | Brands | Use Case |
|:------|:-----|:----|:-------|:---------|
| `system-administrator@ext.iptwins.com` | System Administrator | TOTP Required | All Brands | Full system access |
| `account-manager@ext.iptwins.com` | Account Manager | None | acme-corp, techstart-inc | Cross-brand management |
| `client-account@ext.iptwins.com` | Client Account | None | acme-corp | Single brand client |
| `external-partner@ext.iptwins.com` | External Partner | None | techstart-inc | External partner access |
| `admin-no2fa@ext.iptwins.com` | System Administrator | None | All Brands | Admin testing without 2FA |
| `admin-needs-setup@ext.iptwins.com` | System Administrator | Setup Required | All Brands | 2FA setup flow testing |

> All test accounts use password: `123456`

---

## IAM Endpoints

### POST /auth/refresh

**Purpose**: Refreshes an expired access token using a refresh token. Essential for M2M (Machine-to-Machine) clients to maintain authenticated sessions without re-authentication.

**When to Use**:
- When the access token expires (default: 1 hour)
- M2M integrations that need long-running authenticated sessions
- Mobile/SPA applications that need to silently refresh tokens

**Authorization**: None (refresh token provides authentication)

**Request Body**:
```json
{
  "refreshToken": "eyJfQXV0aEVtdWxhdG9yUmVmcmVzaFRva2VuIjoiRE8gTk9UIE1PRElGWSIs..."
}
```

**Response**:
```json
{
  "accessToken": "eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0...",
  "refreshToken": "eyJfQXV0aEVtdWxhdG9yUmVmcmVzaFRva2VuIjoiRE8gTk9UIE1PRElGWSIs...",
  "expiresIn": 3600
}
```

**M2M Token Flow**:
1. Initial login via `/auth/login` returns access + refresh tokens
2. Store refresh token securely
3. When access token expires, call `/auth/refresh` with stored refresh token
4. Replace stored tokens with new ones from response
5. Repeat step 3-4 as needed

**Test Account**: Any account (e.g., `external-partner@ext.iptwins.com`)

---

### GET /users/me

**Purpose**: Retrieves the currently authenticated user's profile information.

**When to Use**:
- After login to display user profile
- To verify current user's role and permissions
- To check which brands the user has access to

**Authorization**: Any authenticated user

**Request Headers**:
```
Authorization: Bearer {accessToken}
```

**Response**:
```json
{
  "id": "76554c74-a127-5cdb-a39c-74e49d15c4c0",
  "email": "external-partner@ext.iptwins.com",
  "displayName": "external-partner",
  "roleId": "520f4369-9e75-5613-9ece-eb3248b6b962",
  "brandIds": ["beae4937-bf6e-55a8-864b-f56cd63bae95"],
  "status": "Active"
}
```

**Test Account**: Any authenticated account

---

### GET /users

**Purpose**: Lists all users in the system with pagination support.

**When to Use**:
- Admin dashboard to manage users
- User search and filtering
- Audit and compliance reporting

**Authorization**: `system-administrator` role only

**Request Headers**:
```
Authorization: Bearer {accessToken}
```

**Query Parameters**:
| Parameter | Type | Default | Description |
|:----------|:-----|:--------|:------------|
| `page` | number | 1 | Page number |
| `limit` | number | 20 | Items per page |

**Response**:
```json
{
  "items": [...],
  "total": 6,
  "page": 1,
  "limit": 20
}
```

**Test Account**: `system-administrator@ext.iptwins.com` or `admin-no2fa@ext.iptwins.com`

---

### GET /users/:id

**Purpose**: Retrieves a specific user by their UUID.

**When to Use**:
- View detailed user profile
- Admin user inspection
- Pre-populating user edit forms

**Authorization**: `system-administrator` role only

**Request Headers**:
```
Authorization: Bearer {accessToken}
```

**Path Parameters**:
| Parameter | Type | Description |
|:----------|:-----|:------------|
| `id` | UUID | User's unique identifier |

**Response**:
```json
{
  "id": "76554c74-a127-5cdb-a39c-74e49d15c4c0",
  "email": "external-partner@ext.iptwins.com",
  "displayName": "external-partner",
  "roleId": "520f4369-9e75-5613-9ece-eb3248b6b962",
  "brandIds": ["beae4937-bf6e-55a8-864b-f56cd63bae95"],
  "status": "Active",
  "hasAllBrandsAccess": false,
  "require2FA": false
}
```

**Test Account**: `system-administrator@ext.iptwins.com` or `admin-no2fa@ext.iptwins.com`

---

### POST /users/sync

**Purpose**: Triggers synchronization of user accounts from Domainarium external system.

**When to Use**:
- Initial system setup
- Periodic user synchronization
- After user changes in Domainarium

**Authorization**: `system-administrator` role only

**Request Headers**:
```
Authorization: Bearer {accessToken}
```

**Response**:
```json
{
  "synced": 6,
  "created": 0,
  "updated": 6
}
```

**Test Account**: `system-administrator@ext.iptwins.com` or `admin-no2fa@ext.iptwins.com`

---

### PATCH /users/batch

**Purpose**: Bulk updates multiple users' status and/or role assignment.

**When to Use**:
- Mass user activation/deactivation
- Batch role reassignment
- User cleanup operations

**Authorization**: `system-administrator` role only

**Request Headers**:
```
Authorization: Bearer {accessToken}
Content-Type: application/json
```

**Request Body**:
```json
{
  "userIds": ["uuid1", "uuid2", "uuid3"],
  "status": "Active",
  "roleId": "520f4369-9e75-5613-9ece-eb3248b6b962"
}
```

| Field | Type | Required | Description |
|:------|:-----|:---------|:------------|
| `userIds` | UUID[] | Yes | Array of user IDs to update |
| `status` | string | No* | New status: `Active`, `Inactive` |
| `roleId` | UUID | No* | New role ID to assign |

> *At least one of `status` or `roleId` must be provided.

**Response**:
```json
{
  "success": true,
  "updated": 3,
  "failed": []
}
```

**Test Account**: `system-administrator@ext.iptwins.com` or `admin-no2fa@ext.iptwins.com`

---

### GET /roles

**Purpose**: Lists all available roles in the system.

**When to Use**:
- Populating role dropdowns in UI
- Understanding role hierarchy
- Role assignment forms

**Authorization**: None (public endpoint)

**Response**:
```json
[
  {
    "id": "0559e250-9e20-5069-aad6-d42ba3eb8c28",
    "name": "System Administrator",
    "slug": "system-administrator",
    "permissions": ["*"]
  },
  {
    "id": "3893e3e3-c1bf-5313-b718-c04c2fa8b3ef",
    "name": "Account Manager",
    "slug": "account-manager",
    "permissions": ["finding:read", "finding:write", "task:read", "task:write"]
  }
]
```

**Test Account**: Any (no authentication required)

---

### GET /permissions

**Purpose**: Lists all available permissions in the system.

**When to Use**:
- Understanding available permissions
- Custom role creation (future)
- Permission documentation

**Authorization**: None (public endpoint)

**Response**:
```json
[
  "finding:read",
  "finding:write",
  "task:read",
  "task:write",
  "user:read",
  "user:write"
]
```

**Test Account**: Any (no authentication required)

---

## Audit Endpoints

### GET /audit-logs

**Purpose**: Queries system-wide audit logs with filtering and pagination.

**When to Use**:
- Compliance auditing
- Security incident investigation
- Activity monitoring
- Debugging and troubleshooting

**Authorization**: `system-administrator` role only

**Request Headers**:
```
Authorization: Bearer {accessToken}
```

**Query Parameters**:
| Parameter | Type | Default | Description |
|:----------|:-----|:--------|:------------|
| `user` | UUID | - | Filter by user ID |
| `scope` | string | - | Filter by scope (Identity, Brand, Monitoring, Discovery) |
| `startDate` | number | - | Start timestamp in microseconds |
| `endDate` | number | - | End timestamp in microseconds |
| `page` | number | 1 | Page number |
| `limit` | number | 20 | Items per page |

**Response**:
```json
{
  "items": [
    {
      "id": "0c3dddad-ff20-5516-9040-e1647dee7c4b",
      "userId": "",
      "scope": "Task",
      "operation": "Create",
      "description": "Task created: TechStart Marketplace Monitor",
      "resourceId": "f4ac4f7a-8b19-5793-9c87-258df398e9e4",
      "resourceType": "Task",
      "brandId": "beae4937-bf6e-55a8-864b-f56cd63bae95",
      "timestamp": 1700000000000000
    }
  ],
  "total": 10,
  "page": 1,
  "limit": 20
}
```

**Test Account**: `system-administrator@ext.iptwins.com` or `admin-no2fa@ext.iptwins.com`

---

### POST /audit-logs/export

**Purpose**: Exports audit logs to a downloadable file (CSV/XLSX).

**When to Use**:
- Compliance reporting
- External audit requirements
- Data backup/archival
- Offline analysis

**Authorization**: `system-administrator` role only

**Request Headers**:
```
Authorization: Bearer {accessToken}
Content-Type: application/json
```

**Request Body**:
```json
{
  "startDate": 1700000000000000,
  "endDate": 1710000000000000,
  "requesterId": "76554c74-a127-5cdb-a39c-74e49d15c4c0"
}
```

| Field | Type | Required | Description |
|:------|:-----|:---------|:------------|
| `startDate` | number | Yes | Start timestamp in microseconds |
| `endDate` | number | Yes | End timestamp in microseconds |
| `requesterId` | UUID | Yes | ID of user requesting export |

**Response**:
```json
{
  "url": "https://storage.googleapis.com/bucket/exports/audit-logs-2024-01-24.xlsx?token=..."
}
```

**Test Account**: `system-administrator@ext.iptwins.com` or `admin-no2fa@ext.iptwins.com`

---

### GET /tasks/:taskId/logs

**Purpose**: Retrieves audit logs for a specific monitoring task.

**When to Use**:
- Viewing task operation history
- Debugging task issues
- Auditing task configuration changes

**Authorization**: 
- `system-administrator` or `account-manager`: Full access
- Other roles: Must have access to the task's brand

**Request Headers**:
```
Authorization: Bearer {accessToken}
```

**Path Parameters**:
| Parameter | Type | Description |
|:----------|:-----|:------------|
| `taskId` | UUID | Monitoring task ID |

**Query Parameters**:
| Parameter | Type | Default | Description |
|:----------|:-----|:--------|:------------|
| `page` | number | 1 | Page number |
| `limit` | number | 20 | Items per page |

**Response**:
```json
{
  "items": [
    {
      "id": "0c3dddad-ff20-5516-9040-e1647dee7c4b",
      "scope": "Task",
      "operation": "Create",
      "description": "Task created: TechStart Marketplace Monitor",
      "resourceId": "f4ac4f7a-8b19-5793-9c87-258df398e9e4",
      "resourceType": "Task",
      "brandId": "beae4937-bf6e-55a8-864b-f56cd63bae95",
      "timestamp": 1700000000000000
    }
  ],
  "total": 1,
  "page": 1,
  "limit": 20
}
```

**Test Account**: 
- TechStart Inc task: `external-partner@ext.iptwins.com`
- Any brand: `account-manager@ext.iptwins.com` or `admin-no2fa@ext.iptwins.com`

---

### GET /phases/:phaseId/logs

**Purpose**: Retrieves audit logs for a specific phase.

**When to Use**:
- Viewing phase configuration history
- Debugging phase issues
- Auditing phase changes

**Authorization**: 
- `system-administrator` or `account-manager`: Full access
- Other roles: Must have access to the phase's brand

**Request Headers**:
```
Authorization: Bearer {accessToken}
```

**Path Parameters**:
| Parameter | Type | Description |
|:----------|:-----|:------------|
| `phaseId` | UUID | Phase ID |

**Query Parameters**:
| Parameter | Type | Default | Description |
|:----------|:-----|:--------|:------------|
| `page` | number | 1 | Page number |
| `limit` | number | 20 | Items per page |

**Test Account**: 
- TechStart Inc phase: `external-partner@ext.iptwins.com`
- Any brand: `account-manager@ext.iptwins.com` or `admin-no2fa@ext.iptwins.com`

---

### GET /phases/:phaseId/execution-logs

**Purpose**: Retrieves execution logs (scan operations) for a specific phase.

**When to Use**:
- Monitoring scan execution status
- Debugging crawling issues
- Performance analysis
- AI triage execution tracking

**Authorization**: 
- `system-administrator` or `account-manager`: Full access
- Other roles: Must have access to the phase's brand

**Request Headers**:
```
Authorization: Bearer {accessToken}
```

**Path Parameters**:
| Parameter | Type | Description |
|:----------|:-----|:------------|
| `phaseId` | UUID | Phase ID |

**Query Parameters**:
| Parameter | Type | Default | Description |
|:----------|:-----|:--------|:------------|
| `page` | number | 1 | Page number |
| `limit` | number | 20 | Items per page |
| `status` | string | - | Filter by status (Completed, Failed, Running) |
| `startDate` | number | - | Filter by start date |
| `endDate` | number | - | Filter by end date |

**Response**:
```json
{
  "items": [
    {
      "id": "ed9f6488-0035-5723-994c-46cec8681ddf",
      "taskId": "f4ac4f7a-8b19-5793-9c87-258df398e9e4",
      "phaseId": "4715a97a-e262-5e76-9d04-789b9c5fb14c",
      "brandId": "beae4937-bf6e-55a8-864b-f56cd63bae95",
      "executionType": "Scan",
      "status": "Completed",
      "startedAt": 1700000000000000,
      "endedAt": 1700000060000000,
      "durationMs": 60000,
      "itemsProcessed": 150
    }
  ],
  "total": 2,
  "page": 1,
  "limit": 20
}
```

**Test Account**: 
- TechStart Inc phase: `external-partner@ext.iptwins.com`
- Any brand: `account-manager@ext.iptwins.com` or `admin-no2fa@ext.iptwins.com`

---

### GET /findings/:id/logs

**Purpose**: Retrieves audit logs for a specific finding.

**When to Use**:
- Viewing finding processing history
- Tracking status changes
- Auditing classification and labeling
- Takedown request history

**Authorization**: 
- `system-administrator` or `account-manager`: Full access
- Other roles: Must have access to the finding's brand

**Request Headers**:
```
Authorization: Bearer {accessToken}
```

**Path Parameters**:
| Parameter | Type | Description |
|:----------|:-----|:------------|
| `id` | UUID | Finding ID |

**Query Parameters**:
| Parameter | Type | Default | Description |
|:----------|:-----|:--------|:------------|
| `page` | number | 1 | Page number |
| `limit` | number | 20 | Items per page |

**Test Account**: 
- TechStart Inc finding: `external-partner@ext.iptwins.com`
- Any brand: `account-manager@ext.iptwins.com` or `admin-no2fa@ext.iptwins.com`

---

### GET /findings/:findingId/execution-logs

**Purpose**: Retrieves execution logs (retain operations) for a specific finding.

**When to Use**:
- Tracking finding processing status
- Debugging finding retention issues
- Performance analysis

**Authorization**: 
- `system-administrator` or `account-manager`: Full access
- Other roles: Must have access to the finding's brand

**Request Headers**:
```
Authorization: Bearer {accessToken}
```

**Path Parameters**:
| Parameter | Type | Description |
|:----------|:-----|:------------|
| `findingId` | UUID | Finding ID |

**Query Parameters**:
| Parameter | Type | Default | Description |
|:----------|:-----|:--------|:------------|
| `page` | number | 1 | Page number |
| `limit` | number | 20 | Items per page |

**Response**:
```json
{
  "items": [
    {
      "id": "bd66cb6a-f4c1-5b6c-8b59-18e8555c080b",
      "taskId": "f4ac4f7a-8b19-5793-9c87-258df398e9e4",
      "findingId": "58f637c3-a864-56fd-8bab-bb03dc75d0b0",
      "brandId": "beae4937-bf6e-55a8-864b-f56cd63bae95",
      "executionType": "Retain",
      "status": "Completed",
      "startedAt": 1700000100000000,
      "endedAt": 1700000105000000,
      "durationMs": 5000,
      "itemsProcessed": 1
    }
  ],
  "total": 1,
  "page": 1,
  "limit": 20
}
```

**Test Account**: 
- TechStart Inc finding: `external-partner@ext.iptwins.com`
- Any brand: `account-manager@ext.iptwins.com` or `admin-no2fa@ext.iptwins.com`

---

## Quick Reference: Entity IDs for Testing

| Entity | Brand | ID | Description |
|:-------|:------|:---|:------------|
| Brand | TechStart Inc | `beae4937-bf6e-55a8-864b-f56cd63bae95` | Test brand |
| Task | TechStart Inc | `f4ac4f7a-8b19-5793-9c87-258df398e9e4` | TechStart Marketplace Monitor |
| Phase | TechStart Inc | `4715a97a-e262-5e76-9d04-789b9c5fb14c` | Q1 2024 |
| Finding | TechStart Inc | `58f637c3-a864-56fd-8bab-bb03dc75d0b0` | Fake TechStart Gadget |

---

## Error Responses

All endpoints return consistent error responses:

```json
{
  "error": "Error message description"
}
```

| HTTP Status | Meaning |
|:------------|:--------|
| 400 | Bad Request - Missing or invalid parameters |
| 401 | Unauthorized - Missing or invalid token |
| 403 | Forbidden - Insufficient permissions or brand access |
| 404 | Not Found - Resource does not exist |
| 500 | Internal Server Error |
