> ## Documentation Index
> Fetch the complete documentation index at: https://docs.detail.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Rules API: create and manage Detail custom analysis rules

> Create and manage custom Detail analysis rules via the API. Rule creation is asynchronous — poll the request status endpoint to track progress.

Detail rules are custom analysis patterns that teach Detail to find specific problems in your codebase. You can create rules by describing what you want to catch, by referencing existing bug IDs, or by pointing Detail at specific commit SHAs. Rule creation is asynchronous: you submit a request and receive a request ID, then poll for completion to retrieve the generated rule.

***

## POST /public/v1/rules

Starts an asynchronous rule creation job. Detail analyses the input you provide — a description, existing bugs, or commits — and generates the rule files. Returns a `ruleCreationRequestId` you can use to poll for job status.

```bash theme={null}
curl -X POST https://api.detail.dev/public/v1/rules \
  -H "Authorization: Bearer dtl_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "repo_id": "repo_abc123",
    "input": {
      "description": "Flag raw SQL queries that interpolate user input without parameterization",
      "bugIds": ["bug_abc123", "bug_def456"],
      "commitShas": []
    }
  }'
```

### Request body

<ParamField body="repo_id" type="string" required>
  The repository ID the rule should be associated with. Must match the pattern `repo_*`.
</ParamField>

<ParamField body="input" type="object" required>
  The inputs Detail uses to generate the rule. All sub-fields are optional — if you omit all of them, Detail automatically proposes rules based on the repository's existing bug history.

  <Expandable title="input fields">
    <ParamField body="description" type="string">
      A plain-language description of the pattern you want the rule to detect. Be specific: mention the language, library, or anti-pattern you have in mind.
    </ParamField>

    <ParamField body="bugIds" type="string[]">
      Array of existing bug IDs (prefixed with `bug_`) to use as examples. Detail uses the code patterns in these bugs to infer a generalized rule.
    </ParamField>

    <ParamField body="commitShas" type="string[]">
      Array of commit SHAs to use as examples. Detail analyses the diffs in these commits to identify patterns worth codifying as rules.
    </ParamField>
  </Expandable>
</ParamField>

### Response

