Documents
agent-api-complete-reference
agent-api-complete-reference
Type
External
Status
Published
Created
Feb 27, 2026
Updated
Mar 30, 2026
Updated by
Dosu Bot

CipherSwarm Agent API Complete Reference#

Version: 1.3 Base URL: https://cipherswarm.com/api/v1/client Authentication: Bearer Token Content-Type: application/json


Overview#

The CipherSwarm Agent API enables distributed hash-cracking agents to communicate with the CipherSwarm server. Agents authenticate using bearer tokens, receive task assignments, report progress, and submit cracked hashes.

API Workflow#

Agent Startup:
  1. GET /authenticate → Verify token validity
  2. GET /configuration → Get agent settings
  3. PUT /agents/{id} → Register device info
  4. POST /agents/{id}/submit_benchmark → Submit benchmarks

Task Loop:
  5. GET /tasks/new → Request task
  6. POST /tasks/{id}/accept_task → Accept task
  7. GET /attacks/{id} → Get attack parameters
  8. GET /attacks/{id}/hash_list → Download hashes

Work Loop:
  9. POST /tasks/{id}/submit_status → Report progress
  10. POST /tasks/{id}/submit_crack → Submit cracks
  11. GET /tasks/{id}/get_zaps → Get completed hashes

Completion:
  12. POST /tasks/{id}/exhausted → Mark complete
  -or-
  12. POST /tasks/{id}/abandon → Abandon task

Maintenance:
  POST /agents/{id}/heartbeat → Keep alive
  POST /agents/{id}/submit_error → Report errors
  POST /agents/{id}/shutdown → Graceful shutdown

Authentication#

All API requests require a Bearer token in the Authorization header.

Authorization: Bearer <agent_token>

Token Format#

  • 24-character alphanumeric string
  • Generated when agent is created in web UI
  • Stored in agents.token column
  • Revokable by admin

Security#

The server validates agent tokens using constant-time comparison (ActiveSupport::SecurityUtils.secure_compare) to prevent timing attacks. This security measure protects against attackers attempting to enumerate valid agent tokens by measuring authentication response times. All authentication operations take constant time regardless of token validity, ensuring that timing information cannot leak whether a token is valid or not.

This protection operates server-side and is transparent to API clients. Agents continue to use Bearer token authentication as documented, with no changes required to client implementations.

Authentication Errors#

StatusMeaning
401Invalid or missing token
403Agent is stopped or in error state

Endpoints#

Client Authentication#

GET /authenticate#

Verify agent token and retrieve agent ID.

Response (200 OK):

{
  "authenticated": true,
  "agent_id": 42
}

Response (401 Unauthorized):

{
  "error": "Invalid token"
}

GET /configuration#

Get agent configuration settings.

Response (200 OK):

{
  "config": {
    "agent_update_interval": 60,
    "use_native_hashcat": false,
    "backend_device": null,
    "opencl_devices": null,
    "enable_additional_hash_types": false
  },
  "api_version": 1
}

Agent Management#

GET /agents/{id}#

Get agent details.

Parameters:

NameTypeRequiredDescription
idintegerYesAgent ID

Response (200 OK):

{
  "id": 42,
  "host_name": "cracker-01",
  "client_signature": "CipherSwarmAgent/1.0",
  "state": "active",
  "operating_system": "Linux 5.15.0",
  "devices": [
    "NVIDIA RTX 4090",
    "NVIDIA RTX 4090"
  ],
  "current_activity": "cracking",
  "advanced_configuration": {
    "agent_update_interval": 60,
    "use_native_hashcat": false,
    "backend_device": "1,2",
    "opencl_devices": null,
    "enable_additional_hash_types": false
  }
}

Agent States:

StateDescription
pendingAgent needs to complete setup (benchmarks)
activeAgent is ready to accept tasks
stoppedAgent has been stopped by administrator
errorAgent encountered an error

PUT /agents/{id}#

Update agent information (typically on startup).

Request Body:

