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

# Tines

> Call Keenable web search and page fetch from Tines stories with the HTTP Request action, with no key to start.

*HTTP Request action*

Tines stories call any REST API with the [HTTP Request action](https://www.tines.com/docs/actions/types/http-request/). Point one at Keenable and a story can search the web for an alert, an indicator or a vendor, read a page as markdown, and pass the result to the next action. There is nothing to install, and no key or credential to start.

## Search the web

Add an **HTTP Request** action and paste this configuration. `X-Keenable-Title` names your app and is required without a key.

```json theme={"system"}
{
  "url": "https://api.keenable.ai/v1/search/public",
  "method": "post",
  "content_type": "json",
  "headers": {
    "X-Keenable-Title": "Tines"
  },
  "payload": {
    "query": "<<receive_event.body.query>>",
    "max_results": 5
  }
}
```

Replace `<<receive_event.body.query>>` with a field from an upstream action. The action emits the results in `body.results`, each with `title`, `url`, `snippet` (text from the page) and, when known, `published_at`. Read `snippet`: `description` comes back empty.

To keep a search to one site and a time window, add `site` and a date filter to `payload`:

```json theme={"system"}
"payload": {
  "query": "phishing campaign targeting Microsoft 365",
  "site": "bleepingcomputer.com",
  "published_after": "30d",
  "max_results": 5
}
```

Dates take `YYYY-MM-DD`, a timestamp or a relative window such as `7d` ([date filters](/api-reference/search#date-and-time-filters)). Results carry a few thousand characters of page text each; `snippet_max_length` (180 to 10000) keeps events smaller.

## Read a page

Fetch is a GET request, and Tines sends a GET action's `payload` as query parameters:

```json theme={"system"}
{
  "url": "https://api.keenable.ai/v1/fetch/public",
  "method": "get",
  "headers": {
    "X-Keenable-Title": "Tines"
  },
  "payload": {
    "url": "<<search_the_web.body.results[0].url>>"
  }
}
```

Here `search_the_web` is the name of the search action. The page comes back as markdown in `body.content`, with `title` and `published_at` (Unix seconds) when known. Add `"live": "true"` to `payload` for a page Keenable has not indexed ([fetch reference](/api-reference/fetch)).

## With an API key

The public endpoints are limited per IP, and that limit is shared with everything else on the same address. A key lifts the hourly limit for stories that run on a schedule or at volume:

1. Create a key in the [Keenable console](https://app.keenable.ai/console).
2. In Tines, open **Credentials**, create a **Text** credential named `keenable` and paste the key.
3. Drop `/public` from the action URLs and send the key instead of the title header:

```json theme={"system"}
{
  "url": "https://api.keenable.ai/v1/search",
  "method": "post",
  "content_type": "json",
  "headers": {
    "X-API-Key": "<<CREDENTIAL.keenable>>"
  },
  "payload": {
    "query": "<<receive_event.body.query>>",
    "max_results": 5
  }
}
```

The fetch action changes the same way, to `https://api.keenable.ai/v1/fetch` with the `X-API-Key` header. Keyed calls count against your [credits](/credits); both tiers are on [Rate limits](/rate-limits).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.