---
title: Admin REST API
---

The admin screen reads and writes everything through routes under `consepo-csp-scanner/v1/admin/`. They exist for that screen; they are hidden from the REST index and are not a public API.

## Authentication and caching

- Every route requires the `manage_options` capability. Anyone else gets `consepo_csp_scanner_forbidden` with status 401 or 403.
- Authenticate as a logged-in administrator with the `X-WP-Nonce` header carrying a `wp_rest` nonce, as `@wordpress/api-fetch` does.
- Responses in this namespace carry `Cache-Control: no-store, no-cache, must-revalidate, max-age=0`, `Pragma: no-cache` and `X-Robots-Tag: noindex, nofollow`.
- Errors are WordPress REST errors (`code`, `message`, `data.status`). Errors from Consepo are translated, so Consepo rejecting a token is a 400 here, not a 401 that would read as an expired WordPress session.

## Routes

| Method | Route | Does |
| --- | --- | --- |
| GET | `/admin/status` | Everything the Overview shows: connection, scan, policy and integrity counts |
| GET | `/admin/connection` | The connection without the token: `connected`, `method`, `token` (`set` or `missing`), `connectedAt`, `expiresAt`, `oauthAvailable`, `redirectUri` |
| POST | `/admin/connection` | Connect with `api_key`, after Consepo accepts it |
| DELETE | `/admin/connection` | Disconnect, revoking OAuth tokens when Consepo offers revocation |
| POST | `/admin/connection/oauth` | Begin signing in with Consepo; returns `authorizeUrl` |
| POST | `/admin/connection/oauth/callback` | Finish signing in with the `code` and `state` Consepo returned |
| GET | `/admin/scan` | The site's scan, its directives and sources, crawl findings, last policy and report address |
| POST | `/admin/scan` | Start the site's scan, or re-run it in place |
| POST | `/admin/scan/refresh` | Ask Consepo for the scan's current state |
| GET | `/admin/settings` | The settings, the header they produce (`preview`), the last Consepo policy and the report address |
| POST | `/admin/settings` | Save changed settings; returns the same shape as GET |
| GET | `/admin/integrity` | The asset inventory, counts by status, and the pinning settings |
| DELETE | `/admin/integrity` | Forget the inventory; pinning stops until assets are seen again |
| POST | `/admin/integrity/discover` | Load the home page once and record its assets; returns the inventory plus `discovered` |
| POST | `/admin/integrity/rehash` | Hash entries again: local files now, remote ones on the next background run |
| POST | `/admin/hashes` | Hash `content`, or the file at `url` |

## Parameters

<!-- wp:docspress/fields {"title":"Request parameters","description":"JSON body fields. Every other route takes none.","fields":[{"name":"api_key","type":"string","required":true,"defaultValue":"","description":"POST /admin/connection. A Consepo token: csp_ followed by 48 lowercase hex characters.","values":"","deprecated":false},{"name":"code","type":"string","required":true,"defaultValue":"","description":"POST /admin/connection/oauth/callback. The authorization code Consepo returned.","values":"","deprecated":false},{"name":"state","type":"string","required":true,"defaultValue":"","description":"POST /admin/connection/oauth/callback. Must match the attempt this user started in the last ten minutes.","values":"","deprecated":false},{"name":"limit","type":"number","required":false,"defaultValue":"10","description":"POST /admin/scan. Most pages to crawl, 1 to 100.","values":"","deprecated":false},{"name":"depth","type":"number","required":false,"defaultValue":"10","description":"POST /admin/scan. Most links to follow, 1 to 10.","values":"","deprecated":false},{"name":"settings","type":"object","required":true,"defaultValue":"","description":"POST /admin/settings. Any subset of the keys in Settings; others are ignored.","values":"","deprecated":false},{"name":"ids","type":"array","required":false,"defaultValue":"[]","description":"POST /admin/integrity/rehash. Entry ids from GET /admin/integrity. Empty means every entry.","values":"","deprecated":false},{"name":"content","type":"string","required":false,"defaultValue":"","description":"POST /admin/hashes. Up to 2 MB, hashed exactly as sent.","values":"","deprecated":false},{"name":"url","type":"url","required":false,"defaultValue":"","description":"POST /admin/hashes. A public http or https URL; takes precedence over content.","values":"","deprecated":false}],"searchable":true,"compact":false} /-->

## Example: hash an inline script

<!-- wp:docspress/api-request {"method":"POST","endpoint":"/wp-json/consepo-csp-scanner/v1/admin/hashes","headers":"Content-Type: application/json\nX-WP-Nonce: \u003cwp_rest nonce\u003e","requestBody":"{\n  \u0022content\u0022: \u0022alert('Hello, world.');\u0022\n}","requestBodyFormat":"json","responseStatus":"200 OK","responseBody":"{\n  \u0022source\u0022: \u0022content\u0022,\n  \u0022bytes\u0022: 23,\n  \u0022hashes\u0022: [\n    {\n      \u0022algorithm\u0022: \u0022sha256\u0022,\n      \u0022base64\u0022: \u0022qznLcsROx4GACP2dm0UCKCzCG+HiZ1guq6ZZDob/Tng=\u0022,\n      \u0022sri\u0022: \u0022sha256-qznLcsROx4GACP2dm0UCKCzCG+HiZ1guq6ZZDob/Tng=\u0022,\n      \u0022csp\u0022: \u0022'sha256-qznLcsROx4GACP2dm0UCKCzCG+HiZ1guq6ZZDob/Tng='\u0022\n    },\n    {\n      \u0022algorithm\u0022: \u0022sha384\u0022,\n      \u0022base64\u0022: \u0022H8BRh8j48O9oYatfu5AZzq6A9RINhZO5H16dQZngK7T62em8MUt1FLm52t+eX6xO\u0022,\n      \u0022sri\u0022: \u0022sha384-H8BRh8j48O9oYatfu5AZzq6A9RINhZO5H16dQZngK7T62em8MUt1FLm52t+eX6xO\u0022,\n      \u0022csp\u0022: \u0022'sha384-H8BRh8j48O9oYatfu5AZzq6A9RINhZO5H16dQZngK7T62em8MUt1FLm52t+eX6xO'\u0022\n    },\n    {\n      \u0022algorithm\u0022: \u0022sha512\u0022,\n      \u0022base64\u0022: \u0022Q2bFTOhEALkN8hOms2FKTDLy7eugP2zFZ1T8LCvX42Fp3WoNr3bjZSAHeOsHrbV1Fu9/A0EzCinRE7Af1ofPrw==\u0022,\n      \u0022sri\u0022: \u0022sha512-Q2bFTOhEALkN8hOms2FKTDLy7eugP2zFZ1T8LCvX42Fp3WoNr3bjZSAHeOsHrbV1Fu9/A0EzCinRE7Af1ofPrw==\u0022,\n      \u0022csp\u0022: \u0022'sha512-Q2bFTOhEALkN8hOms2FKTDLy7eugP2zFZ1T8LCvX42Fp3WoNr3bjZSAHeOsHrbV1Fu9/A0EzCinRE7Af1ofPrw=='\u0022\n    }\n  ]\n}","responseBodyFormat":"json","runnable":false,"editable":false,"allowUnsafe":false,"timeout":10000} /-->

Replace `<wp_rest nonce>` with a nonce from `wp_create_nonce( 'wp_rest' )` for a logged-in administrator. The same request with `url` instead of `content` also returns `url`, `contentType`, `cors` and `volatile`.