{
  "id": 42,
  "host_name": "cracker-01",
  "client_signature": "CipherSwarmAgent/1.0",
  "operating_system": "Linux 5.15.0",
  "devices": [
    "NVIDIA RTX 4090",
    "NVIDIA RTX 4090"
  ]
}

Response (200 OK): Returns updated Agent object.


POST /agents/{id}/heartbeat#

Send heartbeat to keep agent alive. Should be called at regular intervals (default: every 60 seconds).

Request Body (optional):

{
  "activity": "cracking"
}

Activity Values:

ActivityDescription
startingAgent is starting up
benchmarkingRunning hashcat benchmarks
updatingUpdating hashcat or agent
downloadingDownloading resources (wordlists, rules)
waitingIdle, waiting for tasks
crackingActively working on a task
stoppingShutting down

Response (204 No Content): Heartbeat accepted, agent is in good state.

Response (200 OK): Server has feedback for agent:

{
  "state": "pending"
}

Possible states in response:

  • pending - Agent needs to re-run benchmarks
  • stopped - Agent should stop and shutdown
  • error - Agent has been marked as errored

POST /agents/{id}/submit_benchmark#

Submit hashcat benchmark results.

Request Body:

{
  "hashcat_benchmarks": [
    {
      "hash_type": 0,
      "runtime": 5000,
      "hash_speed": 15000000000.0,
      "device": 1
    },
    {
      "hash_type": 1000,
      "runtime": 5000,
      "hash_speed": 8500000000.0,
      "device": 1
    }
  ]
}

Response (200 OK): Benchmarks processed. Returns a BenchmarkReceipt object:

{
  "received_count": 2,
  "processed_count": 2,
  "failed_count": 0,
  "message": "Successfully processed 2 of 2 benchmarks"
}

BenchmarkReceipt Fields:

FieldTypeRequiredDescription
received_countintegerYesNumber of benchmark entries received in the request
processed_countintegerYesNumber of benchmark entries successfully stored
failed_countintegerYesNumber of benchmark entries rejected due to validation failures
messagestringNoHuman-readable summary of the submission result

Note

Invalid individual entries are skipped and reflected in failed_count. The endpoint returns 200 OK with a BenchmarkReceipt when processing succeeds; 422 is returned when submission fails validation/processing for the current agent state. Clients should rely on both HTTP status and receipt counts (processed_count/failed_count) to handle partial or zero-processed batches safely.

Important

During rolling deployments across mixed server versions, clients SHOULD accept either:

  • 200 OK with BenchmarkReceipt JSON body (current contract), or
  • 204 No Content with no body (legacy behavior from older servers).

Response (400 Bad Request):

{
  "error": "Invalid benchmark data"
}

POST /agents/{id}/submit_error#

Report an error to the server.

Request Body:

{
  "message": "GPU temperature exceeded threshold",
  "severity": "major",
  "agent_id": 42,
  "task_id": 123,
  "metadata": {
    "error_date": "2025-01-15T10:30:00Z",
    "other": {
      "gpu_temp": 95,
      "gpu_id": 1
    }
  }
}

Severity Levels:

LevelDescriptionAction
infoInformational messageNone
warningNon-critical, anticipatedNone
minorShould investigateTask continues
majorRequires attentionCheck task
criticalImmediate action neededStop task
fatalAgent cannot continueDo not retry

Response (204 No Content): Error logged.


POST /agents/{id}/shutdown#

Mark agent as offline and release any assigned tasks.

Response (204 No Content): Agent marked as shutdown.


Task Management#

GET /tasks/new#

Request a new task assignment.

Response (200 OK): Task available:

{
  "id": 123,
  "attack_id": 456,
  "start_date": "2025-01-15T10:00:00Z",
  "status": "pending",
  "skip": 0,
  "limit": 10000000
}

Response (204 No Content): No tasks available.


GET /tasks/{id}#

Get task details.

Response (200 OK):

{
  "id": 123,
  "attack_id": 456,
  "start_date": "2025-01-15T10:00:00Z",
  "status": "running",
  "skip": 0,
  "limit": 10000000
}

Task Status Values:

