Private API/MCP Documentation

OnlineHashCrack Private API

Use the private API to submit authorized hash recovery tasks and retrieve your current task list. Requests and responses are JSON, API keys always use the sk_ prefix, and each response includes a server-generated request_id for support and troubleshooting.

JSON over HTTPS Maximum 50 hashes per request Per-key hourly limits Authorized use only
Base endpoint https://api.onlinehashcrack.com/v2
Authentication Send api_key in the JSON body.
Content type Use Content-Type: application/json.

Endpoints

POST https://api.onlinehashcrack.com/v2
Add tasks or list existing tasks.
GET https://api.onlinehashcrack.com/v2?schema=1
Return the JSON Schema for the request body. No API key required.
GET https://api.onlinehashcrack.com/v2?openapi=1
Return the OpenAPI 3.0.3 schema. No API key required.
Terms and authorized use. Set agree_terms to yes only when you have read and accepted the Terms & Conditions and you are submitting hashes you are authorized to test.

Request Body

All API actions use a JSON object. If action is omitted, the API defaults to add_tasks.

Field Type Required Description
api_key String Required Your private API key. Format: sk_ followed by 32 to 64 alphanumeric characters. Generate or manage it from API management.
agree_terms String Required Must be exactly yes. Any other value returns terms_not_accepted.
action String Optional Allowed values: add_tasks or list_tasks. Defaults to add_tasks.
algo_mode Integer Required for add_tasks Non-negative Hashcat algorithm mode. See the accepted hash list. Example: 0 for MD5.
hashes Array<string> Required for add_tasks One to 50 hash strings. Each value is trimmed, HTML tags are stripped, values are capped at 512 characters, and duplicates in the same request are ignored.

Examples

# Add hash recovery tasks
curl -sS -X POST "https://api.onlinehashcrack.com/v2" \
	-H "Content-Type: application/json" \
	-d '{
		"api_key": "sk_REPLACE_WITH_YOUR_KEY",
		"agree_terms": "yes",
		"action": "add_tasks",
		"algo_mode": 0,
		"hashes": [
			"8124BC0A5335C27F086F24BA2C7A4810"
		]
	}'

# List current tasks
curl -sS -X POST "https://api.onlinehashcrack.com/v2" \
	-H "Content-Type: application/json" \
	-d '{
		"api_key": "sk_REPLACE_WITH_YOUR_KEY",
		"agree_terms": "yes",
		"action": "list_tasks"
	}'

# Inspect the request schema
curl -sS "https://api.onlinehashcrack.com/v2?schema=1"

# Inspect the OpenAPI 3.0 schema
curl -sS "https://api.onlinehashcrack.com/v2?openapi=1"
import requests

url = "https://api.onlinehashcrack.com/v2"
payload = {
	"api_key": "sk_REPLACE_WITH_YOUR_KEY",
	"agree_terms": "yes",
	"action": "add_tasks",
	"algo_mode": 0,
	"hashes": ["8124BC0A5335C27F086F24BA2C7A4810"],
}

response = requests.post(url, json=payload, timeout=30)
data = response.json()

if response.status_code == 429:
	print("Retry after", response.headers.get("Retry-After"), "seconds")
elif not response.ok:
	print(data.get("error_code"), data.get("message"), data.get("request_id"))
else:
	print(data)
const response = await fetch('https://api.onlinehashcrack.com/v2', {
	method: 'POST',
	headers: { 'Content-Type': 'application/json' },
	body: JSON.stringify({
		api_key: 'sk_REPLACE_WITH_YOUR_KEY',
		agree_terms: 'yes',
		action: 'add_tasks',
		algo_mode: 0,
		hashes: ['8124BC0A5335C27F086F24BA2C7A4810'],
	}),
});

const data = await response.json();

if (response.status === 429) {
	console.log('Retry after', response.headers.get('Retry-After'), 'seconds');
} else if (!response.ok) {
	console.error(data.error_code, data.message, data.request_id);
} else {
	console.log(data);
}
$uri = 'https://api.onlinehashcrack.com/v2'
$payload = @{
	api_key = 'sk_REPLACE_WITH_YOUR_KEY'
	agree_terms = 'yes'
	action = 'add_tasks'
	algo_mode = 0
	hashes = @('8124BC0A5335C27F086F24BA2C7A4810')
} | ConvertTo-Json -Depth 4

