Dry-Run Policy and Resolution Writes

Add ?dry_run=true to a policy, rule, or resolution write to check the request without saving anything. A dry-run returns the same body that a normal write would return. Socket does not create, update, or delete the policy, rule, or resolution, and matching alerts stay on the open list.

This is most useful before you confirm the migration. Until then, a real policy or rule write returns 409. A dry-run of the same request still works. Resolutions can be created for real before and after the cutover; dry-run is optional there.

Which Writes Support dry_run

EndpointOperation
POST /orgs/{org_slug}/alert-policiesCreate a policy
PUT /orgs/{org_slug}/alert-policies/{policy_id}Update a policy
DELETE /orgs/{org_slug}/alert-policies/{policy_id}Delete a policy
POST /orgs/{org_slug}/alert-policies/{policy_id}/rulesCreate a rule
PUT /orgs/{org_slug}/alert-policies/{policy_id}/rules/{rule_id}Update a rule
DELETE /orgs/{org_slug}/alert-policies/{policy_id}/rules/{rule_id}Delete a rule
POST /orgs/{org_slug}/alerts/resolutionsCreate a resolution

Resolution delete has no dry-run. Neither do any GETs, translate, or the legacy security-policy and triage writes.

Auth and token restrictions match a real write: alert-policy:create / :update / :delete for policy and rule endpoints, alert-resolution:create for a resolution. A repository-restricted token still gets 403 on policy writes, and still cannot create an organization-wide or multi-repo resolution. Each call uses 1 unit of quota.

Success Is 200, Not 201

A dry-run create returns HTTP 200 with dry_run: true on the body, not 201. The body still includes the id or uuid a real write would have produced, but that identifier does not exist. GET it and you get 404. A 201 means it was created. A 200 with dry_run: true means nothing was saved.

A dry-run delete returns { "dry_run": true }, not { "result": "success" }.

A dry-run update returns 200 with the updated body and dry_run: true.

Errors are the same as a real write. A duplicate policy name is still 409. An unknown policy or rule is still 404. A malformed body is still 400. Until you confirm the migration, a real policy or rule write still returns 409. A dry-run is the exception: it returns 200 instead.

Query Values

ValueEffect
omitted, false, 0, no, or emptyReal write
true, 1, or yes (any case, surrounding space ignored)Dry-run
anything else (ture, on, maybe)400: dry_run must be true, 1, yes, false, 0, or no
repeated values that disagree (true and false)400: dry_run has conflicting values

Example: Creating a Policy

This works before you confirm the migration. The policy is not created.

curl -u "$SOCKET_API_TOKEN:" -X POST \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Production",
    "description": "Stricter handling for production services",
    "baseline": "balanced"
  }' \
  "https://api.socket.dev/v0/orgs/$ORG/alert-policies?dry_run=true"
{
  "id": "7d9e2f10-4a3b-4c5d-8e6f-1a2b3c4d5e6f",
  "name": "Production",
  "description": "Stricter handling for production services",
  "apply_method": "labeled_repos",
  "repo_label_id": "3c4d5e6f-7a8b-4c9d-0e1f-2a3b4c5d6e7f",
  "repository_ids": [],
  "baseline": "balanced",
  "created_by": "0f8a3c1e-2b4d-4e5f-9a6b-7c8d9e0f1a2b",
  "updated_by": "0f8a3c1e-2b4d-4e5f-9a6b-7c8d9e0f1a2b",
  "created_at": "2026-08-20T14:02:11.000Z",
  "updated_at": "2026-08-20T14:02:11.000Z",
  "dry_run": true
}

GET /orgs/$ORG/alert-policies/7d9e2f10-4a3b-4c5d-8e6f-1a2b3c4d5e6f returns 404. After you confirm the migration, the same POST without dry_run returns 201 and creates the policy.

Example: Creating a Policy Rule from Translate

If translate turned a triage rule into a policy rule, send that body with ?dry_run=true. Use the Default policy, or another policy id if the rule belongs there. Until you confirm the migration, posting the same body without dry_run still returns 409.

curl -u "$SOCKET_API_TOKEN:" -X POST \
  -H "Content-Type: application/json" \
  -d '{
    "name": "in [email protected]",
    "action": "monitor",
    "note": null,
    "vigil_selector": {
      "artifact.type": "npm",
      "artifact.name": "react",
      "artifact.version": "19.2.8"
    }
  }' \
  "https://api.socket.dev/v0/orgs/$ORG/alert-policies/default/rules?dry_run=true"
{
  "id": "1b2c3d4e-5f60-4718-9a2b-3c4d5e6f7a8b",
  "alert_policy_id": "7d9e2f10-4a3b-4c5d-8e6f-1a2b3c4d5e6f",
  "rank": "a0",
  "name": "in [email protected]",
  "vigil_selector": {
    "artifact.type": "npm",
    "artifact.name": "react",
    "artifact.version": "19.2.8"
  },
  "action": "monitor",
  "note": null,
  "created_by": "0f8a3c1e-2b4d-4e5f-9a6b-7c8d9e0f1a2b",
  "updated_by": "0f8a3c1e-2b4d-4e5f-9a6b-7c8d9e0f1a2b",
  "created_at": "2026-08-20T14:03:44.000Z",
  "updated_at": "2026-08-20T14:03:44.000Z",
  "dry_run": true
}

Example: Creating a Resolution

You can create resolutions before you confirm the migration. Dry-run is optional; use it if you want to check the request first without saving it.

curl -u "$SOCKET_API_TOKEN:" -X POST \
  -H "Content-Type: application/json" \
  -d '{
    "reason": "other",
    "comment": "accepted risk",
    "vigil_selector": {
      "finding.alertType": "criticalCVE",
      "artifact.type": "npm",
      "artifact.name": "lodash"
    }
  }' \
  "https://api.socket.dev/v0/orgs/$ORG/alerts/resolutions?dry_run=true"
{
  "uuid": "9e0f1a2b-3c4d-4e5f-8a6b-7c8d9e0f1a2b",
  "reason": "other",
  "reason_text": null,
  "comment": "accepted risk",
  "vigil_selector": {
    "finding.alertType": "criticalCVE",
    "artifact.type": "npm",
    "artifact.name": "lodash"
  },
  "alert_type": "criticalCVE",
  "repo": null,
  "repo_label": null,
  "artifact_type": "npm",
  "artifact_namespace": null,
  "artifact_name": "lodash",
  "artifact_version": null,
  "resolved_by": null,
  "created_at": "2026-08-20T14:04:18.000Z",
  "updated_at": "2026-08-20T14:04:18.000Z",
  "dry_run": true
}

GET /orgs/$ORG/alerts/resolutions/9e0f1a2b-3c4d-4e5f-8a6b-7c8d9e0f1a2b returns 404. Matching alerts stay on the open list. A dry-run does not hide them.

Example: Deleting a Policy

curl -u "$SOCKET_API_TOKEN:" -X DELETE \
  "https://api.socket.dev/v0/orgs/$ORG/alert-policies/$POLICY_ID?dry_run=true"
{ "dry_run": true }

The policy is still there. The same URL without dry_run returns { "result": "success" } and then GET is 404.

Related Pages


Did this page help you?