StatusDescription
pendingTask created, not yet accepted
runningAgent is working on task
completedAll hashes cracked
exhaustedKeyspace exhausted, task finished
failedTask failed with errors
pausedTask paused by server

POST /tasks/{id}/accept_task#

Accept an offered task and start working.

Response (204 No Content): Task accepted.

Response (404 Not Found):

{
  "error": "Task not found for agent"
}

Response (422 Unprocessable Entity):

{
  "error": "Task already completed"
}

POST /tasks/{id}/submit_status#

Submit task progress update (call regularly during cracking).

Request Body:

{
  "original_line": "STATUS\t5\tcracking\t...",
  "time": "2025-01-15T10:15:00Z",
  "session": "task_123",
  "status": 5,
  "target": "hashlist.txt",
  "progress": [
    5000000,
    10000000
  ],
  "restore_point": 5000000,
  "recovered_hashes": [
    42,
    100
  ],
  "recovered_salts": [
    1,
    1
  ],
  "rejected": 0,
  "time_start": "2025-01-15T10:00:00Z",
  "estimated_stop": "2025-01-15T10:30:00Z",
  "hashcat_guess": {
    "guess_base": "rockyou.txt",
    "guess_base_count": 14344391,
    "guess_base_offset": 7000000,
    "guess_base_percentage": 48.8,
    "guess_mod": "",
    "guess_mod_count": 0,
    "guess_mod_offset": 0,
    "guess_mod_percentage": 0.0,
    "guess_mode": 0
  },
  "device_statuses": [
    {
      "device_id": 1,
      "device_name": "NVIDIA RTX 4090",
      "device_type": "GPU",
      "speed": 15000000000,
      "utilization": 98,
      "temperature": 72
    }
  ]
}

Response (204 No Content): Status received.

Response (202 Accepted): Status received but data is stale (submit more frequently).

Response (410 Gone): Task has been paused - stop work and wait.

Response (422 Unprocessable Entity):

{
  "error": "Malformed status data"
}

POST /tasks/{id}/submit_crack#

Submit a cracked hash.

Request Body:

{
  "timestamp": "2025-01-15T10:20:00Z",
  "hash": "5f4dcc3b5aa765d61d8327deb882cf99",
  "plain_text": "password"
}

Response (200 OK): Crack accepted, more hashes remain.

Response (204 No Content): Crack accepted, all hashes in list are now cracked.

Response (404 Not Found):

{
  "error": "Hash value not found in list"
}

POST /tasks/{id}/exhausted#

Mark task as exhausted (keyspace fully searched).

Response (204 No Content): Task marked as exhausted.


POST /tasks/{id}/abandon#

Abandon a task (agent cannot complete it).

Response (200 OK):

{
  "success": true,
  "state": "pending"
}

Response (422 Unprocessable Entity):

{
  "error": "Task already completed",
  "details": [
    "Cannot abandon completed tasks"
  ]
}

Warning

Abandoning a task may trigger rebalancing of all tasks for that attack.


GET /tasks/{id}/get_zaps#

Get hashes that have been cracked by other agents (for runtime removal).

Response (200 OK): Returns plain text list of cracked hashes:

5f4dcc3b5aa765d61d8327deb882cf99
e99a18c428cb38d5f260853678922e03

Add these to hashcat's --potfile-path or remove from working hash list.


Attack Information#

GET /attacks/{id}#

Get attack details and hashcat parameters.

Response (200 OK):

{
  "id": 456,
  "attack_mode": "dictionary",
  "attack_mode_hashcat": 0,
  "mask": null,
  "increment_mode": false,
  "increment_minimum": 0,
  "increment_maximum": 0,
  "optimized": true,
  "slow_candidate_generators": false,
  "workload_profile": 3,
  "disable_markov": false,
  "classic_markov": false,
  "markov_threshold": 0,
  "left_rule": null,
  "right_rule": null,
  "custom_charset_1": null,
  "custom_charset_2": null,
  "custom_charset_3": null,
  "custom_charset_4": null,
  "hash_list_id": 789,
  "hash_mode": 1000,
  "hash_list_url": "https://cipherswarm.com/rails/active_storage/blobs/...",
  "hash_list_checksum": "d41d8cd98f00b204e9800998ecf8427e",
  "url": "/api/v1/client/attacks/456",
  "word_list": {
    "id": 1,
    "download_url": "https://cipherswarm.com/rails/active_storage/blobs/...",
    "checksum": "abc123...",
    "file_name": "rockyou.txt"
  },
  "rule_list": null,
  "mask_list": null
}

