Use the REST API to create scan sessions, check their progress, and pull results. All you need is an enterprise API token.
Every request needs your API token in one of these headers:
https://detect.ac/auth/api/enterprise
All paths in this doc are relative to this base.
| Field | Type | Required | Description |
|---|---|---|---|
game |
string | Yes | Short game code (see Reference → Game Codes) |
{
"game": "mc"
}
{
"status": "success",
"pin": "12345678",
"access_token": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx-12345678",
"game": "mc",
"download_url": "https://detect.ac/auth/dl/mc/12345678",
"expires_at": "2025-01-02T16:04:05Z"
}
access_token from this response — you can pass it directly to the results endpoint instead of just the PIN. Send the download_url to whoever needs to be scanned. The session expires in 1 hour.| Param | Type | Description |
|---|---|---|
:pin |
string | 8-digit session PIN |
{
"pin": "12345678",
"status": "scan-scanning",
"stage": 5,
"results": [],
"scanner_alive": true,
"used": false
}
| Param | Type | Description |
|---|---|---|
:token |
string | The full access_token from Create Session (uuid-pin), or just the 8-digit PIN as a fallback |
{
"pin": "12345678",
"status": "scan-completed",
"results": {
"logs": [...]
},
"access_token": "uuid-12345678",
"saved": true
}
EAP:RSLT_3 if the scan hasn't finished yet. Wait for scan-completed on the status endpoint first.access_token (not just the PIN) in the URL for a reliable exact lookup. The PIN-only form still works as a fallback but can miss results if the scanning client saved and cleaned up the session before you polled.Use one of these codes in the game field.
mcMinecraftfmFiveMrmRageMPcodCall of DutyfnFortniteavalt:VdzDayZruRustgmGarry's Modr6Rainbow SixffFree FirerbRoblox| Status | Description |
|---|---|
| active | Session created, waiting for scanner download |
| scan-connected | Scanner downloaded and connected |
| scan-scanning | Scan in progress |
| scan-completed | Scan finished — results available via /session/results/:pin |
| scan-timed-out | Scanner disconnected during scan |
Errors come back as EAP:<CATEGORY>_<NUMBER>.
| Code | HTTP | Description |
|---|---|---|
EAP:AUTH_1 | 401 | Missing API token |
EAP:AUTH_2 | 401 | Invalid API token format |
EAP:AUTH_3 | 401 | Invalid API token |
EAP:AUTH_4 | 403 | Enterprise is banned |
| Code | HTTP | Description |
|---|---|---|
EAP:SESS_1 | 400 | Missing or invalid game field |
EAP:SESS_2 | 400 | Invalid game code |
EAP:SESS_3 | 500 | Failed to verify license |
EAP:SESS_4 | 403 | Active license required |
EAP:SESS_5 | 500 | Failed to create session |
| Code | HTTP | Description |
|---|---|---|
EAP:STAT_1 | 404 | Session not found |
EAP:STAT_2 | 403 | Session does not belong to your enterprise |
| Code | HTTP | Description |
|---|---|---|
EAP:RSLT_1 | 404 | Session not found |
EAP:RSLT_2 | 403 | Session does not belong to your enterprise |
EAP:RSLT_3 | 400 | Scan not yet completed |
EAP:RSLT_4 | 404 | No scan data available |
EAP:RSLT_5 | 500 | Failed to parse scan data |
Go examples for each endpoint.
package main import ( "bytes" "encoding/json" "fmt" "net/http" ) const ( baseURL = "https://detect.ac/auth/api/enterprise" apiToken = "dtc_your_token_here" ) func createSession(game string) (string, string, error) { body, _ := json.Marshal(map[string]string{"game": game}) req, _ := http.NewRequest("POST", baseURL+"/session/create", bytes.NewReader(body)) req.Header.Set("X-API-Key", apiToken) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { return "", "", err } defer resp.Body.Close() var result map[string]interface{} json.NewDecoder(resp.Body).Decode(&result) if resp.StatusCode != 200 { return "", "", fmt.Errorf("error: %v", result["error"]) } return result["pin"].(string), result["download_url"].(string), nil } func main() { pin, downloadURL, err := createSession("mc") if err != nil { panic(err) } fmt.Printf("Session PIN: %s\nDownload URL: %s\n", pin, downloadURL) }
package main import ( "encoding/json" "fmt" "net/http" "time" ) const ( baseURL = "https://detect.ac/auth/api/enterprise" apiToken = "dtc_your_token_here" ) func checkStatus(pin string) (string, int, error) { req, _ := http.NewRequest("GET", baseURL+"/session/status/"+pin, nil) req.Header.Set("X-API-Key", apiToken) resp, err := http.DefaultClient.Do(req) if err != nil { return "", 0, err } defer resp.Body.Close() var result map[string]interface{} json.NewDecoder(resp.Body).Decode(&result) status := result["status"].(string) stage := int(result["stage"].(float64)) return status, stage, nil } func main() { pin := "12345678" for { status, stage, err := checkStatus(pin) if err != nil { panic(err) } fmt.Printf("Status: %s | Stage: %d\n", status, stage) if status == "scan-completed" { fmt.Println("Scan complete! Fetching results...") break } time.Sleep(3 * time.Second) } }
package main import ( "encoding/json" "fmt" "net/http" ) const ( baseURL = "https://detect.ac/auth/api/enterprise" apiToken = "dtc_your_token_here" ) func getResults(accessToken string) (map[string]interface{}, error) { req, _ := http.NewRequest("GET", baseURL+"/session/results/"+accessToken, nil) req.Header.Set("X-API-Key", apiToken) resp, err := http.DefaultClient.Do(req) if err != nil { return nil, err } defer resp.Body.Close() var result map[string]interface{} json.NewDecoder(resp.Body).Decode(&result) if resp.StatusCode != 200 { return nil, fmt.Errorf("error: %v", result["error"]) } return result, nil } func main() { pin := "12345678" accessToken := "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx-12345678" results, err := getResults(accessToken) if err != nil { panic(err) } data, _ := json.MarshalIndent(results, "", " ") fmt.Println(string(data)) if saved, ok := results["saved"].(bool); ok && saved { fmt.Printf("Scan saved with access token: %s\n", results["access_token"]) } }
package main import ( "bytes" "encoding/json" "fmt" "net/http" "time" ) const ( baseURL = "https://detect.ac/auth/api/enterprise" apiToken = "dtc_your_token_here" ) func apiRequest(method, path string, body interface{}) (map[string]interface{}, int, error) { var reqBody *bytes.Reader if body != nil { data, _ := json.Marshal(body) reqBody = bytes.NewReader(data) } else { reqBody = bytes.NewReader(nil) } req, _ := http.NewRequest(method, baseURL+path, reqBody) req.Header.Set("X-API-Key", apiToken) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { return nil, 0, err } defer resp.Body.Close() var result map[string]interface{} json.NewDecoder(resp.Body).Decode(&result) return result, resp.StatusCode, nil } func main() { result, code, err := apiRequest("POST", "/session/create", map[string]string{"game": "mc"}) if err != nil || code != 200 { fmt.Printf("Failed to create session: %v (code: %d)\n", result["error"], code) return } pin := result["pin"].(string) accessToken := result["access_token"].(string) downloadURL := result["download_url"].(string) fmt.Printf("Session created!\n PIN: %s\n Token: %s\n Download: %s\n\n", pin, accessToken, downloadURL) fmt.Println("Waiting for scan to complete...") for { result, _, err = apiRequest("GET", "/session/status/"+pin, nil) if err != nil { fmt.Printf("Status check failed: %v\n", err) return } status := result["status"].(string) stage := int(result["stage"].(float64)) fmt.Printf(" Status: %-18s Stage: %d\n", status, stage) if status == "scan-completed" { break } if status == "scan-timed-out" { fmt.Println("Scanner timed out!") return } time.Sleep(3 * time.Second) } result, code, err = apiRequest("GET", "/session/results/"+accessToken, nil) if err != nil || code != 200 { fmt.Printf("Failed to get results: %v\n", result["error"]) return } data, _ := json.MarshalIndent(result["results"], "", " ") fmt.Printf("\nScan Results:\n%s\n", string(data)) if token, ok := result["access_token"].(string); ok { fmt.Printf("\nSaved with access token: %s\n", token) } }