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

# Audit Log Example

# Using the Public API v1 Audit Log APIs

This guide explains how to retrieve audit logs via the Public API using the **search** and **query** endpoints. The main idea: **you use a timestamp once to find a starting point, then use log IDs for all actual retrieval and pagination.**

## **Why log IDs instead of timestamps?**

* **Search by time** is supported only to get a **starting point** (the first log at or after a given time). The API returns one log and its **ID**.
* **Fetching and pagination** use that **log ID** (and then the ID of the last log in each page). We do not support “give me all logs between 10:00 and 10:15” by timestamp in a single call.

Reasons we key off IDs:

1. **Stable ordering** — Logs are ordered by ID. IDs are unique and never change, so pagination is consistent even if many events share the same second.
2. **No gaps or duplicates** — Using “last seen ID” as the cursor avoids skipping or duplicating logs when events are dense.
3. **Clear “next page”** — The next request is always “logs after this ID,” which is unambiguous.

So: **think of the timestamp as “where do I start?”** and **the log ID as “where am I in the stream?”** for all subsequent requests.

## **The two endpoints**

| **Purpose**                      | **Endpoint**                                     | **You provide**                                          | **You get**                                                                               |
| :------------------------------- | :----------------------------------------------- | :------------------------------------------------------- | :---------------------------------------------------------------------------------------- |
| **Find a starting log by time**  | `GET /api/v1/logs/audit/search?time=<timestamp>` | A timestamp (e.g. 10:00 AM)                              | One log object — the **first** log at or after that time. That log’s `id` is your cursor. |
| **Fetch logs after a given log** | `GET /api/v1/logs/audit?from=<log_id>&take=<n>`  | A log ID (`from`) and how many to fetch (`take`, 1–1000) | Up to `take` logs whose ID is **after** `from`, in ascending order by ID.                 |

Important details:

* **Search** returns a **single** log: the first one with `timestamp >=` your `time`. The response body is `{ "log": { "id": "...", "timestamp": "...", ... } }`. You need that `log.id` for the next step.
* **Query** returns logs with **ID strictly greater than** `from`. So the log you got from search is **not** included in the first query response — it is the first log in your time range; you add it to your results yourself, then use its ID to fetch the rest.

Base URL for the Public API: `https://api.harvey.ai` (or your environment’s base URL). Full paths are `/api/v1/logs/audit/search` and `/api/v1/logs/audit`. See [developers.harvey.ai](https://developers.harvey.ai) for the full API reference.

## **Example 1: “All logs since 10:00 AM”**

Goal: at 10:15 AM, get every audit log from 10:00 AM onward.

### **Step 1 — Get the first log and its ID (timestamp → ID)**

* Call: `GET /api/v1/logs/audit/search?time=<10:00 AM in ISO 8601 or your API’s accepted format>`
* Response: `{ "log": { "id": "abc-123-...", "timestamp": "2025-03-11T10:00:00.000Z", ... } }`
* **Keep this log** — it is the first log in your range. Add it to your result set.
* **Save** `log.id` (e.g. `abc-123-...`) — this is your cursor for the next request.

If the response is an error (e.g. no logs available for that time), there are no logs at or after 10:00 AM; you’re done.

### **Step 2 — Fetch the next logs (ID-based)**

* Call: `GET /api/v1/logs/audit?from=abc-123-...&take=1000`
* Response: `{ "logs": [ ... ] }` — up to 1000 logs whose ID is **after** `abc-123-...`.

Append these to your result set.

### **Step 3 — Paginate if needed**

* Each response contains **at most** `take` logs (here, 1000). You never get “more than 1000” in one response.
* If you got **exactly 1000** logs, there may be more. Take the **last** log in the array and use its `id` as the new `from`:
  * `GET /api/v1/logs/audit?from=<last_log_id>&take=1000`
* Repeat until a response has **fewer than 1000** logs — then there are no more.

Your full “logs since 10:00 AM” set is: **\[log from Step 1] + \[all logs from Step 2 and Step 3].**

## **Example 2: “A 15-minute slice starting at 8:00 AM”**

Goal: all logs from 8:00 AM to 8:15 AM.

You still use **search** to turn “8:00 AM” into a starting log ID, then **query** by ID. The only extra part is **stopping** when logs go past 8:15 AM.

### **Step 1 — Get the first log at or after 8:00 AM**

* Call: `GET /api/v1/logs/audit/search?time=<8:00 AM>`
* Keep the returned **log** as the first log in your slice.
* Save `log.id` for the next request.

### **Step 2 — Fetch in pages and stop at the end time**

* Call: `GET /api/v1/logs/audit?from=<saved_id>&take=1000`
* For each log in `logs`, check its `timestamp`:
  * If `timestamp <= 8:15 AM` → include it in your 15-minute slice.
  * If `timestamp > 8:15 AM` → you’ve passed the end of the window; stop requesting more and (optionally) drop any later logs from this batch.
* If you got 1000 logs and the last one is still before or at 8:15 AM, there may be more in that window. Use the **last** log’s `id` as `from` and call again. Repeat until you either get fewer than 1000 logs or you see a timestamp after 8:15 AM.

So: **timestamps** are used only to (1) find the start via search and (2) filter or stop when you’ve reached your end time. **IDs** are used for every “give me the next page” request.

## **Summary**

* **Timestamps** answer: “Where do I start?” (search) and “Where do I stop?” (your own end-time filter).
* **Log IDs** answer: “What’s the next page?” (query’s `from` and pagination).
* Always **include the log returned by search** in your results; the first **query** call returns only logs **after** that log’s ID.
* Pagination: use the **last** log’s ID from each response as `from` for the next request; when you get fewer than `take` logs, you’ve reached the end.

For exact parameter names, formats, and error codes, use the [Public API reference](https://developers.harvey.ai) for the audit log endpoints.