<ResponseField name="ruleCreationRequestId" type="string">
  The ID of the new rule creation request, prefixed with `rcr_`. Use this to poll [GET /public/v1/rules/requests/\{rcr\_id}](#get-publicv1rulesrequestsrcr_id) for job status.
</ResponseField>

### Example response

```json theme={null}
{
  "ruleCreationRequestId": "rcr_abc123"
}
```

***

## GET /public/v1/rules

Returns all completed rules for a repository, ordered newest first. This endpoint only returns rules that have been successfully generated — use [GET /public/v1/rules/requests](#get-publicv1rulesrequests) to see rules that are still in progress.

```bash theme={null}
curl "https://api.detail.dev/public/v1/rules?repo_id=repo_abc123" \
  -H "Authorization: Bearer dtl_live_YOUR_KEY"
```

### Query parameters

<ParamField query="repo_id" type="string" required>
  The repository ID to list rules for. Must match the pattern `repo_*`.
</ParamField>

### Response

<ResponseField name="rules" type="RuleListItem[]">
  Array of rule summary objects.

  <Expandable title="RuleListItem fields">
    <ResponseField name="id" type="string">
      Unique rule identifier, prefixed with `rule_`.
    </ResponseField>

    <ResponseField name="ruleName" type="string">
      Human-readable name Detail assigned to the rule.
    </ResponseField>

    <ResponseField name="createdAt" type="integer">
      Unix timestamp (milliseconds) when the rule was created.
    </ResponseField>
  </Expandable>
</ResponseField>

### Example response

```json theme={null}
{
  "rules": [
    {
      "id": "rule_abc123",
      "ruleName": "no-raw-sql-interpolation",
      "createdAt": 1736899200000
    },
    {
      "id": "rule_def456",
      "ruleName": "require-error-boundary",
      "createdAt": 1736812800000
    }
  ]
}
```

***

## GET /public/v1/rules/\{rule\_id}

Returns full details for a completed rule, including the generated rule files. Use this after polling the request status endpoint and confirming that the job has a `complete` status.

```bash theme={null}
curl "https://api.detail.dev/public/v1/rules/rule_abc123" \
  -H "Authorization: Bearer dtl_live_YOUR_KEY"
```

### Path parameters

<ParamField path="rule_id" type="string" required>
  The rule ID to retrieve. Must match the pattern `rule_*`.
</ParamField>

### Response

<ResponseField name="id" type="string">
  Unique rule identifier, prefixed with `rule_`.
</ResponseField>

<ResponseField name="ruleName" type="string">
  Human-readable name Detail assigned to the rule.
</ResponseField>

<ResponseField name="ruleFiles" type="object">
  A map of filename to file content strings. Each key is a file path and each value is the text content of that rule file.
</ResponseField>

<ResponseField name="createdAt" type="integer">
  Unix timestamp (milliseconds) when the rule was created.
</ResponseField>

### Example response

```json theme={null}
{
  "id": "rule_abc123",
  "ruleName": "no-raw-sql-interpolation",
  "ruleFiles": {
    "no-raw-sql-interpolation.yaml": "id: no-raw-sql-interpolation\nlanguage: typescript\n...",
    "no-raw-sql-interpolation.test.ts": "// Rule test cases\n..."
  },
  "createdAt": 1736899200000
}
```

***

## GET /public/v1/rules/requests

Returns all rule creation requests for a repository, ordered newest first. Each entry includes the original input, current status, and — once complete — a summary of the rules that were generated.

```bash theme={null}
curl "https://api.detail.dev/public/v1/rules/requests?repo_id=repo_abc123" \
  -H "Authorization: Bearer dtl_live_YOUR_KEY"
```

### Query parameters

<ParamField query="repo_id" type="string" required>
  The repository ID to list rule creation requests for. Must match the pattern `repo_*`.
</ParamField>

### Response

<ResponseField name="requests" type="RuleRequestStatus[]">
  Array of rule creation request objects. See [GET /public/v1/rules/requests/\{rcr\_id}](#get-publicv1rulesrequestsrcr_id) for the full field reference.
</ResponseField>

***

## GET /public/v1/rules/requests/\{rcr\_id}

Returns the current status and provenance of a rule creation job. Poll this endpoint after calling [POST /public/v1/rules](#post-publicv1rules) until `status` is `complete` or `failed`.

```bash theme={null}
curl "https://api.detail.dev/public/v1/rules/requests/rcr_abc123" \
  -H "Authorization: Bearer dtl_live_YOUR_KEY"
```

### Path parameters

<ParamField path="rcr_id" type="string" required>
  The rule creation request ID to look up. Must match the pattern `rcr_*`.
</ParamField>

### Response

<ResponseField name="id" type="string">
  The rule creation request ID, prefixed with `rcr_`.
</ResponseField>

<ResponseField name="status" type="string">
  Current status of the job. One of:

  * `pending` — the job is queued and has not started
  * `complete` — the job finished and rules are available
  * `failed` — the job encountered an error
</ResponseField>

<ResponseField name="input" type="object">
  The `CreateRuleInput` submitted when the job was created — the `description`, `bugIds`, and `commitShas` you originally passed.
</ResponseField>

<ResponseField name="results" type="RuleRequestResult[]">
  Rules generated by this job. Empty until `status` is `complete`.

  <Expandable title="RuleRequestResult fields">
    <ResponseField name="id" type="string">
      The generated rule ID, prefixed with `rule_`. Use this with [GET /public/v1/rules/\{rule\_id}](#get-publicv1rulesrule_id) to fetch the full rule content.
    </ResponseField>

    <ResponseField name="ruleName" type="string">
      Human-readable name Detail assigned to the rule.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="createdAt" type="integer">
  Unix timestamp (milliseconds) when the request was created.
</ResponseField>

<ResponseField name="completedAt" type="integer">
  Unix timestamp (milliseconds) when the job completed. Only present once the job has finished.
</ResponseField>

### Example response

```json theme={null}
{
  "id": "rcr_abc123",
  "status": "complete",
  "input": {
    "description": "Flag raw SQL queries that interpolate user input without parameterization",
    "bugIds": ["bug_abc123"],
    "commitShas": []
  },
  "results": [
    {
      "id": "rule_abc123",
      "ruleName": "no-raw-sql-interpolation"
    }
  ],
  "createdAt": 1736899200000,
  "completedAt": 1736899560000
}
```

### Full polling example

```bash theme={null}
# Step 1: Create the rule and capture the request ID
RCR_ID=$(curl -s -X POST https://api.detail.dev/public/v1/rules \
  -H "Authorization: Bearer dtl_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "repo_id": "repo_abc123",
    "input": {
      "description": "Flag SQL injection patterns in database query helpers"
    }
  }' | jq -r '.ruleCreationRequestId')

echo "Request ID: $RCR_ID"

# Step 2: Poll until complete
while true; do
  STATUS=$(curl -s "https://api.detail.dev/public/v1/rules/requests/$RCR_ID" \
    -H "Authorization: Bearer dtl_live_YOUR_KEY" | jq -r '.status')

  echo "Status: $STATUS"

  if [ "$STATUS" = "complete" ] || [ "$STATUS" = "failed" ]; then
    break
  fi

  sleep 5
done

# Step 3: Fetch the generated rule files
RULE_ID=$(curl -s "https://api.detail.dev/public/v1/rules/requests/$RCR_ID" \
  -H "Authorization: Bearer dtl_live_YOUR_KEY" | jq -r '.results[0].id')

curl "https://api.detail.dev/public/v1/rules/$RULE_ID" \
  -H "Authorization: Bearer dtl_live_YOUR_KEY"
```

<Note>
  Rule generation typically completes within 30–60 seconds. We recommend polling every 5–10 seconds with a maximum of 20 attempts before surfacing an error to your users.
</Note>
