https://api.subproject55.com
All endpoints are prefixed with /api/ (e.g., /api/auth/login).
The API supports two authentication methods:
# Login to get tokens
POST /api/auth/login
Content-Type: application/x-www-form-urlencoded
username=admin&password=yourpassword
# Response
{
"access_token": "eyJ...",
"refresh_token": "eyJ...",
"token_type": "bearer"
}
# Use in requests
Authorization: Bearer <access_token># Generate API key via web interface or API
POST /api/auth/api-keys
Authorization: Bearer <access_token>
{
"name": "CLI Tool"
}
# Use in requests
X-API-Key: <api_key>POST /api/auth/login
Content-Type: application/x-www-form-urlencoded
username=admin&password=yourpasswordResponse:
{
"access_token": "eyJ...",
"refresh_token": "eyJ...",
"token_type": "bearer"
}POST /api/auth/refresh
Content-Type: application/x-www-form-urlencoded
refresh_token=eyJ...GET /api/auth/me
Authorization: Bearer <access_token>Response:
{
"id": "uuid",
"username": "admin",
"email": "admin@example.com",
"role": "admin",
"is_active": true,
"created_at": "2024-01-15T10:00:00Z"
}POST /api/auth/api-keys
{
"name": "CLI Tool"
}Response:
{
"id": "uuid",
"name": "CLI Tool",
"key": "udk_abc123...",
"created_at": "2024-01-15T10:00:00Z"
}Note: The key is only returned on creation. Store it securely.
GET /api/auth/api-keysResponse:
[
{
"id": "uuid",
"name": "CLI Tool",
"created_at": "2024-01-15T10:00:00Z",
"last_used_at": "2024-01-16T14:30:00Z"
}
]DELETE /api/auth/api-keys/{key_id}POST /api/auth/change-password
{
"current_password": "oldpassword",
"new_password": "newpassword123!"
}Password requirements:
- Minimum 12 characters
- At least one uppercase letter
- At least one lowercase letter
- At least one digit
- At least one special character
GET /api/auth/usersResponse:
[
{
"id": "uuid",
"username": "operator1",
"email": "operator@example.com",
"role": "operator",
"is_active": true,
"created_at": "2024-01-15T10:00:00Z"
}
]POST /api/auth/users
{
"username": "newuser",
"email": "newuser@example.com",
"password": "SecurePass123!",
"role": "operator"
}Available roles: admin, operator, viewer
GET /api/auth/users/{user_id}PUT /api/auth/users/{user_id}
{
"email": "updated@example.com",
"role": "viewer",
"is_active": false
}Deactivates the user account.
DELETE /api/auth/users/{user_id}POST /api/auth/users/{user_id}/reset-password
{
"new_password": "NewSecurePass123!"
}GET /api/auth/rolesResponse:
{
"roles": [
{"name": "admin", "description": "Full access to all features"},
{"name": "operator", "description": "Can manage campaigns and drives"},
{"name": "viewer", "description": "Read-only access"}
]
}GET /api/campaignsResponse:
[
{
"id": "uuid",
"name": "Q1 2024 Assessment",
"client_name": "Acme Corp",
"status": "active",
"drive_count": 10,
"triggered_count": 3,
"created_at": "2024-01-15T10:00:00Z"
}
]POST /api/campaigns
{
"name": "Q1 2024 Assessment",
"client_name": "Acme Corp",
"description": "Quarterly security assessment",
"landing_page_config": {
"mode": "included",
"included_theme": "corporate",
"delay_seconds": 5
}
}Landing Page Configuration:
mode:"disabled","included"(built-in theme), or"custom_url"included_theme: Theme name when using included modecustom_url: Custom landing page URL when usingcustom_urlmodedelay_seconds: Redirect delay in seconds (1-30, default: 3)
GET /api/campaigns/landing-pages/themesResponse:
{
"themes": [
{"id": "corporate", "name": "Corporate Portal", "description": "Professional business page"},
{"id": "login", "name": "Login Page", "description": "Generic login form"},
{"id": "maintenance", "name": "Maintenance", "description": "Site maintenance notice"},
{"id": "helpdesk", "name": "IT Helpdesk", "description": "IT support portal"},
{"id": "hrportal", "name": "HR Portal", "description": "Human resources portal"},
{"id": "fileshare", "name": "File Share", "description": "File sharing service"},
{"id": "training", "name": "Training Portal", "description": "Corporate training"},
{"id": "banking", "name": "Banking", "description": "Financial services"},
{"id": "document", "name": "Document Viewer", "description": "Document preview"},
{"id": "survey", "name": "Survey", "description": "Feedback survey"},
{"id": "onlyfans", "name": "OnlyFans", "description": "Content creator page"}
]
}GET /api/campaigns/{id}PUT /api/campaigns/{id}
{
"name": "Updated Name",
"status": "completed",
"landing_page_config": {
"mode": "included",
"included_theme": "fileshare",
"delay_seconds": 10
}
}Shows what will be deleted (drives, tokens) before confirming.
GET /api/campaigns/{id}/delete-previewResponse:
{
"campaign": {"id": "uuid", "name": "Q1 Assessment"},
"drives_count": 10,
"tokens_count": 45,
"triggers_count": 12,
"deployments_count": 8,
"warning": "This action cannot be undone"
}Deletes campaign and cascades to all drives, tokens, and deployments.
DELETE /api/campaigns/{id}GET /api/campaigns/{id}/statsResponse:
{
"total_drives": 10,
"deployed": 8,
"triggered": 3,
"drives_by_status": {
"created": 1,
"prepared": 1,
"deployed": 5,
"triggered": 3
}
}GET /api/profilesPOST /api/profiles
{
"name": "HR Payroll",
"description": "HR department payroll documents",
"scenario_type": "hr",
"theme": "corporate",
"token_config": {
"types": ["dns", "word", "excel"]
},
"label_suggestions": ["Payroll Q4", "Benefits 2024"]
}GET /api/profiles/{id}PUT /api/profiles/{id}
{
"name": "Updated Name",
"description": "Updated description"
}DELETE /api/profiles/{id}POST /api/profiles/{id}/toggleShows files and tokens that would be generated.
GET /api/profiles/{id}/previewResponse:
{
"files": [
{"name": "Payroll_Summary.docx", "type": "word"},
{"name": "Benefits_Overview.xlsx", "type": "excel"}
],
"tokens": ["dns", "word", "excel"],
"folders": ["Documents", "Photos"]
}GET /api/profiles/templates/listResponse:
[
{
"id": "it_department",
"name": "IT Department",
"category": "corporate",
"description": "IT support and network files"
}
]GET /api/profiles/templates/{template_id}POST /api/profiles/from-template/{template_id}
{
"name": "Custom IT Profile",
"url_config": {
"enabled": true,
"base_slug": "it-docs"
}
}GET /api/profiles/template-images/listResponse:
{
"templates": {
"it_department": {
"name": "IT Department",
"images": ["server_room.jpg", "network_diagram.jpg"]
},
"social_creator": {
"name": "Social Creator",
"images": ["beach_sunset.jpg", "coffee_shop.jpg"]
}
}
}GET /api/profiles/template-images/{template_id}/{filename}Returns the image file.
GET /api/profiles/text-templates/listResponse:
[
{"id": "password_list", "name": "Password List", "description": "Fake credentials file"},
{"id": "meeting_notes", "name": "Meeting Notes", "description": "Corporate meeting notes"},
{"id": "project_notes", "name": "Project Notes", "description": "Technical documentation"},
{"id": "personal_notes", "name": "Personal Notes", "description": "Diary-style notes"},
{"id": "todo_list", "name": "Todo List", "description": "Task list with URLs"}
]GET /api/profiles/text-templates/{template_id}GET /api/profiles/token-types/listResponse:
[
{"id": "dns", "name": "DNS Token", "extension": null},
{"id": "word", "name": "Word Document", "extension": ".docx"},
{"id": "excel", "name": "Excel Spreadsheet", "extension": ".xlsx"},
{"id": "pdf", "name": "PDF Document", "extension": ".pdf"},
{"id": "url", "name": "HTTP URL", "extension": ".txt"},
{"id": "qr", "name": "QR Code", "extension": ".png"}
]Manage uploaded files for a profile.
GET /api/profiles/{profile_id}/filesPOST /api/profiles/{profile_id}/files
Content-Type: multipart/form-data
file: <binary>
folder: "Documents"
file_type: "static"File types: static, document, template
GET /api/profiles/{profile_id}/files/{file_id}PUT /api/profiles/{profile_id}/files/{file_id}
{
"folder": "Photos",
"display_name": "vacation.jpg"
}GET /api/profiles/{profile_id}/files/{file_id}/downloadDELETE /api/profiles/{profile_id}/files/{file_id}POST /api/profiles/{profile_id}/files/reorder
{
"file_ids": ["uuid1", "uuid2", "uuid3"]
}POST /api/profiles/{profile_id}/shortcuts
{
"filename": "Important Link.url",
"target_url": "{canary_token-URL}",
"folder": "Documents",
"shortcut_type": "url"
}Shortcut types: url (Windows), webloc (macOS)
POST /api/profiles/{profile_id}/templates
{
"filename": "passwords.txt",
"template_id": "password_list",
"folder": "Private",
"custom_content": null
}POST /api/profiles/{profile_id}/templates/{file_id}/preview
{
"token_urls": {
"{canary_token-URL}": "https://example.com/token123"
}
}GET /api/drives?campaign_id={uuid}&status={status}Status values: created, prepared, deployed, triggered, recovered
POST /api/drives
{
"campaign_id": "uuid",
"profile_id": "uuid",
"label": "HR Payroll Q4",
"url_config": {
"enabled": true,
"domain": "links.example.com",
"base_slug": "hr-docs",
"suffix_mode": "random",
"suffix_length": 4
}
}The url_config field is optional. If omitted, the drive inherits URL settings from its profile.
Response:
{
"id": "uuid",
"unique_code": "USB-A1B2C3",
"status": "created",
"label": "HR Payroll Q4"
}GET /api/drives/by-code/{code}GET /api/drives/{id}PUT /api/drives/{id}
{
"label": "Updated Label",
"notes": "Additional notes"
}Deletes drive and all associated tokens from database and CanaryTokens server.
DELETE /api/drives/{id}Creates tokens and generates files.
POST /api/drives/{id}/prepareResponse:
{
"id": "uuid",
"status": "prepared",
"tokens": [
{"id": "uuid", "token_type": "dns", "filename": null},
{"id": "uuid", "token_type": "word", "filename": "Payroll_Summary.docx"}
],
"files_manifest": {
"file_count": 12,
"total_size_bytes": 1048576
}
}GET /api/drives/{id}/downloadReturns a ZIP file containing all drive files.
Record deployment location.
POST /api/drives/{id}/deploy
{
"latitude": 37.7749,
"longitude": -122.4194,
"location_description": "Building A lobby",
"deployed_by": "John Smith"
}Record deployment with photo (extracts GPS from EXIF).
POST /api/drives/{id}/deploy-with-photo
Content-Type: multipart/form-data
photo: <binary>
location_description: "Near reception"
deployed_by: "John Smith"GET /api/drives/{id}/tokensGET /api/drives/{id}/deploymentResponse:
{
"id": "uuid",
"drive_id": "uuid",
"latitude": 37.7749,
"longitude": -122.4194,
"location_name": "Building A",
"location_description": "Main lobby entrance",
"location_type": "office_building",
"address": "123 Main St",
"city": "San Francisco",
"state": "CA",
"country": "US",
"photo_url": "/uploads/deployments/photo.jpg",
"deployed_by": "John Smith",
"deployment_notes": "Left near reception desk",
"deployed_at": "2024-01-15T10:00:00Z"
}PUT /api/drives/{id}/deployment
{
"location_description": "Updated location",
"deployment_notes": "Added more details"
}GET /api/tokens/{token_id}Response:
{
"id": "uuid",
"drive_id": "uuid",
"token_type": "word",
"filename": "Payroll_Summary.docx",
"canary_token_id": "abc123",
"token_url": "https://tokens.example.com/abc123",
"created_at": "2024-01-15T10:00:00Z",
"trigger_count": 5
}GET /api/tokens/{token_id}/triggersResponse:
[
{
"id": "uuid",
"source_ip": "192.168.1.100",
"user_agent": "Mozilla/5.0...",
"geo_city": "San Francisco",
"geo_country": "US",
"triggered_at": "2024-01-15T14:30:00Z"
}
]Deletes token from database and CanaryTokens server.
DELETE /api/tokens/{token_id}Manage shortened URLs for tokens.
POST /api/shortener/drives/{drive_id}/tokens/{token_id}
{
"custom_slug": "hr-docs-2024"
}Response:
{
"id": "uuid",
"short_url": "https://links.example.com/hr-docs-2024",
"target_url": "https://tokens.example.com/abc123",
"slug": "hr-docs-2024",
"created_at": "2024-01-15T10:00:00Z"
}GET /api/shortener/drives/{drive_id}GET /api/shortener/{short_url_id}GET /api/shortener/{short_url_id}/statsResponse:
{
"id": "uuid",
"short_url": "https://links.example.com/hr-docs-2024",
"visit_count": 42,
"visits_by_day": {
"2024-01-15": 10,
"2024-01-16": 32
}
}DELETE /api/shortener/{short_url_id}POST /api/shortener/bulk/drives/{drive_id}
{
"token_ids": ["uuid1", "uuid2", "uuid3"],
"base_slug": "hr-docs",
"suffix_mode": "random"
}Manage target organization profiles for campaigns.
GET /api/targets/optionsResponse:
{
"industries": ["technology", "finance", "healthcare", "manufacturing", "retail", "other"],
"company_sizes": ["startup", "smb", "mid_market", "enterprise", "global"],
"departments": ["it", "hr", "finance", "executive", "engineering", "sales", "marketing"],
"regions": ["us_east", "us_west", "europe", "asia_pacific", "latam"]
}GET /api/targets?industry={industry}POST /api/targets
{
"name": "Acme Corp Assessment",
"company_name": "Acme Corporation",
"industry": "technology",
"company_size": "enterprise",
"target_department": "engineering",
"geographic_region": "us_west",
"known_technologies": ["AWS", "Kubernetes", "Python"],
"email_domain": "acme.com",
"website": "https://acme.com",
"osint_notes": "Uses Slack for internal comms"
}GET /api/targets/{target_id}PUT /api/targets/{target_id}
{
"osint_notes": "Updated reconnaissance notes"
}DELETE /api/targets/{target_id}Uses AI to recommend the best profile scenario for the target.
POST /api/targets/{target_id}/recommend-scenarioResponse:
{
"recommended_profile": "it_department",
"confidence": "high",
"reasoning": "Target is a tech company with engineering focus...",
"alternative_profiles": ["developer", "network_admin"],
"suggested_labels": ["IT Tools Q4", "DevOps Resources"],
"suggested_filenames": ["kubernetes_config.docx", "aws_credentials.xlsx"],
"risk_factors": ["Tech-savvy employees may be suspicious"],
"tips": ["Use technical jargon in filenames"]
}GET /api/alerts/recent?hours=24Response:
[
{
"id": "uuid",
"drive_code": "USB-A1B2C3",
"token_type": "word",
"token_filename": "Payroll_Summary.docx",
"source_ip": "192.168.1.100",
"geo_city": "San Francisco",
"geo_country": "US",
"triggered_at": "2024-01-15T14:30:00Z"
}
]GET /api/alerts/stats?campaign_id={uuid}Response:
{
"total": 150,
"today": 5,
"this_week": 23,
"unique_ips": 45
}GET /api/alerts/map?campaign_id={uuid}Response:
[
{
"id": "uuid",
"type": "deployment",
"latitude": 37.7749,
"longitude": -122.4194,
"label": "Dropped: USB-A1B2",
"drive_code": "USB-A1B2",
"timestamp": "2024-01-15T10:00:00Z",
"details": {
"location_name": "Building A",
"location_type": "office_building"
}
},
{
"id": "uuid",
"type": "trigger",
"latitude": 37.7849,
"longitude": -122.4094,
"label": "Triggered: USB-A1B2",
"drive_code": "USB-A1B2",
"timestamp": "2024-01-15T14:30:00Z",
"details": {
"token_type": "word",
"filename": "Payroll_Summary.docx",
"source_ip": "192.168.1.100"
}
}
]POST /api/generate/document
{
"document_type": "memo",
"topic": "Q4 payroll adjustments",
"tone": "professional",
"length": "medium"
}Response:
{
"content": "MEMORANDUM\n\nTo: All Employees...",
"filename": "memo_payroll_adjustments.docx"
}POST /api/generate/image
{
"prompt": "Professional corporate office building",
"style": "photorealistic",
"size": "1024x1024"
}GET /api/reports/campaign/{id}Response:
{
"campaign": {
"id": "uuid",
"name": "Q1 Assessment",
"client_name": "Acme Corp"
},
"total_drives": 10,
"deployed": 8,
"triggered": 3,
"total_triggers": 15,
"status_distribution": {
"created": 1,
"prepared": 1,
"deployed": 5,
"triggered": 3
},
"triggers_by_day": {
"2024-01-15": 5,
"2024-01-16": 10
},
"triggers_by_type": {
"dns": 3,
"word": 8,
"excel": 4
},
"top_drives": [
{
"id": "uuid",
"unique_code": "USB-A1B2",
"trigger_count": 5,
"first_trigger": "2024-01-15T14:30:00Z"
}
]
}GET /api/reports/export/{id}/csvReturns a CSV file with all campaign data.
Receives trigger notifications from CanaryTokens.
POST /api/webhooks/canary
{
"token": "canary-token-id",
"src_ip": "192.168.1.100",
"user_agent": "Mozilla/5.0...",
"additional_data": {}
}GET /api/settings/shlink/statusResponse:
{
"connected": true,
"domain": "links.subproject55.com",
"api_url": "http://shlink:8080",
"short_url_count": 42,
"error": null
}GET /api/settings/shlink/configPOST /api/settings/shlink/testResponse:
{
"success": true,
"test_url": "https://example.com/test",
"short_url": "https://links.example.com/abc123",
"error": null
}GET /api/settings/url-configsPUT /api/settings/url-configs/{profile_id}
{
"enabled": true,
"base_slug": "hr-docs",
"suffix_mode": "random",
"suffix_length": 4
}Suffix modes:
random- Random alphanumeric suffixdrive_code- Uses drive codesequential- Sequential numbering
PUT /api/settings/url-configs/bulk
[
{
"id": "profile-uuid",
"enabled": true,
"base_slug": "hr-docs"
}
]All errors follow this format:
{
"detail": "Error message here"
}Validation errors include field details:
{
"detail": [
{
"loc": ["body", "email"],
"msg": "Invalid email format",
"type": "value_error"
}
]
}Common HTTP status codes:
400- Bad Request (invalid input)401- Unauthorized (missing/invalid auth)403- Forbidden (insufficient permissions)404- Not Found422- Validation Error500- Internal Server Error
API requests are limited to:
- 100 requests per minute for authenticated users
- 10 requests per minute for unauthenticated endpoints
Rate limit headers:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1705329600