try {
	$response = Invoke-RestMethod `
		-Uri $uri `
		-Method Post `
		-ContentType 'application/json' `
		-Body $payload `
		-TimeoutSec 30

	$response
} catch {
	$statusCode = $_.Exception.Response.StatusCode.value__
	$retryAfter = $_.Exception.Response.Headers['Retry-After']
	Write-Error "OHC API error HTTP $statusCode. Retry-After: $retryAfter"
}
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"time"
)

func main() {
	payload := map[string]any{
		"api_key": "sk_REPLACE_WITH_YOUR_KEY",
		"agree_terms": "yes",
		"action": "add_tasks",
		"algo_mode": 0,
		"hashes": []string{"8124BC0A5335C27F086F24BA2C7A4810"},
	}

	body, err := json.Marshal(payload)
	if err != nil {
		panic(err)
	}

	client := &http.Client{Timeout: 30 * time.Second}
	req, err := http.NewRequest(http.MethodPost, "https://api.onlinehashcrack.com/v2", bytes.NewReader(body))
	if err != nil {
		panic(err)
	}
	req.Header.Set("Content-Type", "application/json")

	resp, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	responseBody, err := io.ReadAll(resp.Body)
	if err != nil {
		panic(err)
	}

	if resp.StatusCode == http.StatusTooManyRequests {
		fmt.Println("Retry after", resp.Header.Get("Retry-After"), "seconds")
	}
	if resp.StatusCode >= 400 {
		fmt.Println("API error:", resp.Status, string(responseBody))
		return
	}

	fmt.Println(string(responseBody))
}
$url = 'https://api.onlinehashcrack.com/v2';
$payload = [
	'api_key' => 'sk_REPLACE_WITH_YOUR_KEY',
	'agree_terms' => 'yes',
	'action' => 'add_tasks',
	'algo_mode' => 0,
	'hashes' => ['8124BC0A5335C27F086F24BA2C7A4810'],
];

$ch = curl_init($url);
curl_setopt_array($ch, [
	CURLOPT_POST => true,
	CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
	CURLOPT_POSTFIELDS => json_encode($payload, JSON_THROW_ON_ERROR),
	CURLOPT_RETURNTRANSFER => true,
	CURLOPT_TIMEOUT => 30,
]);

$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
$error = curl_error($ch);
curl_close($ch);

if ($body === false) {
	throw new RuntimeException('API request failed: ' . $error);
}

$data = json_decode($body, true, 512, JSON_THROW_ON_ERROR);
if ($status >= 400) {
	error_log('OHC API error ' . ($data['error_code'] ?? 'unknown') . ' request_id=' . ($data['request_id'] ?? 'none'));
}

print_r($data);

Successful Responses

add_tasks response

The response groups submitted hashes into accepted, skipped, and rejected. Hashes are masked for safe correlation in local logs.

{
	"accepted": {
		"count": 1,
		"hashes": [
			"8124...4810"
		]
	},
	"skipped": {
		"count": 1,
		"reason": "already_sent",
		"hashes": [
			"5F4D...27E0"
		]
	},
	"rejected": {
		"count": 1,
		"hashes": [
			"BAD...HASH"
		],
		"reason": "invalid_format"
	},
	"success": true,
	"request_id": "9f8a7b6c5d4e3f21"
}

list_tasks response

{
	"success": true,
	"tasks": [
		{
			"created_at": "2026-05-12 14:25:00",
			"hash": "8124BC0A5335C27F086F24BA2C7A4810",
			"algomode": "0",
			"algorithm": "MD5",
			"usernote": "",
			"status": "In queue",
			"lastAttack": ""
		}
	],
	"request_id": "9f8a7b6c5d4e3f21"
}

Error Responses

Request-level errors return a non-2xx HTTP status, success: false, a machine-readable error_code, a human-readable message, and a request_id.

{
	"success": false,
	"error_code": "invalid_api_key",
	"message": "Invalid API key.",
	"request_id": "9f8a7b6c5d4e3f21"
}
Status Error code When it happens
400 empty_body The request body is empty.
400 malformed_json The body is not a valid JSON object.
400 missing_field api_key or agree_terms is missing. The response includes a missing array.
400 terms_not_accepted agree_terms is not exactly yes.
400 invalid_action action is not add_tasks or list_tasks.
400 invalid_algo_mode algo_mode is missing, negative, or not an integer for add_tasks.
400 invalid_hashes hashes is missing, not an array, empty, above 50 items, or contains non-string values.
401 invalid_api_key The API key format is invalid, the key is unknown, the account is not verified, or API access is unavailable for the account.
405 method_not_allowed The request method is not POST. The response includes Allow: POST.
413 body_too_large The JSON body exceeds 1 MB.
429 rate_limit_exceeded The hourly API limit is exhausted. The response includes Retry-After, retry_after, and limit. Upgrade your Tier from your Profile when your automation needs more headroom.
500 internal_error An internal server error occurred. Provide request_id when contacting support.

Hash-level rejection reasons

When the request itself is valid but individual hashes cannot be added, they appear in rejected. The reason field contains the last rejection reason returned for that batch.

  • invalid_format: the hash does not match the selected algo_mode.
  • invalid_algorithm: the selected algorithm is unsupported or invalid.
  • quota_exceeded: the account quota is reached. Upgrade your Tier from your Profile to unlock more capacity for larger or recurring audits.
  • internal_error: an unexpected server-side error occurred while saving a task.

Rate Limits

Rate limits are enforced per API key in a fixed one-hour window. Higher tiers are designed for heavier automation, recurring compliance checks, and larger audit workflows. You can upgrade from your Profile.

Tier Requests per hour Upgrade path
Tier 1 50 Best for light automation and occasional submissions. Need more throughput? Upgrade your Tier.
Tier 2 500 Built for regular scripting, scheduled checks, and team workflows. Manage or upgrade it from your Profile.
Tier 3 2000 Highest self-service API allowance for intensive audit pipelines. Check your Profile or contact us for specific needs.
{
	"success": false,
	"error_code": "rate_limit_exceeded",
	"message": "Hourly rate limit of 500 requests exceeded. Retry after 532 seconds, or upgrade your Tier (see Profile).",
	"request_id": "9f8a7b6c5d4e3f21",
	"retry_after": 532,
	"limit": 500
}

Implementation Best Practices

  • Keep API keys server-side. Do not expose sk_ keys in browser JavaScript, mobile apps, public repositories, screenshots, or client logs.
  • Store request_id with failed calls. It is the safest value to share with support.
  • Respect Retry-After on 429 responses and use backoff instead of retry loops.
  • Submit up to 50 hashes per request instead of one request per hash when possible.
  • Use the schema endpoint in tests to validate your request format before sending production traffic.
  • Never submit hashes unless you own the system or have written authorization to test it.

MCP Server

OHC exposes a Model Context Protocol server over Streamable HTTP (spec 2025-03-26). It lets any MCP-compatible AI agent — Claude, ChatGPT, Cursor, and others — call your account directly using natural language. The same sk_ key authenticates both the REST API and the MCP server.

Same key, two interfaces. Your API key is embedded in the MCP URL — no extra header or credential needed. Rotating your key requires updating both endpoints.
MCP https://mcp.onlinehashcrack.com/sk_YOUR_API_KEY
Streamable HTTP · MCP spec 2025-03-26

Available tools

Tool Type Description
ohc_submit_hashes Write Submit 1–50 hashes for GPU-accelerated cracking. Parameters: algo_mode (Hashcat integer mode), hashes (array of strings), user_confirmed: true. The LLM prompts you for explicit consent before calling this tool.
ohc_list_tasks Read-only Retrieve all tasks for the account with status, algorithm, last attack, and a structured analysis with prioritized recommendations.

Client setup

Three ways to connect Claude to your OHC account — all use the same URL.

Option 1 — Claude Code (recommended for developers)

Register the server once. Claude Code persists it across sessions.

claude mcp add onlinehashcrack \
    --transport http \
    "https://mcp.onlinehashcrack.com/sk_YOUR_API_KEY"

Confirm the server is registered:

claude mcp list

Then just open a session and ask:

claude
# → "List my OHC tasks" or "Submit this hash ..."

Option 2 — Claude Desktop

Open claude_desktop_config.json and add the entry under mcpServers. Create the file if it does not exist.

OSPath
macOS~/Library/Application Support/Claude/claude_desktop_config.json
Windows%APPDATA%\Claude\claude_desktop_config.json
{
    "mcpServers": {
        "onlinehashcrack": {
            "url": "https://mcp.onlinehashcrack.com/sk_YOUR_API_KEY"
        }
    }
}

Restart Claude Desktop. The OHC tools will appear in the tool picker.

Option 3 — Claude.ai (web)

Go to Settings → Integrations, click Add integration, and paste the MCP URL:

https://mcp.onlinehashcrack.com/sk_YOUR_API_KEY

No restart needed — tools are available immediately in the next conversation.

ChatGPT Desktop and the OpenAI Agents SDK both support MCP remote servers.

Option 1 — ChatGPT Desktop

Open Settings → Connections and add the OHC MCP server by pasting the URL directly into the remote server field:

https://mcp.onlinehashcrack.com/sk_YOUR_API_KEY

Option 2 — OpenAI Agents SDK

Use the OHC MCP server inside an agent workflow. Install with pip install openai-agents.

import asyncio
from agents import Agent, Runner
from agents.mcp import MCPServerStreamableHttp

async def main():
    params = {"url": "https://mcp.onlinehashcrack.com/sk_YOUR_API_KEY"}
    async with MCPServerStreamableHttp(name="OnlineHashCrack", params=params) as ohc:
        agent = Agent(
            name="hash-auditor",
            instructions=(
                "You are a security audit assistant with access to OnlineHashCrack. "
                "Only submit hashes the user confirms they own or are authorized to test."
            ),
            mcp_servers=[ohc],
        )
        result = await Runner.run(agent, "List my cracking tasks and summarize the results.")
        print(result.final_output)

asyncio.run(main())

See the OpenAI Agents SDK docs for streaming, tool filtering, and multi-server setups.

Confirmation gate on ohc_submit_hashes. The tool requires user_confirmed: true, enforced server-side. The LLM will ask for your explicit confirmation before dispatching the call — this gate cannot be bypassed programmatically.