HackTricks AI API
Programmatic access to HackTricks AI Chat and RAG (Retrieval-Augmented Generation) endpoints.
Overview
The HackTricks AI API provides two main capabilities:
Chat API — Create and continue AI conversations powered by the HackTricks knowledge base. The AI assistant draws on HackTricks content to answer cybersecurity questions.
RAG API — Directly query the HackTricks vector store to retrieve relevant documentation chunks for your own applications or research.
Base URL: https://ai.hacktricks.wiki
Authentication
All API requests require an API key sent via the X-API-Key header.
Getting your API key:
1. Sign in at tools.hacktricks.wiki/account.html or from the ai.hacktricks.wiki sidebar.
2. In the HackTricks API keys section, click Create key.
3. Copy the key immediately — it is only shown once. Keys start with htk_.
You can have up to 2 API keys per account. Use Rotate to replace a key.
Rate Limits
Chat API: Subject to the same weekly input token cap as the web interface (shared across both).
RAG API: 100 requests per week per account. Resets every Monday at 00:00 Europe/Paris.
When limits are exceeded, the API returns 429 Too Many Requests.
Create a Conversation
/api/v1/chatStart a new AI conversation. Returns the assistant's reply and thread ID.
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
message | string | Yes | Your message to the AI assistant. |
model | string | No | Model alias (e.g. deepseek/deepseek-chat-v3-0324). Defaults to server default. |
Response
| Field | Type | Description |
|---|---|---|
thread_id | string | Unique conversation identifier. Use this to continue the conversation. |
reply | string | The assistant's response (Markdown). |
sources | array | Source documents referenced (if any). |
curl -X POST https://ai.hacktricks.wiki/api/v1/chat \
-H "Content-Type: application/json" \
-H "X-API-Key: $HACKTRICKS_API_KEY" \
-d '{"message": "Explain SSRF attacks on AWS metadata"}'
import requests, os resp = requests.post( "https://ai.hacktricks.wiki/api/v1/chat", headers={"X-API-Key": os.environ["HACKTRICKS_API_KEY"]}, json={"message": "Explain SSRF attacks on AWS metadata"}, ) data = resp.json() print(data["thread_id"]) # save for follow-ups print(data["reply"])
const res = await fetch("https://ai.hacktricks.wiki/api/v1/chat", { method: "POST", headers: { "Content-Type": "application/json", "X-API-Key": process.env.HACKTRICKS_API_KEY, }, body: JSON.stringify({ message: "Explain SSRF attacks on AWS metadata" }), }); const data = await res.json(); console.log(data.thread_id); // save for follow-ups console.log(data.reply);
package main import ( "bytes" "encoding/json" "fmt" "net/http" "os" ) func main() { body, _ := json.Marshal(map[string]string{ "message": "Explain SSRF attacks on AWS metadata", }) req, _ := http.NewRequest("POST", "https://ai.hacktricks.wiki/api/v1/chat", bytes.NewReader(body)) req.Header.Set("Content-Type", "application/json") req.Header.Set("X-API-Key", os.Getenv("HACKTRICKS_API_KEY")) resp, _ := http.DefaultClient.Do(req) defer resp.Body.Close() var data map[string]interface{} json.NewDecoder(resp.Body).Decode(&data) fmt.Println(data["thread_id"]) fmt.Println(data["reply"]) }
Continue a Conversation
/api/v1/chat/:threadIdSend a follow-up message in an existing conversation thread.
URL Parameters
| Parameter | Description |
|---|---|
threadId | The thread_id returned from creating a conversation. |
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
message | string | Yes | Your follow-up message. |
model | string | No | Model alias to use. |
Response
Same format as Create Conversation.
curl -X POST https://ai.hacktricks.wiki/api/v1/chat/thread_abc123 \
-H "Content-Type: application/json" \
-H "X-API-Key: $HACKTRICKS_API_KEY" \
-d '{"message": "How can I detect this in CloudTrail?"}'
resp = requests.post(
f"https://ai.hacktricks.wiki/api/v1/chat/{thread_id}",
headers={"X-API-Key": os.environ["HACKTRICKS_API_KEY"]},
json={"message": "How can I detect this in CloudTrail?"},
)
print(resp.json()["reply"])
const res = await fetch(`https://ai.hacktricks.wiki/api/v1/chat/${threadId}`, { method: "POST", headers: { "Content-Type": "application/json", "X-API-Key": process.env.HACKTRICKS_API_KEY, }, body: JSON.stringify({ message: "How can I detect this in CloudTrail?" }), }); console.log((await res.json()).reply);
Get Conversation Messages
/api/v1/chat/:threadIdRetrieve all messages from an existing conversation.
Response
| Field | Type | Description |
|---|---|---|
thread_id | string | The conversation thread ID. |
messages | array | Array of message objects with role and content. |
curl https://ai.hacktricks.wiki/api/v1/chat/thread_abc123 \ -H "X-API-Key: $HACKTRICKS_API_KEY"
resp = requests.get(
f"https://ai.hacktricks.wiki/api/v1/chat/{thread_id}",
headers={"X-API-Key": os.environ["HACKTRICKS_API_KEY"]},
)
for msg in resp.json()["messages"]:
print(f"{msg['role']}: {msg['content'][:100]}")
RAG Search
/api/v1/ragSearch the HackTricks vector store for relevant documentation chunks.
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
query | string | Yes | Your search query. |
max_results | integer | No | Number of chunks to return (1–5, default 3). |
rewrite_query | boolean | No | Let the server optimize your query for vector search (default false). |
Response
| Field | Type | Description |
|---|---|---|
results | array | Array of matched chunks. Each has content, score, and filename. |
query | string | The (possibly rewritten) query used for search. |
usage | object | Current week's used and limit counts. |
curl -X POST https://ai.hacktricks.wiki/api/v1/rag \
-H "Content-Type: application/json" \
-H "X-API-Key: $HACKTRICKS_API_KEY" \
-d '{"query": "AWS IAM privilege escalation", "max_results": 5}'
import requests, os resp = requests.post( "https://ai.hacktricks.wiki/api/v1/rag", headers={"X-API-Key": os.environ["HACKTRICKS_API_KEY"]}, json={ "query": "AWS IAM privilege escalation", "max_results": 5, }, ) data = resp.json() for chunk in data["results"]: print(f"[{chunk['score']:.3f}] {chunk['filename']}") print(chunk["content"][:200]) print()
const res = await fetch("https://ai.hacktricks.wiki/api/v1/rag", { method: "POST", headers: { "Content-Type": "application/json", "X-API-Key": process.env.HACKTRICKS_API_KEY, }, body: JSON.stringify({ query: "AWS IAM privilege escalation", max_results: 5 }), }); const { results } = await res.json(); results.forEach(c => console.log(c.filename, c.score));
package main import ( "bytes" "encoding/json" "fmt" "net/http" "os" ) func main() { body, _ := json.Marshal(map[string]interface{}{ "query": "AWS IAM privilege escalation", "max_results": 5, }) req, _ := http.NewRequest("POST", "https://ai.hacktricks.wiki/api/v1/rag", bytes.NewReader(body)) req.Header.Set("Content-Type", "application/json") req.Header.Set("X-API-Key", os.Getenv("HACKTRICKS_API_KEY")) resp, _ := http.DefaultClient.Do(req) defer resp.Body.Close() var data struct { Results []struct { Content string `json:"content"` Score float64 `json:"score"` Filename string `json:"filename"` } `json:"results"` } json.NewDecoder(resp.Body).Decode(&data) for _, r := range data.Results { fmt.Printf("[%.3f] %s\n", r.Score, r.Filename) } }
Check RAG Usage
/api/v1/rag/usageCheck your current weekly RAG request count and remaining quota.
Response
| Field | Type | Description |
|---|---|---|
used | integer | Requests made this week. |
limit | integer | Weekly limit (100). |
remaining | integer | Requests remaining this week. |
curl https://ai.hacktricks.wiki/api/v1/rag/usage \ -H "X-API-Key: $HACKTRICKS_API_KEY"
resp = requests.get(
"https://ai.hacktricks.wiki/api/v1/rag/usage",
headers={"X-API-Key": os.environ["HACKTRICKS_API_KEY"]},
)
usage = resp.json()
print(f"Used {usage['used']}/{usage['limit']} this week")
Error Handling
The API returns standard HTTP status codes with a JSON body containing a message field:
| Status | Meaning |
|---|---|
200 | Success. |
400 | Bad request — missing or invalid parameters. |
401 | Unauthorized — missing or invalid API key. |
403 | Forbidden — the thread belongs to another user. |
404 | Not found — thread does not exist. |
429 | Rate limited — weekly quota exceeded. |
500 | Internal server error. |
Example error response
{
"message": "Weekly RAG limit exceeded (100/100)"
}
© HackTricks · hacktricks.wiki · Training