Attack Modes:

ModeNameHashcat Mode
dictionaryDictionary attack0
maskMask/brute-force attack3
hybrid_dictionaryDictionary + Mask6
hybrid_maskMask + Dictionary7

GET /attacks/{id}/hash_list#

Download the hash list file for an attack.

Response (200 OK): Returns plain text hash list:

5f4dcc3b5aa765d61d8327deb882cf99
e99a18c428cb38d5f260853678922e03
098f6bcd4621d373cade4e832627b4f6

Error Handling#

Standard Error Response#

All errors return JSON with an error field:

{
  "error": "Description of the error"
}

HTTP Status Codes#

CodeMeaning
200Success with response body
202Accepted but stale data
204Success with no content
400Bad request (invalid parameters)
401Unauthorized (invalid token)
404Resource not found
410Resource gone (task paused)
422Unprocessable entity (validation error)
500Internal server error

Rate Limiting#

The API does not currently enforce rate limits, but agents should:

  • Send heartbeats every 60 seconds (configurable via agent_update_interval)
  • Submit status updates every 5-10 seconds during active cracking
  • Submit cracks immediately as they are found

Code Examples#

Python Example#

import requests

class CipherSwarmClient:
    def __init__(self, base_url, token):
        self.base_url = base_url
        self.session = requests.Session()
        self.session.headers["Authorization"] = f"Bearer {token}"
        self.session.headers["Content-Type"] = "application/json"

    def authenticate(self):
        resp = self.session.get(f"{self.base_url}/authenticate")
        resp.raise_for_status()
        return resp.json()

    def get_new_task(self):
        resp = self.session.get(f"{self.base_url}/tasks/new")
        if resp.status_code == 204:
            return None
        resp.raise_for_status()
        return resp.json()

    def accept_task(self, task_id):
        resp = self.session.post(f"{self.base_url}/tasks/{task_id}/accept_task")
        resp.raise_for_status()

    def submit_crack(self, task_id, hash_value, plain_text):
        resp = self.session.post(
            f"{self.base_url}/tasks/{task_id}/submit_crack",
            json={
                "timestamp": datetime.utcnow().isoformat() + "Z",
                "hash": hash_value,
                "plain_text": plain_text,
            },
        )
        resp.raise_for_status()
        return resp.status_code == 200 # True if more hashes remain

# Usage
client = CipherSwarmClient("https://cipherswarm.com/api/v1/client", "YOUR_TOKEN")
auth = client.authenticate()
print(f"Authenticated as agent {auth['agent_id']}")

cURL Example#

# Authenticate
curl -H "Authorization: Bearer YOUR_TOKEN" \
  https://cipherswarm.com/api/v1/client/authenticate

# Get new task
curl -H "Authorization: Bearer YOUR_TOKEN" \
  https://cipherswarm.com/api/v1/client/tasks/new

# Accept task
curl -X POST \
  -H "Authorization: Bearer YOUR_TOKEN" \
  https://cipherswarm.com/api/v1/client/tasks/123/accept_task

# Submit crack
curl -X POST \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"timestamp":"2025-01-15T10:20:00Z","hash":"5f4dcc3b...","plain_text":"password"}' \
  https://cipherswarm.com/api/v1/client/tasks/123/submit_crack

Changelog#

Version 1.3 (Current)#

  • Added current_activity field to Agent
  • Added activity parameter to heartbeat endpoint
  • Improved error responses with structured JSON

Version 1.2#

  • Added get_zaps endpoint for runtime hash removal
  • Added task preemption support (410 response on submit_status)

Version 1.1#

  • Added advanced_configuration to Agent
  • Added benchmark submission endpoint

Version 1.0#

  • Initial release