---
title: "Save Search"
method: POST
path: "/search/saved-searches"
tags: ["Search"]
---

# Save Search

`POST /search/saved-searches`

## Request

- Base URL: `https://be.graph8.com/api/v1`
- URL: `https://be.graph8.com/api/v1/search/saved-searches`
- Auth: HTTP bearer

Store a search so it can be run again.

Sending `id` REPLACES that saved search rather than creating a second one -
which is why a caller looping over a list should send the id back, not omit
it. A saved search belonging to someone else comes back as a 404 rather
than a 403, so a guessed id cannot confirm that it exists.

`icp_query` is stored verbatim and is not interpreted here.

## Headers

- `Authorization` string, nullable
- `X-Target-Org-Id` string, nullable

## Request body

- SaveSearchRequest: Store a search so a person can run it again later. `icp_query` is OPAQUE and round-tripped verbatim: the app stores it as a plain JSON blob and does not interpret it at save time, so this contract does not either. That is also why it is the one place here that does not go through the field map - translating a blob nobody reads would change what the caller gets back. `id` present means UPDATE the saved search rather than create a new one.
  - `title` string, required
  - `scope` string, required: What the saved search is over - `contacts` or `companies` today. Deliberately a free string rather than a closed enum, matching the app, which is designed to add more.
  - `icp_query` object, required: The search itself. Opaque and round-tripped as-is.
  - `id` integer, nullable: Send the id of an existing saved search to REPLACE it.

## Response `201`

Successful Response

- ApiResponseSearchDiscoveryPayload
  - `data` SearchDiscoveryPayload, required: An open envelope for an autocomplete or filter-option result.
  - `pagination` PaginationMeta
    - `page` integer, required: Current page number (1-indexed)
    - `limit` integer, required: Items per page
    - `total` integer, required: Total number of items
    - `has_next` boolean, required: Whether there are more pages
    - `next_cursor` string, nullable: Opaque cursor for the next page; null when there are no more items. Pass it back as the `cursor` query param to fetch the following page without computing page numbers.
    - `total_available` integer, nullable: Search endpoints only: how many records really match, when known. Can be larger than `total`, which is capped at the 10,000 results that can be paged. For company search this is a distinct-company estimate. Null when unknown; absent outside search.
    - `total_is_lower_bound` boolean, nullable: Search endpoints only: true when more records match than `total` shows (the result set is larger than the 10,000 results that can be paged). Absent outside search.
    - `notes` string[], nullable: Search endpoints only: plain-language notes about the result, e.g. that more records match than can be paged, or that a reversed `between` range was put in order.

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/graph8/apis/graph8-developer-api.md) · [All operations](https://skmtc.dev/graph8/apis/graph8-developer-api/llms.txt) · [OpenAPI document](https://skmtc.dev/graph8/apis/graph8-developer-api/revisions/2e7cfa0ca921?raw)
