> For clean Markdown content of this page, append .md to this URL. For the complete documentation index, see https://docs.agentmail.to/llms.txt.

# Query Rates

GET https://api.agentmail.to/v0/metrics/rates

Rolling bounce and complaint rates for the organization. At each
`period` grid point, the bounced (or complained) messages over the
preceding `window` divided by the messages sent over the same window,
with the send count alongside so you can see the volume behind
it. This is the number AgentMail's account moderation acts on: a
warning at a 5% bounce rate and suspension at 10%, evaluated over a
rolling 24 hours once at least 1,000 messages were sent in that
window. Defaults to the rolling 24-hour rate sampled hourly over the
last day; `start` must be within the last 90 days, `window` must be a
whole multiple of `period`, and the range plus window divided by
`period` must not exceed 1000 buckets.

**CLI:**
```bash
agentmail metrics query-rates
```

Reference: https://docs.agentmail.to/api-reference/metrics/query-rates

## Authentication

- `Authorization` header (bearer token, required) — Bearer authentication of the form `Bearer <token>`, where token is your auth token.

## Servers

- `https://api.agentmail.to` (prod, default)
- `https://x402.api.agentmail.to` (prod-x402)
- `https://mpp.api.agentmail.to` (prod-mpp)
- `https://api.agentmail.eu` (eu-prod)

## Request

### Query parameters

- `rate_types` (list of enum, optional) — List of rate types to query. Omit to query both.
  - Allowed values: `bounce`, `complaint`
- `start` (datetime, optional) — Start timestamp for the query.
- `end` (datetime, optional) — End timestamp for the query.
- `period` (integer, optional) — How often a point is sampled, as a whole number of seconds between 60 and 86400. Defaults to 3600 (one point per hour).
- `window` (integer, optional) — How far back each point looks, as a whole number of seconds. Must be a whole multiple of `period`, at most 30 days (2592000). Defaults to 86400 (a rolling 24-hour rate).
- `limit` (integer, optional) — Limit on number of buckets to return.
- `descending` (boolean, optional) — Sort in descending order.

## Response

### 200

- `map from enum to list of RatePoint`

## Errors

### 400 Validation Error

- `name` (string, required) — Name of error.
- `errors` (any, required) — Validation errors. Each entry has a path and a message identifying the invalid field.
- `code` (string, optional) — Stable, machine-readable error code in snake_case (for example, not_found or missing_permission). Branch on this rather than the message text.
- `message` (string, optional) — Error message.
- `fix` (string, optional) — The concrete next action that resolves the error.
- `docs` (string, optional) — Link to the error reference entry for this code.

## Types

### RatePoint

- `timestamp` (datetime, required) — End of the window the point covers; the window is the `window` seconds before it.
- `sent` (integer, required) — Messages sent in the window, counted per recipient.
- `rate` (double, optional) — Bounced or complained messages divided by messages sent over the window, as a fraction (0.05 is 5%). Null when nothing was sent in the window.

## Examples

**Response**

```json
{
  "bounce": [
    {
      "timestamp": "2024-01-15T09:30:00Z",
      "sent": 1,
      "rate": 1.1
    },
    {
      "timestamp": "2024-01-15T09:30:00Z",
      "sent": 1,
      "rate": 1.1
    }
  ]
}
```

**SDK Code**

```python
import requests

url = "https://api.agentmail.to/v0/metrics/rates"

headers = {"Authorization": "Bearer <api_key>"}

response = requests.get(url, headers=headers)

print(response.json())
```

```javascript
const url = 'https://api.agentmail.to/v0/metrics/rates';
const options = {method: 'GET', headers: {Authorization: 'Bearer <api_key>'}};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://api.agentmail.to/v0/metrics/rates"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("Authorization", "Bearer <api_key>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://api.agentmail.to/v0/metrics/rates")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <api_key>'

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://api.agentmail.to/v0/metrics/rates")
  .header("Authorization", "Bearer <api_key>")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://api.agentmail.to/v0/metrics/rates', [
  'headers' => [
    'Authorization' => 'Bearer <api_key>',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://api.agentmail.to/v0/metrics/rates");
var request = new RestRequest(Method.GET);
request.AddHeader("Authorization", "Bearer <api_key>");
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = ["Authorization": "Bearer <api_key>"]

let request = NSMutableURLRequest(url: NSURL(string: "https://api.agentmail.to/v0/metrics/rates")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```