# Reloop Documentation (full) > Full-document snapshot of Reloop docs for long-context agents. > Hosted on the marketing web app (source of truth for agent files). > Curated docs index: https://reloop.sh/llms-docs.txt > Site index: https://reloop.sh/llms.txt > Product skill: https://reloop.sh/skill.md > Prefer per-page markdown: append `.md` under https://reloop.sh/docs/ Generated from 333 source files. --- # introduction.mdx Source: https://reloop.sh/docs Markdown: https://reloop.sh/docs/introduction.md --- # learn/ai/api-keys.curl.md Source: https://reloop.sh/docs/learn/ai/api-keys.curl Markdown: https://reloop.sh/docs/learn/ai/api-keys.curl.md # API Keys — cURL > Agent-optimized samples for managing Reloop API keys in cURL. Index: [api-keys.md](./api-keys.md) ## Auth reminder - Header: `x-api-key: rl_...` - Secret shown once on create/rotate ## Create API key `POST /api/api-key/v1/` ```bash curl -X POST https://reloop.sh/api/api-key/v1/ \ -H "x-api-key: rl_123456789" \ -H "Content-Type: application/json" \ -d '{"name": "Production Key"}' ``` ## List API keys `GET /api/api-key/v1/` ```bash curl "https://reloop.sh/api/api-key/v1/?page=1&limit=10" \ -H "x-api-key: rl_123456789" ``` ## Get API key `GET /api/api-key/v1/:api_key_id` ```bash curl "https://reloop.sh/api/api-key/v1/key_123456789" \ -H "x-api-key: rl_123456789" ``` ## Update API key `PATCH /api/api-key/v1/:api_key_id` ```bash curl -X PATCH https://reloop.sh/api/api-key/v1/key_123456789 \ -H "x-api-key: rl_123456789" \ -H "Content-Type: application/json" \ -d '{"name": "Updated Key Name"}' ``` ## Rotate API key `POST /api/api-key/v1/rotate/:api_key_id` ```bash curl -X POST https://reloop.sh/api/api-key/v1/rotate/key_123456789 \ -H "x-api-key: rl_123456789" ``` ## Disable API key `POST /api/api-key/v1/disable/:api_key_id` ```bash curl -X POST https://reloop.sh/api/api-key/v1/disable/key_123456789 \ -H "x-api-key: rl_123456789" ``` ## Enable API key `POST /api/api-key/v1/enable/:api_key_id` ```bash curl -X POST https://reloop.sh/api/api-key/v1/enable/key_123456789 \ -H "x-api-key: rl_123456789" ``` ## Delete API key `DELETE /api/api-key/v1/:api_key_id` ```bash curl -X DELETE https://reloop.sh/api/api-key/v1/key_123456789 \ -H "x-api-key: rl_123456789" ``` --- # learn/ai/api-keys.dotnet.md Source: https://reloop.sh/docs/learn/ai/api-keys.dotnet Markdown: https://reloop.sh/docs/learn/ai/api-keys.dotnet.md # API Keys — .NET > Agent-optimized samples for managing Reloop API keys in .NET. Index: [api-keys.md](./api-keys.md) ## Auth reminder - Header: `x-api-key: rl_...` - Secret shown once on create/rotate ## Create API key `POST /api/api-key/v1/` ```csharp using Reloop; using Reloop.Models; var reloop = new ReloopClient("rl_123456789"); var apiKey = await reloop.ApiKeys.CreateAsync(new CreateApiKeyParams(Name: "Production Key")); ``` ## List API keys `GET /api/api-key/v1/` ```csharp using Reloop; using Reloop.Models; var reloop = new ReloopClient("rl_123456789"); var apiKeys = await reloop.ApiKeys.ListAsync(new ApiKeyListParams { Page = 1, Limit = 10, }); ``` ## Get API key `GET /api/api-key/v1/:api_key_id` ```csharp using Reloop; using Reloop.Models; var reloop = new ReloopClient("rl_123456789"); await reloop.ApiKeys.GetAsync("key_123456789"); ``` ## Update API key `PATCH /api/api-key/v1/:api_key_id` ```csharp using Reloop; using Reloop.Models; var reloop = new ReloopClient("rl_123456789"); var apiKey = await reloop.ApiKeys.UpdateAsync("key_123456789", new UpdateApiKeyParams(Name: "Updated Key Name")); ``` ## Rotate API key `POST /api/api-key/v1/rotate/:api_key_id` ```csharp using Reloop; using Reloop.Models; var reloop = new ReloopClient("rl_123456789"); await reloop.ApiKeys.RotateAsync("key_123456789"); ``` ## Disable API key `POST /api/api-key/v1/disable/:api_key_id` ```csharp using Reloop; using Reloop.Models; var reloop = new ReloopClient("rl_123456789"); await reloop.ApiKeys.DisableAsync("key_123456789"); ``` ## Enable API key `POST /api/api-key/v1/enable/:api_key_id` ```csharp using Reloop; using Reloop.Models; var reloop = new ReloopClient("rl_123456789"); await reloop.ApiKeys.EnableAsync("key_123456789"); ``` ## Delete API key `DELETE /api/api-key/v1/:api_key_id` ```csharp using Reloop; using Reloop.Models; var reloop = new ReloopClient("rl_123456789"); await reloop.ApiKeys.DeleteAsync("key_123456789"); ``` --- # learn/ai/api-keys.go.md Source: https://reloop.sh/docs/learn/ai/api-keys.go Markdown: https://reloop.sh/docs/learn/ai/api-keys.go.md # API Keys — Go > Agent-optimized samples for managing Reloop API keys in Go. Index: [api-keys.md](./api-keys.md) ## Auth reminder - Header: `x-api-key: rl_...` - Secret shown once on create/rotate ## Create API key `POST /api/api-key/v1/` ```go client, _ := reloop.NewClient(reloop.ClientOptions{ APIKey: "rl_123456789", }) apiKey, _ := client.ApiKeys.Create(reloop.CreateApiKeyParams{ Name: "Production Key", }) ``` ## List API keys `GET /api/api-key/v1/` ```go client, _ := reloop.NewClient(reloop.ClientOptions{ APIKey: "rl_123456789", }) apiKeys, _ := client.ApiKeys.List(&reloop.ApiKeyListParams{ Page: reloop.Int(1), Limit: reloop.Int(10), }) ``` ## Get API key `GET /api/api-key/v1/:api_key_id` ```go client, _ := reloop.NewClient(reloop.ClientOptions{ APIKey: "rl_123456789", }) _, _ = client.ApiKeys.Get("key_123456789") ``` ## Update API key `PATCH /api/api-key/v1/:api_key_id` ```go client, _ := reloop.NewClient(reloop.ClientOptions{ APIKey: "rl_123456789", }) apiKey, _ := client.ApiKeys.Update("key_123456789", reloop.UpdateApiKeyParams{ Name: "Updated Key Name", }) ``` ## Rotate API key `POST /api/api-key/v1/rotate/:api_key_id` ```go client, _ := reloop.NewClient(reloop.ClientOptions{ APIKey: "rl_123456789", }) _, _ = client.ApiKeys.Rotate("key_123456789") ``` ## Disable API key `POST /api/api-key/v1/disable/:api_key_id` ```go client, _ := reloop.NewClient(reloop.ClientOptions{ APIKey: "rl_123456789", }) _, _ = client.ApiKeys.Disable("key_123456789") ``` ## Enable API key `POST /api/api-key/v1/enable/:api_key_id` ```go client, _ := reloop.NewClient(reloop.ClientOptions{ APIKey: "rl_123456789", }) _, _ = client.ApiKeys.Enable("key_123456789") ``` ## Delete API key `DELETE /api/api-key/v1/:api_key_id` ```go client, _ := reloop.NewClient(reloop.ClientOptions{ APIKey: "rl_123456789", }) _, _ = client.ApiKeys.Delete("key_123456789") ``` --- # learn/ai/api-keys.java.md Source: https://reloop.sh/docs/learn/ai/api-keys.java Markdown: https://reloop.sh/docs/learn/ai/api-keys.java.md # API Keys — Java > Agent-optimized samples for managing Reloop API keys in Java. Index: [api-keys.md](./api-keys.md) ## Auth reminder - Header: `x-api-key: rl_...` - Secret shown once on create/rotate ## Create API key `POST /api/api-key/v1/` ```java ReloopClient reloop = new ReloopClient("rl_123456789"); CreateApiKeyParams params = new CreateApiKeyParams(); params.name = "Production Key"; var apiKey = reloop.apiKey.create(params); System.out.println(apiKey.id + " " + apiKey.key); ``` ## List API keys `GET /api/api-key/v1/` ```java ReloopClient reloop = new ReloopClient("rl_123456789"); ApiKeyListParams params = new ApiKeyListParams(); params.page = 1; params.limit = 10; params.enabled = true; var apiKeys = reloop.apiKey.list(params); System.out.println(apiKeys.total + " " + apiKeys.apiKeys); ``` ## Get API key `GET /api/api-key/v1/:api_key_id` ```java ReloopClient reloop = new ReloopClient("rl_123456789"); var apiKey = reloop.apiKey.get("key_123456789"); System.out.println(apiKey.id + " " + apiKey.name + " " + apiKey.enabled); ``` ## Update API key `PATCH /api/api-key/v1/:api_key_id` ```java ReloopClient reloop = new ReloopClient("rl_123456789"); UpdateApiKeyParams params = new UpdateApiKeyParams(); params.name = "Updated Key Name"; var apiKey = reloop.apiKey.update("key_123456789", params); System.out.println(apiKey.id + " " + apiKey.name); ``` ## Rotate API key `POST /api/api-key/v1/rotate/:api_key_id` ```java ReloopClient reloop = new ReloopClient("rl_123456789"); var apiKey = reloop.apiKey.rotate("key_123456789"); System.out.println(apiKey.id + " " + apiKey.key); ``` ## Disable API key `POST /api/api-key/v1/disable/:api_key_id` ```java ReloopClient reloop = new ReloopClient("rl_123456789"); var apiKey = reloop.apiKey.disable("key_123456789"); System.out.println(apiKey.id + " " + apiKey.enabled); ``` ## Enable API key `POST /api/api-key/v1/enable/:api_key_id` ```java ReloopClient reloop = new ReloopClient("rl_123456789"); var apiKey = reloop.apiKey.enable("key_123456789"); System.out.println(apiKey.id + " " + apiKey.enabled); ``` ## Delete API key `DELETE /api/api-key/v1/:api_key_id` ```java ReloopClient reloop = new ReloopClient("rl_123456789"); var apiKey = reloop.apiKey.delete("key_123456789"); System.out.println(apiKey.id + " " + apiKey.message); ``` --- # learn/ai/api-keys.md Source: https://reloop.sh/docs/learn/ai/api-keys Markdown: https://reloop.sh/docs/learn/ai/api-keys.md # API Keys (agent guide) > Prefer this guide over the human dashboard page at `/docs/learn/api-keys`. Use a language-specific file below for runnable SDK samples. ## Auth - Send `x-api-key: ` on every request. - Secrets are prefixed with `rl_`. - Store secrets in env vars / a secret manager. Never commit them. - The full secret is returned **once** on create and rotate. Reloop stores a hash; it cannot be retrieved again. ## Rules - **Disable** pauses the key (requests return 401); you can re-enable later. - **Delete** permanently revokes the key; irreversible. - API keys work for REST (`x-api-key`) and SMTP (password = secret). - Creating or managing keys requires an existing authenticated API key. ## Endpoints | Action | Method | Path | |--------|--------|------| | Create | POST | /api/api-key/v1/ | | List | GET | /api/api-key/v1/ | | Get | GET | /api/api-key/v1/:api_key_id | | Update | PATCH | /api/api-key/v1/:api_key_id | | Rotate | POST | /api/api-key/v1/rotate/:api_key_id | | Disable | POST | /api/api-key/v1/disable/:api_key_id | | Enable | POST | /api/api-key/v1/enable/:api_key_id | | Delete | DELETE | /api/api-key/v1/:api_key_id | Base URL: `https://reloop.sh` ## Language guides - [Node](./api-keys.node.md) - [cURL](./api-keys.curl.md) - [Python](./api-keys.python.md) - [PHP](./api-keys.php.md) - [Java](./api-keys.java.md) - [.NET](./api-keys.dotnet.md) - [Go](./api-keys.go.md) - [Rust](./api-keys.rust.md) - [Ruby](./api-keys.ruby.md) ## Dashboard (humans) Dashboard UI walkthrough (GIFs, tabs): [/docs/learn/api-keys](https://reloop.sh/docs/learn/api-keys) --- # learn/ai/api-keys.node.md Source: https://reloop.sh/docs/learn/ai/api-keys.node Markdown: https://reloop.sh/docs/learn/ai/api-keys.node.md # API Keys — Node > Agent-optimized samples for managing Reloop API keys in Node. Index: [api-keys.md](./api-keys.md) ## Auth reminder - Header: `x-api-key: rl_...` - Secret shown once on create/rotate ## Create API key `POST /api/api-key/v1/` ```javascript const reloop = new Reloop({ apiKey: "rl_123456789" }); const { apiKey, apiKeyError } = await reloop.apiKey.create({ name: "Production Key", }); if (apiKeyError) throw apiKeyError; console.log(apiKey.id, apiKey.key); ``` ## List API keys `GET /api/api-key/v1/` ```javascript const reloop = new Reloop({ apiKey: "rl_123456789" }); const { apiKeys, apiKeyError } = await reloop.apiKey.list({ page: 1, limit: 10, enabled: true, }); if (apiKeyError) throw apiKeyError; console.log(apiKeys.total, apiKeys.apiKeys); ``` ## Get API key `GET /api/api-key/v1/:api_key_id` ```javascript const reloop = new Reloop({ apiKey: "rl_123456789" }); const { apiKey, apiKeyError } = await reloop.apiKey.get("key_123456789"); if (apiKeyError) throw apiKeyError; console.log(apiKey.id, apiKey.name, apiKey.enabled); ``` ## Update API key `PATCH /api/api-key/v1/:api_key_id` ```javascript const reloop = new Reloop({ apiKey: "rl_123456789" }); const { apiKey, apiKeyError } = await reloop.apiKey.update("key_123456789", { name: "Updated Key Name", }); if (apiKeyError) throw apiKeyError; console.log(apiKey.id, apiKey.name); ``` ## Rotate API key `POST /api/api-key/v1/rotate/:api_key_id` ```javascript const reloop = new Reloop({ apiKey: "rl_123456789" }); const { apiKey, apiKeyError } = await reloop.apiKey.rotate("key_123456789"); if (apiKeyError) throw apiKeyError; console.log(apiKey.id, apiKey.key); ``` ## Disable API key `POST /api/api-key/v1/disable/:api_key_id` ```javascript const reloop = new Reloop({ apiKey: "rl_123456789" }); const { apiKey, apiKeyError } = await reloop.apiKey.disable("key_123456789"); if (apiKeyError) throw apiKeyError; console.log(apiKey.id, apiKey.enabled); ``` ## Enable API key `POST /api/api-key/v1/enable/:api_key_id` ```javascript const reloop = new Reloop({ apiKey: "rl_123456789" }); const { apiKey, apiKeyError } = await reloop.apiKey.enable("key_123456789"); if (apiKeyError) throw apiKeyError; console.log(apiKey.id, apiKey.enabled); ``` ## Delete API key `DELETE /api/api-key/v1/:api_key_id` ```javascript const reloop = new Reloop({ apiKey: "rl_123456789" }); const { apiKey, apiKeyError } = await reloop.apiKey.delete("key_123456789"); if (apiKeyError) throw apiKeyError; console.log(apiKey.id, apiKey.message); ``` --- # learn/ai/api-keys.php.md Source: https://reloop.sh/docs/learn/ai/api-keys.php Markdown: https://reloop.sh/docs/learn/ai/api-keys.php.md # API Keys — PHP > Agent-optimized samples for managing Reloop API keys in PHP. Index: [api-keys.md](./api-keys.md) ## Auth reminder - Header: `x-api-key: rl_...` - Secret shown once on create/rotate ## Create API key `POST /api/api-key/v1/` ```php apiKey->create([ 'name' => 'Production Key', ]); echo $apiKey['id'] . ' ' . $apiKey['key'] . PHP_EOL; ``` ## List API keys `GET /api/api-key/v1/` ```php apiKey->list([ 'page' => 1, 'limit' => 10, 'enabled' => true, ]); echo $apiKeys['total'] . ' ' . $apiKeys['apiKeys'] . PHP_EOL; ``` ## Get API key `GET /api/api-key/v1/:api_key_id` ```php apiKey->get('key_123456789'); echo $apiKey['id'] . ' ' . $apiKey['name'] . ' ' . $apiKey['enabled'] . PHP_EOL; ``` ## Update API key `PATCH /api/api-key/v1/:api_key_id` ```php apiKey->update('key_123456789', [ 'name' => 'Updated Key Name', ]); echo $apiKey['id'] . ' ' . $apiKey['name'] . PHP_EOL; ``` ## Rotate API key `POST /api/api-key/v1/rotate/:api_key_id` ```php apiKey->rotate('key_123456789'); echo $apiKey['id'] . ' ' . $apiKey['key'] . PHP_EOL; ``` ## Disable API key `POST /api/api-key/v1/disable/:api_key_id` ```php apiKey->disable('key_123456789'); echo $apiKey['id'] . ' ' . $apiKey['enabled'] . PHP_EOL; ``` ## Enable API key `POST /api/api-key/v1/enable/:api_key_id` ```php apiKey->enable('key_123456789'); echo $apiKey['id'] . ' ' . $apiKey['enabled'] . PHP_EOL; ``` ## Delete API key `DELETE /api/api-key/v1/:api_key_id` ```php apiKey->delete('key_123456789'); echo $apiKey['id'] . ' ' . $apiKey['message'] . PHP_EOL; ``` --- # learn/ai/api-keys.python.md Source: https://reloop.sh/docs/learn/ai/api-keys.python Markdown: https://reloop.sh/docs/learn/ai/api-keys.python.md # API Keys — Python > Agent-optimized samples for managing Reloop API keys in Python. Index: [api-keys.md](./api-keys.md) ## Auth reminder - Header: `x-api-key: rl_...` - Secret shown once on create/rotate ## Create API key `POST /api/api-key/v1/` ```python from reloop_email import Reloop reloop = Reloop(api_key="rl_123456789") result = reloop.api_key.create({ "name": "Production Key", }) if result.api_key_error: raise result.api_key_error print(result.api_key["id"], result.api_key["key"]) ``` ## List API keys `GET /api/api-key/v1/` ```python from reloop_email import Reloop reloop = Reloop(api_key="rl_123456789") result = reloop.api_key.list({ "page": 1, "limit": 10, "enabled": True, }) if result.api_key_error: raise result.api_key_error print(result.api_keys["total"], result.api_keys["apiKeys"]) ``` ## Get API key `GET /api/api-key/v1/:api_key_id` ```python from reloop_email import Reloop reloop = Reloop(api_key="rl_123456789") result = reloop.api_key.get("key_123456789") if result.api_key_error: raise result.api_key_error print(result.api_key["id"], result.api_key["name"], result.api_key["enabled"]) ``` ## Update API key `PATCH /api/api-key/v1/:api_key_id` ```python from reloop_email import Reloop reloop = Reloop(api_key="rl_123456789") result = reloop.api_key.update("key_123456789", { "name": "Updated Key Name", }) if result.api_key_error: raise result.api_key_error print(result.api_key["id"], result.api_key["name"]) ``` ## Rotate API key `POST /api/api-key/v1/rotate/:api_key_id` ```python from reloop_email import Reloop reloop = Reloop(api_key="rl_123456789") result = reloop.api_key.rotate("key_123456789") if result.api_key_error: raise result.api_key_error print(result.api_key["id"], result.api_key["key"]) ``` ## Disable API key `POST /api/api-key/v1/disable/:api_key_id` ```python from reloop_email import Reloop reloop = Reloop(api_key="rl_123456789") result = reloop.api_key.disable("key_123456789") if result.api_key_error: raise result.api_key_error print(result.api_key["id"], result.api_key["enabled"]) ``` ## Enable API key `POST /api/api-key/v1/enable/:api_key_id` ```python from reloop_email import Reloop reloop = Reloop(api_key="rl_123456789") result = reloop.api_key.enable("key_123456789") if result.api_key_error: raise result.api_key_error print(result.api_key["id"], result.api_key["enabled"]) ``` ## Delete API key `DELETE /api/api-key/v1/:api_key_id` ```python from reloop_email import Reloop reloop = Reloop(api_key="rl_123456789") result = reloop.api_key.delete("key_123456789") if result.api_key_error: raise result.api_key_error print(result.api_key["id"], result.api_key["message"]) ``` --- # learn/ai/api-keys.ruby.md Source: https://reloop.sh/docs/learn/ai/api-keys.ruby Markdown: https://reloop.sh/docs/learn/ai/api-keys.ruby.md # API Keys — Ruby > Agent-optimized samples for managing Reloop API keys in Ruby. Index: [api-keys.md](./api-keys.md) ## Auth reminder - Header: `x-api-key: rl_...` - Secret shown once on create/rotate ## Create API key `POST /api/api-key/v1/` ```ruby require "reloop" reloop = Reloop::Client.new(api_key: "rl_123456789") api_key = reloop.api_keys.create(name: "Production Key") ``` ## List API keys `GET /api/api-key/v1/` ```ruby require "reloop" reloop = Reloop::Client.new(api_key: "rl_123456789") api_keys = reloop.api_keys.list(page: 1, limit: 10) ``` ## Get API key `GET /api/api-key/v1/:api_key_id` ```ruby require "reloop" reloop = Reloop::Client.new(api_key: "rl_123456789") reloop.api_keys.get("key_123456789") ``` ## Update API key `PATCH /api/api-key/v1/:api_key_id` ```ruby require "reloop" reloop = Reloop::Client.new(api_key: "rl_123456789") api_key = reloop.api_keys.update("key_123456789", name: "Updated Key Name") ``` ## Rotate API key `POST /api/api-key/v1/rotate/:api_key_id` ```ruby require "reloop" reloop = Reloop::Client.new(api_key: "rl_123456789") reloop.api_keys.rotate("key_123456789") ``` ## Disable API key `POST /api/api-key/v1/disable/:api_key_id` ```ruby require "reloop" reloop = Reloop::Client.new(api_key: "rl_123456789") reloop.api_keys.disable("key_123456789") ``` ## Enable API key `POST /api/api-key/v1/enable/:api_key_id` ```ruby require "reloop" reloop = Reloop::Client.new(api_key: "rl_123456789") reloop.api_keys.enable("key_123456789") ``` ## Delete API key `DELETE /api/api-key/v1/:api_key_id` ```ruby require "reloop" reloop = Reloop::Client.new(api_key: "rl_123456789") reloop.api_keys.delete("key_123456789") ``` --- # learn/ai/api-keys.rust.md Source: https://reloop.sh/docs/learn/ai/api-keys.rust Markdown: https://reloop.sh/docs/learn/ai/api-keys.rust.md # API Keys — Rust > Agent-optimized samples for managing Reloop API keys in Rust. Index: [api-keys.md](./api-keys.md) ## Auth reminder - Header: `x-api-key: rl_...` - Secret shown once on create/rotate ## Create API key `POST /api/api-key/v1/` ```rust use reloop::ReloopClient; #[tokio::main] async fn main() -> Result<(), Box> { let reloop = ReloopClient::new("rl_123456789".to_string(), None); reloop.api_keys().create(CreateApiKeyParams { name: "Production Key".to_string(), }).await?; Ok(()) } ``` ## List API keys `GET /api/api-key/v1/` ```rust use reloop::ReloopClient; #[tokio::main] async fn main() -> Result<(), Box> { let reloop = ReloopClient::new("rl_123456789".to_string(), None); reloop.api_keys().list(Some(ApiKeyListParams { page: Some(1), limit: Some(10), ..Default::default() })).await?; Ok(()) } ``` ## Get API key `GET /api/api-key/v1/:api_key_id` ```rust use reloop::ReloopClient; #[tokio::main] async fn main() -> Result<(), Box> { let reloop = ReloopClient::new("rl_123456789".to_string(), None); reloop.api_keys().get("key_123456789").await?; Ok(()) } ``` ## Update API key `PATCH /api/api-key/v1/:api_key_id` ```rust use reloop::ReloopClient; #[tokio::main] async fn main() -> Result<(), Box> { let reloop = ReloopClient::new("rl_123456789".to_string(), None); reloop.api_keys().update("key_123456789", UpdateApiKeyParams { name: "Updated Key Name".to_string(), }).await?; Ok(()) } ``` ## Rotate API key `POST /api/api-key/v1/rotate/:api_key_id` ```rust use reloop::ReloopClient; #[tokio::main] async fn main() -> Result<(), Box> { let reloop = ReloopClient::new("rl_123456789".to_string(), None); reloop.api_keys().rotate("key_123456789").await?; Ok(()) } ``` ## Disable API key `POST /api/api-key/v1/disable/:api_key_id` ```rust use reloop::ReloopClient; #[tokio::main] async fn main() -> Result<(), Box> { let reloop = ReloopClient::new("rl_123456789".to_string(), None); reloop.api_keys().disable("key_123456789").await?; Ok(()) } ``` ## Enable API key `POST /api/api-key/v1/enable/:api_key_id` ```rust use reloop::ReloopClient; #[tokio::main] async fn main() -> Result<(), Box> { let reloop = ReloopClient::new("rl_123456789".to_string(), None); reloop.api_keys().enable("key_123456789").await?; Ok(()) } ``` ## Delete API key `DELETE /api/api-key/v1/:api_key_id` ```rust use reloop::ReloopClient; #[tokio::main] async fn main() -> Result<(), Box> { let reloop = ReloopClient::new("rl_123456789".to_string(), None); reloop.api_keys().delete("key_123456789").await?; Ok(()) } ``` --- # learn/api-keys.mdx Source: https://reloop.sh/docs/learn/api-keys Markdown: https://reloop.sh/docs/learn/api-keys.md ## View all API Keys The [API Keys Dashboard](https://reloop.sh/dashboard/api-keys) shows you all the API Keys you have created along with their details, including the last time you used an API Key. ![API Keys list in the Reloop dashboard](/docs/images/docs/api-keys/list-api-key.png) ## Create an API key 1. Go to [API Keys](https://reloop.sh/dashboard/api-keys) 2. Click **Create API key** (or press `C`) 3. Enter a descriptive name (e.g., `Production Server` or `Staging Worker`) 4. Click **Create API Key** 5. Copy the secret key, then click **Cancel** Copy the secret key immediately upon creation. Reloop stores a secure hash, so the full secret can never be retrieved again after closing the dialog. ## View all API Keys Fetch a paginated list of API keys in your organization. ## Create an API key Use an existing API key to programmatically create new keys for services or team members. Copy the secret key immediately upon creation. Reloop stores a secure hash, so the full secret can never be retrieved again. ## Edit an API key ## Rotate an API key ## Disable or enable an API key ## Delete an API key ## FAQ No. Reloop displays the full secret key string only once when created or rotated. After closing the modal, only the prefix (e.g. `rl_prod_17aQUCC-e`) is visible. Reloop stores a secure hash, so if a secret is lost, you must rotate the key or create a new one. **Disabling** pauses access temporarily — requests using the key fail with `401 Unauthorized`, but you can re-enable it later. **Deleting** permanently removes the key record and cannot be undone. Yes. Reloop API keys work across both REST API endpoints (as the `x-api-key` header) and SMTP authentication (using the API key prefix/secret as SMTP credentials). Reloop does not enforce a hard limit on total API keys per organization. However, we recommend maintaining clean key hygiene by deleting stale or unused keys. ## Related Official Reloop SDK libraries for TypeScript, Python, Go, and more. Use API keys for SMTP email sending. API rate limits and request quotas per organization. ## API reference Generate new API key and secret. Paginated list of organization keys. Rename existing API key. Issue new secret, revoke old. Pause access temporarily. Restore paused access. Permanently delete key. --- # api/api-key/delete-api-api-key-v1by-api_key_id.mdx Source: https://reloop.sh/docs/api/api-key/delete-api-api-key-v1by-api_key_id Markdown: https://reloop.sh/docs/api/api-key/delete-api-api-key-v1by-api_key_id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/api-key/get-api-api-key-v1.mdx Source: https://reloop.sh/docs/api/api-key/get-api-api-key-v1 Markdown: https://reloop.sh/docs/api/api-key/get-api-api-key-v1.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/api-key/get-api-api-key-v1by-api_key_id.mdx Source: https://reloop.sh/docs/api/api-key/get-api-api-key-v1by-api_key_id Markdown: https://reloop.sh/docs/api/api-key/get-api-api-key-v1by-api_key_id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/api-key/patch-api-api-key-v1by-api_key_id.mdx Source: https://reloop.sh/docs/api/api-key/patch-api-api-key-v1by-api_key_id Markdown: https://reloop.sh/docs/api/api-key/patch-api-api-key-v1by-api_key_id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/api-key/post-api-api-key-v1.mdx Source: https://reloop.sh/docs/api/api-key/post-api-api-key-v1 Markdown: https://reloop.sh/docs/api/api-key/post-api-api-key-v1.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/api-key/post-api-api-key-v1disable-by-api_key_id.mdx Source: https://reloop.sh/docs/api/api-key/post-api-api-key-v1disable-by-api_key_id Markdown: https://reloop.sh/docs/api/api-key/post-api-api-key-v1disable-by-api_key_id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/api-key/post-api-api-key-v1enable-by-api_key_id.mdx Source: https://reloop.sh/docs/api/api-key/post-api-api-key-v1enable-by-api_key_id Markdown: https://reloop.sh/docs/api/api-key/post-api-api-key-v1enable-by-api_key_id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/api-key/post-api-api-key-v1rotate-by-api_key_id.mdx Source: https://reloop.sh/docs/api/api-key/post-api-api-key-v1rotate-by-api_key_id Markdown: https://reloop.sh/docs/api/api-key/post-api-api-key-v1rotate-by-api_key_id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/contacts/channels/delete-api-contacts-v1channels-by-channel_id.mdx Source: https://reloop.sh/docs/api/contacts/channels/delete-api-contacts-v1channels-by-channel_id Markdown: https://reloop.sh/docs/api/contacts/channels/delete-api-contacts-v1channels-by-channel_id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/contacts/channels/get-api-contacts-v1channels-by-channel_id.mdx Source: https://reloop.sh/docs/api/contacts/channels/get-api-contacts-v1channels-by-channel_id Markdown: https://reloop.sh/docs/api/contacts/channels/get-api-contacts-v1channels-by-channel_id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/contacts/channels/get-api-contacts-v1channels-list.mdx Source: https://reloop.sh/docs/api/contacts/channels/get-api-contacts-v1channels-list Markdown: https://reloop.sh/docs/api/contacts/channels/get-api-contacts-v1channels-list.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/contacts/channels/patch-api-contacts-v1channels-by-channel_id.mdx Source: https://reloop.sh/docs/api/contacts/channels/patch-api-contacts-v1channels-by-channel_id Markdown: https://reloop.sh/docs/api/contacts/channels/patch-api-contacts-v1channels-by-channel_id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/contacts/channels/post-api-contacts-v1channels-create.mdx Source: https://reloop.sh/docs/api/contacts/channels/post-api-contacts-v1channels-create Markdown: https://reloop.sh/docs/api/contacts/channels/post-api-contacts-v1channels-create.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/contacts/contact-properties/delete-api-contacts-v1properties-by-contact_property_id.mdx Source: https://reloop.sh/docs/api/contacts/contact-properties/delete-api-contacts-v1properties-by-contact_property_id Markdown: https://reloop.sh/docs/api/contacts/contact-properties/delete-api-contacts-v1properties-by-contact_property_id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/contacts/contact-properties/get-api-contacts-v1properties-list.mdx Source: https://reloop.sh/docs/api/contacts/contact-properties/get-api-contacts-v1properties-list Markdown: https://reloop.sh/docs/api/contacts/contact-properties/get-api-contacts-v1properties-list.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/contacts/contact-properties/patch-api-contacts-v1properties-by-contact_property_id.mdx Source: https://reloop.sh/docs/api/contacts/contact-properties/patch-api-contacts-v1properties-by-contact_property_id Markdown: https://reloop.sh/docs/api/contacts/contact-properties/patch-api-contacts-v1properties-by-contact_property_id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/contacts/contact-properties/post-api-contacts-v1properties-create.mdx Source: https://reloop.sh/docs/api/contacts/contact-properties/post-api-contacts-v1properties-create Markdown: https://reloop.sh/docs/api/contacts/contact-properties/post-api-contacts-v1properties-create.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/contacts/delete-api-contacts-by-contact_id.mdx Source: https://reloop.sh/docs/api/contacts/delete-api-contacts-by-contact_id Markdown: https://reloop.sh/docs/api/contacts/delete-api-contacts-by-contact_id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/contacts/delete-api-contacts-group-by-group_id.mdx Source: https://reloop.sh/docs/api/contacts/delete-api-contacts-group-by-group_id Markdown: https://reloop.sh/docs/api/contacts/delete-api-contacts-group-by-group_id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/contacts/get-api-contacts-list.mdx Source: https://reloop.sh/docs/api/contacts/get-api-contacts-list Markdown: https://reloop.sh/docs/api/contacts/get-api-contacts-list.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/contacts/get-api-contacts-retrieve-by-contact_id.mdx Source: https://reloop.sh/docs/api/contacts/get-api-contacts-retrieve-by-contact_id Markdown: https://reloop.sh/docs/api/contacts/get-api-contacts-retrieve-by-contact_id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/contacts/groups/delete-api-contacts-v1groups-by-group_id.mdx Source: https://reloop.sh/docs/api/contacts/groups/delete-api-contacts-v1groups-by-group_id Markdown: https://reloop.sh/docs/api/contacts/groups/delete-api-contacts-v1groups-by-group_id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/contacts/groups/get-api-contacts-v1groups-by-group_id-contacts.mdx Source: https://reloop.sh/docs/api/contacts/groups/get-api-contacts-v1groups-by-group_id-contacts Markdown: https://reloop.sh/docs/api/contacts/groups/get-api-contacts-v1groups-by-group_id-contacts.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/contacts/groups/get-api-contacts-v1groups-by-group_id.mdx Source: https://reloop.sh/docs/api/contacts/groups/get-api-contacts-v1groups-by-group_id Markdown: https://reloop.sh/docs/api/contacts/groups/get-api-contacts-v1groups-by-group_id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/contacts/groups/get-api-contacts-v1groups-list.mdx Source: https://reloop.sh/docs/api/contacts/groups/get-api-contacts-v1groups-list Markdown: https://reloop.sh/docs/api/contacts/groups/get-api-contacts-v1groups-list.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/contacts/groups/patch-api-contacts-v1groups-by-group_id.mdx Source: https://reloop.sh/docs/api/contacts/groups/patch-api-contacts-v1groups-by-group_id Markdown: https://reloop.sh/docs/api/contacts/groups/patch-api-contacts-v1groups-by-group_id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/contacts/groups/post-api-contacts-v1groups-create.mdx Source: https://reloop.sh/docs/api/contacts/groups/post-api-contacts-v1groups-create Markdown: https://reloop.sh/docs/api/contacts/groups/post-api-contacts-v1groups-create.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/contacts/patch-api-contacts-by-contact_id.mdx Source: https://reloop.sh/docs/api/contacts/patch-api-contacts-by-contact_id Markdown: https://reloop.sh/docs/api/contacts/patch-api-contacts-by-contact_id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/contacts/patch-api-contacts-channel-by-channel_id.mdx Source: https://reloop.sh/docs/api/contacts/patch-api-contacts-channel-by-channel_id Markdown: https://reloop.sh/docs/api/contacts/patch-api-contacts-channel-by-channel_id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/contacts/post-api-contacts-channel-by-channel_id.mdx Source: https://reloop.sh/docs/api/contacts/post-api-contacts-channel-by-channel_id Markdown: https://reloop.sh/docs/api/contacts/post-api-contacts-channel-by-channel_id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/contacts/post-api-contacts-create.mdx Source: https://reloop.sh/docs/api/contacts/post-api-contacts-create Markdown: https://reloop.sh/docs/api/contacts/post-api-contacts-create.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/contacts/post-api-contacts-group-by-group_id.mdx Source: https://reloop.sh/docs/api/contacts/post-api-contacts-group-by-group_id Markdown: https://reloop.sh/docs/api/contacts/post-api-contacts-group-by-group_id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/domain/delete-api-domain-v1by-domain_id.mdx Source: https://reloop.sh/docs/api/domain/delete-api-domain-v1by-domain_id Markdown: https://reloop.sh/docs/api/domain/delete-api-domain-v1by-domain_id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/domain/get-api-domain-v1by-domain_id.mdx Source: https://reloop.sh/docs/api/domain/get-api-domain-v1by-domain_id Markdown: https://reloop.sh/docs/api/domain/get-api-domain-v1by-domain_id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/domain/get-api-domain-v1list.mdx Source: https://reloop.sh/docs/api/domain/get-api-domain-v1list Markdown: https://reloop.sh/docs/api/domain/get-api-domain-v1list.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/domain/get-api-domain-v1nameservers-by-domain_id.mdx Source: https://reloop.sh/docs/api/domain/get-api-domain-v1nameservers-by-domain_id Markdown: https://reloop.sh/docs/api/domain/get-api-domain-v1nameservers-by-domain_id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/domain/patch-api-domain-v1by-domain_id.mdx Source: https://reloop.sh/docs/api/domain/patch-api-domain-v1by-domain_id Markdown: https://reloop.sh/docs/api/domain/patch-api-domain-v1by-domain_id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/domain/post-api-domain-v1create.mdx Source: https://reloop.sh/docs/api/domain/post-api-domain-v1create Markdown: https://reloop.sh/docs/api/domain/post-api-domain-v1create.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/domain/post-api-domain-v1verify-by-domain_id-forward-dns.mdx Source: https://reloop.sh/docs/api/domain/post-api-domain-v1verify-by-domain_id-forward-dns Markdown: https://reloop.sh/docs/api/domain/post-api-domain-v1verify-by-domain_id-forward-dns.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/domain/post-api-domain-v1verify-by-domain_id.mdx Source: https://reloop.sh/docs/api/domain/post-api-domain-v1verify-by-domain_id Markdown: https://reloop.sh/docs/api/domain/post-api-domain-v1verify-by-domain_id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/errors.mdx Source: https://reloop.sh/docs/api/errors Markdown: https://reloop.sh/docs/api/errors.md Reloop uses standard HTTP response codes to indicate the success or failure of an API request. Every error response includes structured fields so you can programmatically handle failures without parsing human-readable messages. ## Error Response Format All error responses return a JSON object with four fields: ```json { "message": "Invalid sender address", "why": "The address 'not-an-email' is not a valid email format", "fix": "Provide a valid email address in the 'from' field (e.g., user@example.com)", "link": "https://reloop.sh/docs/api/errors" } ``` | Field | Type | Description | |-------|------|-------------| | `message` | `string` | A short summary of what went wrong (e.g., `"Domain not found"`). | | `why` | `string` | A detailed explanation of what triggered the error, often including the offending value. | | `fix` | `string` | Actionable steps to resolve the issue. | | `link` | `string` | A URL to the relevant documentation page. | ## Error Codes Reference ### 400 — Bad Request The request was invalid. This usually means a required parameter is missing, a value is the wrong type, or an input failed validation. **Common causes:** - Missing required fields in the request body. - A DNS health check failed because records are not configured correctly. - An email body was missing both `html` and `text` content, and the referenced template had no rendered HTML. ```json { "message": "DNS health check failed", "why": "Domain acme.com is missing required DNS records: SPF, DKIM", "fix": "Update your DNS configuration with the required SPF, DKIM, and DMARC records" } ``` --- ### 401 — Unauthorized The API key is missing, invalid, or has been revoked. **Common causes:** - The `x-api-key` header was not included in the request. - The API key has been disabled or rotated. - The key format is incorrect (valid keys start with `rl_prod_`). ```json { "message": "Unauthorized", "why": "No valid API key was provided in the x-api-key header", "fix": "Please provide valid credentials" } ``` --- ### 403 — Forbidden The API key is valid, but it doesn't have permission to access the requested resource. **Common causes:** - Attempting to access a resource that belongs to a different organization. - The authenticated user is not a member of the organization tied to the API key. ```json { "message": "Forbidden", "why": "User is not a member of an organization", "fix": "Ensure your API key is associated with the correct organization" } ``` --- ### 404 — Not Found The requested resource doesn't exist or isn't accessible to your organization. **Common causes:** - The resource ID is incorrect or was deleted. - The resource belongs to a different organization than your API key. ```json { "message": "Domain not found", "why": "The domain acme.com was not found or is not authorized for your organization", "fix": "Ensure the domain is registered and verified in your dashboard" } ``` --- ### 409 — Conflict The request conflicts with an existing resource. **Common causes:** - Creating a domain that is already registered. - Creating a channel or contact property with a name that already exists in your organization. ```json { "message": "Channel already exists", "why": "A channel with the name 'Weekly Newsletter' already exists in your organization", "fix": "Use a unique channel name or update the existing channel" } ``` --- ### 429 — Too Many Requests You've exceeded a rate limit. The response includes additional fields and headers to help you retry. ```json { "message": "Too many requests", "why": "You have exceeded the limit of 10 requests per 60s window for this operation.", "fix": "Wait 42 second(s) before retrying.", "retryAfter": 42 } ``` Check the `Retry-After` response header for the number of seconds to wait, or use the `retryAfter` field in the body. See [Usage Limits](/docs/api/usage-limits) for per-endpoint limits. --- ### 500 — Internal Server Error Something went wrong on Reloop's end. These errors are automatically logged and investigated. **What to do:** - Retry the request after a short delay. - If the issue persists, contact [support@reloop.sh](mailto:support@reloop.sh) with the request details and timestamp. --- # api/inbox/mailboxes/delete-api-inbox-v1mailboxes-by-id.mdx Source: https://reloop.sh/docs/api/inbox/mailboxes/delete-api-inbox-v1mailboxes-by-id Markdown: https://reloop.sh/docs/api/inbox/mailboxes/delete-api-inbox-v1mailboxes-by-id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/inbox/mailboxes/get-api-inbox-v1mailboxes-by-id.mdx Source: https://reloop.sh/docs/api/inbox/mailboxes/get-api-inbox-v1mailboxes-by-id Markdown: https://reloop.sh/docs/api/inbox/mailboxes/get-api-inbox-v1mailboxes-by-id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/inbox/mailboxes/get-api-inbox-v1mailboxes-list.mdx Source: https://reloop.sh/docs/api/inbox/mailboxes/get-api-inbox-v1mailboxes-list Markdown: https://reloop.sh/docs/api/inbox/mailboxes/get-api-inbox-v1mailboxes-list.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/inbox/mailboxes/patch-api-inbox-v1mailboxes-by-id.mdx Source: https://reloop.sh/docs/api/inbox/mailboxes/patch-api-inbox-v1mailboxes-by-id Markdown: https://reloop.sh/docs/api/inbox/mailboxes/patch-api-inbox-v1mailboxes-by-id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/inbox/mailboxes/post-api-inbox-v1mailboxes-create.mdx Source: https://reloop.sh/docs/api/inbox/mailboxes/post-api-inbox-v1mailboxes-create Markdown: https://reloop.sh/docs/api/inbox/mailboxes/post-api-inbox-v1mailboxes-create.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/inbox/messages/delete-api-inbox-v1messages-by-id.mdx Source: https://reloop.sh/docs/api/inbox/messages/delete-api-inbox-v1messages-by-id Markdown: https://reloop.sh/docs/api/inbox/messages/delete-api-inbox-v1messages-by-id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/inbox/messages/get-api-inbox-v1messages-by-id-attachments-by-attachment-id.mdx Source: https://reloop.sh/docs/api/inbox/messages/get-api-inbox-v1messages-by-id-attachments-by-attachment-id Markdown: https://reloop.sh/docs/api/inbox/messages/get-api-inbox-v1messages-by-id-attachments-by-attachment-id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/inbox/messages/get-api-inbox-v1messages-by-id-raw.mdx Source: https://reloop.sh/docs/api/inbox/messages/get-api-inbox-v1messages-by-id-raw Markdown: https://reloop.sh/docs/api/inbox/messages/get-api-inbox-v1messages-by-id-raw.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/inbox/messages/get-api-inbox-v1messages-by-id.mdx Source: https://reloop.sh/docs/api/inbox/messages/get-api-inbox-v1messages-by-id Markdown: https://reloop.sh/docs/api/inbox/messages/get-api-inbox-v1messages-by-id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/inbox/messages/get-api-inbox-v1messages.mdx Source: https://reloop.sh/docs/api/inbox/messages/get-api-inbox-v1messages Markdown: https://reloop.sh/docs/api/inbox/messages/get-api-inbox-v1messages.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/inbox/messages/patch-api-inbox-v1messages-by-id-read.mdx Source: https://reloop.sh/docs/api/inbox/messages/patch-api-inbox-v1messages-by-id-read Markdown: https://reloop.sh/docs/api/inbox/messages/patch-api-inbox-v1messages-by-id-read.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/inbox/messages/patch-api-inbox-v1messages-by-id-star.mdx Source: https://reloop.sh/docs/api/inbox/messages/patch-api-inbox-v1messages-by-id-star Markdown: https://reloop.sh/docs/api/inbox/messages/patch-api-inbox-v1messages-by-id-star.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/inbox/messages/patch-api-inbox-v1messages-by-id.mdx Source: https://reloop.sh/docs/api/inbox/messages/patch-api-inbox-v1messages-by-id Markdown: https://reloop.sh/docs/api/inbox/messages/patch-api-inbox-v1messages-by-id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/inbox/messages/post-api-inbox-v1messages-batch.mdx Source: https://reloop.sh/docs/api/inbox/messages/post-api-inbox-v1messages-batch Markdown: https://reloop.sh/docs/api/inbox/messages/post-api-inbox-v1messages-batch.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/inbox/messages/post-api-inbox-v1messages-by-id-forward.mdx Source: https://reloop.sh/docs/api/inbox/messages/post-api-inbox-v1messages-by-id-forward Markdown: https://reloop.sh/docs/api/inbox/messages/post-api-inbox-v1messages-by-id-forward.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/inbox/messages/post-api-inbox-v1messages-by-id-reply-all.mdx Source: https://reloop.sh/docs/api/inbox/messages/post-api-inbox-v1messages-by-id-reply-all Markdown: https://reloop.sh/docs/api/inbox/messages/post-api-inbox-v1messages-by-id-reply-all.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/inbox/messages/post-api-inbox-v1messages-by-id-reply.mdx Source: https://reloop.sh/docs/api/inbox/messages/post-api-inbox-v1messages-by-id-reply Markdown: https://reloop.sh/docs/api/inbox/messages/post-api-inbox-v1messages-by-id-reply.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/inbox/messages/post-api-inbox-v1messages-send.mdx Source: https://reloop.sh/docs/api/inbox/messages/post-api-inbox-v1messages-send Markdown: https://reloop.sh/docs/api/inbox/messages/post-api-inbox-v1messages-send.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/inbox/threads/delete-api-inbox-v1threads-by-id.mdx Source: https://reloop.sh/docs/api/inbox/threads/delete-api-inbox-v1threads-by-id Markdown: https://reloop.sh/docs/api/inbox/threads/delete-api-inbox-v1threads-by-id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/inbox/threads/get-api-inbox-v1threads-by-id-attachments-by-attachment-id.mdx Source: https://reloop.sh/docs/api/inbox/threads/get-api-inbox-v1threads-by-id-attachments-by-attachment-id Markdown: https://reloop.sh/docs/api/inbox/threads/get-api-inbox-v1threads-by-id-attachments-by-attachment-id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/inbox/threads/get-api-inbox-v1threads-by-id.mdx Source: https://reloop.sh/docs/api/inbox/threads/get-api-inbox-v1threads-by-id Markdown: https://reloop.sh/docs/api/inbox/threads/get-api-inbox-v1threads-by-id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/inbox/threads/get-api-inbox-v1threads.mdx Source: https://reloop.sh/docs/api/inbox/threads/get-api-inbox-v1threads Markdown: https://reloop.sh/docs/api/inbox/threads/get-api-inbox-v1threads.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/inbox/threads/patch-api-inbox-v1threads-by-id-read.mdx Source: https://reloop.sh/docs/api/inbox/threads/patch-api-inbox-v1threads-by-id-read Markdown: https://reloop.sh/docs/api/inbox/threads/patch-api-inbox-v1threads-by-id-read.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/inbox/threads/patch-api-inbox-v1threads-by-id-star.mdx Source: https://reloop.sh/docs/api/inbox/threads/patch-api-inbox-v1threads-by-id-star Markdown: https://reloop.sh/docs/api/inbox/threads/patch-api-inbox-v1threads-by-id-star.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/inbox/threads/patch-api-inbox-v1threads-by-id.mdx Source: https://reloop.sh/docs/api/inbox/threads/patch-api-inbox-v1threads-by-id Markdown: https://reloop.sh/docs/api/inbox/threads/patch-api-inbox-v1threads-by-id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/inbox/threads/post-api-inbox-v1threads-by-id-archive.mdx Source: https://reloop.sh/docs/api/inbox/threads/post-api-inbox-v1threads-by-id-archive Markdown: https://reloop.sh/docs/api/inbox/threads/post-api-inbox-v1threads-by-id-archive.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/index.mdx Source: https://reloop.sh/docs/api Markdown: https://reloop.sh/docs/api.md Welcome to the Reloop API Reference. The Reloop API is built on **REST** principles. We enforce HTTPS in every request to improve data security, integrity, and privacy. ## Authentication Every request must include your API key in the `x-api-key` header. API keys are scoped to a single **organization** — all resources you create, read, or modify are automatically associated with that organization. ```bash curl -X GET "https://reloop.sh/api/domain/v1/list" \ -H "x-api-key: rl_prod_YOUR_API_KEY" ``` You can create, rotate, and revoke API keys from the [Reloop Dashboard](https://reloop.sh/dashboard/api-keys). ### Required Headers | Header | Value | When | |--------|-------|------| | `x-api-key` | Your Reloop API key (prefixed `rl_prod_`) | Every request | | `Content-Type` | `application/json` | Requests with a body (`POST`, `PUT`, `PATCH`) | ## Response Format All responses — including errors — are returned as JSON. Successful responses typically include an `event` field describing the action performed: ```json { "event": "contact.created", ... } ``` ## Response Codes The API uses standard HTTP status codes to indicate the outcome of a request: | Code | Meaning | When You'll See It | |------|---------|-------------------| | `200` | OK | Request succeeded. | | `201` | Created | A new resource was created successfully. | | `400` | Bad Request | Missing or invalid parameters — check the `why` field for details. | | `401` | Unauthorized | The `x-api-key` header is missing, invalid, or the key has been revoked. | | `403` | Forbidden | The API key doesn't have permission to access the requested resource. | | `404` | Not Found | The resource doesn't exist, or it belongs to a different organization. | | `409` | Conflict | A resource with the same unique identifier already exists (e.g., duplicate domain or channel name). | | `429` | Too Many Requests | You've exceeded a [rate limit](/docs/api/usage-limits). Retry after the `Retry-After` header value. | | `500` | Internal Server Error | Something went wrong on our end. If the issue persists, contact [support](mailto:support@reloop.sh). | ## Errors When a request fails, the response body always contains four fields to help you diagnose and fix the issue: ```json { "message": "Domain not found", "why": "The domain acme.com was not found or is not authorized for your organization", "fix": "Ensure the domain is registered and verified in your dashboard", "link": "https://reloop.sh/docs/api/errors" } ``` | Field | Description | |-------|-------------| | `message` | A short, human-readable summary of the error. | | `why` | A detailed explanation of what went wrong and what triggered the error. | | `fix` | Actionable steps you can take to resolve the issue. | | `link` | A URL to the relevant documentation page for more context. | See the [Errors](/docs/api/errors) page for a full reference of common error codes and troubleshooting tips. ## Rate Limits Rate limits are applied per **organization** and vary by endpoint. Every API response includes headers so you can monitor your usage: | Header | Description | |--------|-------------| | `X-RateLimit-Limit` | Maximum requests allowed in the current window. | | `X-RateLimit-Remaining` | Requests remaining before the limit is reached. | | `X-RateLimit-Window` | Window size in seconds (management endpoints like domains, contacts, and channels). | | `X-RateLimit-Reset` | Unix epoch timestamp when the window resets (email sending endpoints). | | `Retry-After` | Seconds to wait before retrying (only returned with `429` responses). | For the full breakdown of per-endpoint limits and the multi-layer email sending strategy, see [Usage Limits](/docs/api/usage-limits). --- # api/logs/get-api-logs-v1by-log_id.mdx Source: https://reloop.sh/docs/api/logs/get-api-logs-v1by-log_id Markdown: https://reloop.sh/docs/api/logs/get-api-logs-v1by-log_id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/logs/get-api-logs-v1emails-by-id.mdx Source: https://reloop.sh/docs/api/logs/get-api-logs-v1emails-by-id Markdown: https://reloop.sh/docs/api/logs/get-api-logs-v1emails-by-id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/logs/get-api-logs-v1emails-contact-activity.mdx Source: https://reloop.sh/docs/api/logs/get-api-logs-v1emails-contact-activity Markdown: https://reloop.sh/docs/api/logs/get-api-logs-v1emails-contact-activity.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/logs/get-api-logs-v1emails-stats.mdx Source: https://reloop.sh/docs/api/logs/get-api-logs-v1emails-stats Markdown: https://reloop.sh/docs/api/logs/get-api-logs-v1emails-stats.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/logs/get-api-logs-v1emails.mdx Source: https://reloop.sh/docs/api/logs/get-api-logs-v1emails Markdown: https://reloop.sh/docs/api/logs/get-api-logs-v1emails.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/logs/get-api-logs-v1list.mdx Source: https://reloop.sh/docs/api/logs/get-api-logs-v1list Markdown: https://reloop.sh/docs/api/logs/get-api-logs-v1list.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/mail/post-api-mail-v1send.mdx Source: https://reloop.sh/docs/api/mail/post-api-mail-v1send Markdown: https://reloop.sh/docs/api/mail/post-api-mail-v1send.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/pagination.mdx Source: https://reloop.sh/docs/api/pagination Markdown: https://reloop.sh/docs/api/pagination.md All list endpoints in the Reloop API use **offset-based pagination**. You control the page size and page number using query parameters, and the response includes metadata so you can calculate total pages and build navigation. ## Query Parameters | Parameter | Type | Default | Max | Description | |-----------|------|---------|-----|-------------| | `page` | `number` | `1` | — | The page number to retrieve (1-indexed). | | `limit` | `number` | `20` | `100` | The number of records to return per page. | **Example request:** ```bash curl "https://reloop.sh/api/contacts/v1/list?page=2&limit=50" \ -H "x-api-key: rl_prod_YOUR_API_KEY" ``` ## Response Structure Pagination metadata is returned at the **root** of the JSON response alongside the data array. The exact field names vary by endpoint, but every paginated response includes `total`, `page`, and `limit`. ### Contacts The contacts list endpoint includes additional aggregate counts: ```json { "object": "contact", "contacts": [...], "total": 120, "page": 1, "limit": 20, "totalContacts": 120, "subscribedContacts": 100, "unsubscribedContacts": 20, "event": "contact.list" } ``` | Field | Type | Description | |-------|------|-------------| | `contacts` | `array` | The list of contact objects for the current page. | | `total` | `number` | Total number of contacts matching the query. | | `page` | `number` | The current page number. | | `limit` | `number` | The page size used for this request. | | `totalContacts` | `number` | Total contacts in the organization. | | `subscribedContacts` | `number` | Number of contacts with an active subscription. | | `unsubscribedContacts` | `number` | Number of contacts who have unsubscribed. | ### Templates ```json { "templates": [...], "total": 45, "page": 1, "limit": 20, "event": "template.list" } ``` | Field | Type | Description | |-------|------|-------------| | `templates` | `array` | The list of template objects for the current page. | | `total` | `number` | Total number of templates matching the query. | | `page` | `number` | The current page number. | | `limit` | `number` | The page size used for this request. | ## Calculating Total Pages Use the `total` and `limit` fields to calculate the number of pages: ```javascript const totalPages = Math.ceil(response.total / response.limit); const hasNextPage = response.page < totalPages; ``` --- # api/template/delete-api-template-v1by-id-versions-by-version-id.mdx Source: https://reloop.sh/docs/api/template/delete-api-template-v1by-id-versions-by-version-id Markdown: https://reloop.sh/docs/api/template/delete-api-template-v1by-id-versions-by-version-id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/template/delete-api-template-v1by-id.mdx Source: https://reloop.sh/docs/api/template/delete-api-template-v1by-id Markdown: https://reloop.sh/docs/api/template/delete-api-template-v1by-id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/template/get-api-template-v1by-id-versions.mdx Source: https://reloop.sh/docs/api/template/get-api-template-v1by-id-versions Markdown: https://reloop.sh/docs/api/template/get-api-template-v1by-id-versions.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/template/get-api-template-v1by-id.mdx Source: https://reloop.sh/docs/api/template/get-api-template-v1by-id Markdown: https://reloop.sh/docs/api/template/get-api-template-v1by-id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/template/get-api-template-v1list.mdx Source: https://reloop.sh/docs/api/template/get-api-template-v1list Markdown: https://reloop.sh/docs/api/template/get-api-template-v1list.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/template/post-api-template-v1by-id-duplicate.mdx Source: https://reloop.sh/docs/api/template/post-api-template-v1by-id-duplicate Markdown: https://reloop.sh/docs/api/template/post-api-template-v1by-id-duplicate.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/template/post-api-template-v1by-id-test.mdx Source: https://reloop.sh/docs/api/template/post-api-template-v1by-id-test Markdown: https://reloop.sh/docs/api/template/post-api-template-v1by-id-test.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/template/post-api-template-v1by-id-versions-by-version-id-restore.mdx Source: https://reloop.sh/docs/api/template/post-api-template-v1by-id-versions-by-version-id-restore Markdown: https://reloop.sh/docs/api/template/post-api-template-v1by-id-versions-by-version-id-restore.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/template/post-api-template-v1by-id-versions.mdx Source: https://reloop.sh/docs/api/template/post-api-template-v1by-id-versions Markdown: https://reloop.sh/docs/api/template/post-api-template-v1by-id-versions.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/template/post-api-template-v1create.mdx Source: https://reloop.sh/docs/api/template/post-api-template-v1create Markdown: https://reloop.sh/docs/api/template/post-api-template-v1create.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/template/put-api-template-v1by-id.mdx Source: https://reloop.sh/docs/api/template/put-api-template-v1by-id Markdown: https://reloop.sh/docs/api/template/put-api-template-v1by-id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/upload/delete-api-upload-v1files-by-file-id.mdx Source: https://reloop.sh/docs/api/upload/delete-api-upload-v1files-by-file-id Markdown: https://reloop.sh/docs/api/upload/delete-api-upload-v1files-by-file-id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/upload/post-api-upload-v1upload.mdx Source: https://reloop.sh/docs/api/upload/post-api-upload-v1upload Markdown: https://reloop.sh/docs/api/upload/post-api-upload-v1upload.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/usage-limits.mdx Source: https://reloop.sh/docs/api/usage-limits Markdown: https://reloop.sh/docs/api/usage-limits.md Reloop enforces rate limits on API requests to ensure stability and fair usage across all organizations. Limits are applied per **organization** and tracked using a sliding window counter backed by Redis. If a limit is exceeded, the API returns a `429 Too Many Requests` response with a `Retry-After` header indicating how many seconds to wait. ## Management Endpoint Limits Management endpoints cover everything outside of email sending — domains, contacts, channels, groups, properties, API keys, and templates. Each endpoint category has its own independent limit. ### Domain Service | Operation | Limit | Window | |-----------|-------|--------| | Create Domain | 10 requests | 60s | | Update Domain | 10 requests | 60s | | Delete Domain | 10 requests | 60s | | Verify DNS | 10 requests | 60s | ### Contacts Service | Operation | Limit | Window | |-----------|-------|--------| | List Contacts | 60 requests | 60s | | Get Contact | 60 requests | 60s | | Create Contact | 200 requests | 60s | | Update Contact | 30 requests | 60s | | Delete Contact | 30 requests | 60s | ### Channels Service | Operation | Limit | Window | |-----------|-------|--------| | List Channels | 60 requests | 60s | | Get Channel | 60 requests | 60s | | Create Channel | 30 requests | 60s | | Update Channel | 30 requests | 60s | | Delete Channel | 30 requests | 60s | ### Groups Service | Operation | Limit | Window | |-----------|-------|--------| | List Groups | 60 requests | 60s | | Get Group | 60 requests | 60s | | Create Group | 30 requests | 60s | | Update Group | 30 requests | 60s | | Delete Group | 30 requests | 60s | | Add Contact to Group | 30 requests | 60s | | Remove Contact from Group | 30 requests | 60s | ### Contact Properties Service | Operation | Limit | Window | |-----------|-------|--------| | List Properties | 60 requests | 60s | | Create Property | 30 requests | 60s | | Update Property | 30 requests | 60s | | Delete Property | 30 requests | 60s | ### API Keys Service | Operation | Limit | Window | |-----------|-------|--------| | Create API Key | 10 requests | 60s | | Update API Key | 30 requests | 60s | | Delete API Key | 20 requests | 60s | | Rotate API Key | 20 requests | 60s | | Enable / Disable API Key | 30 requests | 60s | ### Preferences Service | Operation | Limit | Window | |-----------|-------|--------| | Generate Token | 30 requests | 60s | | Update Preference | 30 requests | 60s | --- ## Email Sending Limits The email sending endpoint (`/api/mail/v1/send`) uses a **multi-layer** rate limiting strategy. All five layers are checked in parallel — if any single layer is exceeded, the request is rejected. | Layer | Limit | Window | What It Protects | |-------|-------|--------|-----------------| | IP | 20 requests | 60s | Prevents brute-force from a single source. | | User | 50 requests | 60s | Stops abuse from a single user within an organization. | | Organization | 100 requests | 60s | Prevents runaway integrations per tenant. | | Organization Daily | 5,000 requests | 24h | Hard daily cap per organization. | | Global | 500 requests | 60s | Protects infrastructure from DDoS. | When a sending request is rate limited, the error response tells you which layer was exceeded: ```json { "message": "Too Many Requests", "why": "Rate limit exceeded on the organization layer. You have sent too many requests in the current time window.", "fix": "Please wait 42 seconds before retrying, or contact support to increase your limits." } ``` --- ## Rate Limit Headers Every API response includes headers indicating your current rate limit status. The specific headers vary slightly between management and sending endpoints. ### Management Endpoints | Header | Description | Example | |--------|-------------|---------| | `X-RateLimit-Limit` | Maximum requests allowed in the window. | `60` | | `X-RateLimit-Remaining` | Requests remaining in the current window. | `48` | | `X-RateLimit-Window` | Window size in seconds. | `60` | | `Retry-After` | Seconds to wait before retrying (only on `429`). | `12` | ### Email Sending Endpoints | Header | Description | Example | |--------|-------------|---------| | `X-RateLimit-Limit` | Maximum requests for the tightest active layer. | `100` | | `X-RateLimit-Remaining` | Requests remaining for the tightest active layer. | `73` | | `X-RateLimit-Reset` | Unix epoch timestamp (seconds) when the window resets. | `1718284800` | | `Retry-After` | Seconds to wait before retrying (only on `429`). | `42` | --- ## Best Practices - **Monitor headers proactively.** Check `X-RateLimit-Remaining` before it reaches zero to avoid disruptions. - **Implement exponential backoff.** When you receive a `429`, wait for the duration specified in `Retry-After`, then retry with increasing delays if the limit is still exceeded. - **Batch where possible.** Use list endpoints with pagination instead of fetching resources one at a time. - **Separate read and write traffic.** Read operations (list, get) generally have higher limits than write operations (create, update, delete). --- # api/webhook/delete-api-webhook-v1by-id.mdx Source: https://reloop.sh/docs/api/webhook/delete-api-webhook-v1by-id Markdown: https://reloop.sh/docs/api/webhook/delete-api-webhook-v1by-id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/webhook/get-api-webhook-v1.mdx Source: https://reloop.sh/docs/api/webhook/get-api-webhook-v1 Markdown: https://reloop.sh/docs/api/webhook/get-api-webhook-v1.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/webhook/get-api-webhook-v1by-webhook_id-deliveries.mdx Source: https://reloop.sh/docs/api/webhook/get-api-webhook-v1by-webhook_id-deliveries Markdown: https://reloop.sh/docs/api/webhook/get-api-webhook-v1by-webhook_id-deliveries.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/webhook/get-api-webhook-v1by-webhook_id.mdx Source: https://reloop.sh/docs/api/webhook/get-api-webhook-v1by-webhook_id Markdown: https://reloop.sh/docs/api/webhook/get-api-webhook-v1by-webhook_id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/webhook/patch-api-webhook-v1by-webhook_id.mdx Source: https://reloop.sh/docs/api/webhook/patch-api-webhook-v1by-webhook_id Markdown: https://reloop.sh/docs/api/webhook/patch-api-webhook-v1by-webhook_id.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/webhook/post-api-webhook-deliveries-by-delivery_id-retry.mdx Source: https://reloop.sh/docs/api/webhook/post-api-webhook-deliveries-by-delivery_id-retry Markdown: https://reloop.sh/docs/api/webhook/post-api-webhook-deliveries-by-delivery_id-retry.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/webhook/post-api-webhook-v1.mdx Source: https://reloop.sh/docs/api/webhook/post-api-webhook-v1 Markdown: https://reloop.sh/docs/api/webhook/post-api-webhook-v1.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # api/webhook/post-api-webhook-v1trigger.mdx Source: https://reloop.sh/docs/api/webhook/post-api-webhook-v1trigger Markdown: https://reloop.sh/docs/api/webhook/post-api-webhook-v1trigger.md {/* This file was generated by the OpenAPI doc generator. Do not edit this file directly. Run `bun run generate:api-docs` to regenerate. */} --- # webhooks/contacts/created.mdx Source: https://reloop.sh/docs/webhooks/contacts/created Markdown: https://reloop.sh/docs/webhooks/contacts/created.md The `contact.create` event is triggered when a new contact is added (via API or auto-capture from sends). ## Event Details All webhook payloads follow a consistent top-level structure with event-specific data nested within the `data` object. ### type `string` The event type that triggered the webhook (`contact.create`). ### created_at `string` ISO 8601 timestamp when the webhook event was created. ### data `object` Contact identity and status fields (`id`, `email`, `first_name`, `last_name`, `status`). ## Handling this event When your endpoint receives a `contact.create` event, you might want to: - Sync the contact with your primary database. - Trigger a welcome email sequence. - Tag the contact in your CRM. ```json { "id": "whev_01h…", "type": "contact.create", "created_at": "2026-07-22T12:00:00.000Z", "data": { "id": "con_123456789", "email": "contact@example.com", "first_name": "Ada", "last_name": "Lovelace", "status": "subscribed" } } ``` ## Learn More - [Webhooks Introduction](/docs/webhooks) - [All Event Types](/docs/webhooks/event-types) --- # webhooks/contacts/deleted.mdx Source: https://reloop.sh/docs/webhooks/contacts/deleted Markdown: https://reloop.sh/docs/webhooks/contacts/deleted.md The `contact.delete` event is triggered when a contact is permanently removed. ## Event Details All webhook payloads follow a consistent top-level structure with event-specific data nested within the `data` object. ### type `string` The event type that triggered the webhook (`contact.delete`). ### created_at `string` ISO 8601 timestamp when the webhook event was created. ### data `object` The deleted contact identity and last known fields. ## Handling this event When your endpoint receives a `contact.delete` event, you might want to: - Purge the contact from your local cache or database. - Stop any active communication threads. - Update your audience metrics. ```json { "id": "whev_01h…", "type": "contact.delete", "created_at": "2026-07-22T12:00:00.000Z", "data": { "id": "con_123456789", "email": "contact@example.com", "first_name": null, "last_name": null, "status": "subscribed" } } ``` ## Learn More - [Webhooks Introduction](/docs/webhooks) - [All Event Types](/docs/webhooks/event-types) --- # webhooks/contacts/updated.mdx Source: https://reloop.sh/docs/webhooks/contacts/updated Markdown: https://reloop.sh/docs/webhooks/contacts/updated.md The `contact.update` event is triggered when a contact's details change. Status-only transitions also emit dedicated events (`contact.subscribed`, `contact.unsubscribed`, `contact.blocked`). ## Event Details All webhook payloads follow a consistent top-level structure with event-specific data nested within the `data` object. ### type `string` The event type that triggered the webhook (`contact.update`). ### created_at `string` ISO 8601 timestamp when the webhook event was created. ### data `object` Updated contact fields (`id`, `email`, `first_name`, `last_name`, `status`). ## Handling this event When your endpoint receives a `contact.update` event, you might want to: - Update the contact's record in your system. - Synchronize subscription preferences. - Log the change for audit purposes. ```json { "id": "whev_01h…", "type": "contact.update", "created_at": "2026-07-22T12:00:00.000Z", "data": { "id": "con_123456789", "email": "contact@example.com", "first_name": "Ada", "last_name": "Lovelace", "status": "unsubscribed" } } ``` ## Learn More - [Webhooks Introduction](/docs/webhooks) - [All Event Types](/docs/webhooks/event-types) --- # webhooks/domains/created.mdx Source: https://reloop.sh/docs/webhooks/domains/created Markdown: https://reloop.sh/docs/webhooks/domains/created.md The `domain.create` event is triggered when a new domain is successfully added to your Reloop account. ## Event Details All webhook payloads follow a consistent top-level structure with event-specific data nested within the `data` object. ### type `string` The event type that triggered the webhook (`domain.create`). ### created_at `string` ISO 8601 timestamp when the webhook event was created. ### data `object` Contains the details of the newly created domain (`id`, `name`, `status`). ## Handling this event When your endpoint receives a `domain.create` event, you might want to: - Sync the domain status with your internal system. - Trigger DNS verification workflows. - Log the activity for auditing. ```json { "id": "whev_01h…", "type": "domain.create", "created_at": "2026-07-22T12:00:00.000Z", "data": { "id": "dom_123456789", "name": "example.com", "status": "pending" } } ``` ## Learn More - [Webhooks Introduction](/docs/webhooks) - [All Event Types](/docs/webhooks/event-types) --- # webhooks/domains/deleted.mdx Source: https://reloop.sh/docs/webhooks/domains/deleted Markdown: https://reloop.sh/docs/webhooks/domains/deleted.md The `domain.delete` event is triggered when a domain is removed from your organization. ## Event Details All webhook payloads follow a consistent top-level structure with event-specific data nested within the `data` object. ### type `string` The event type that triggered the webhook (`domain.delete`). ### created_at `string` ISO 8601 timestamp when the webhook event was created. ### data `object` Contains the deleted domain identity (`id`, `name`, `status`). ## Handling this event When your endpoint receives a `domain.delete` event, you might want to: - Stop sending from that domain in your application. - Remove DNS setup reminders. - Clean up local domain caches. ```json { "id": "whev_01h…", "type": "domain.delete", "created_at": "2026-07-22T12:00:00.000Z", "data": { "id": "dom_123456789", "name": "example.com", "status": "pending" } } ``` ## Learn More - [Webhooks Introduction](/docs/webhooks) - [All Event Types](/docs/webhooks/event-types) --- # webhooks/domains/updated.mdx Source: https://reloop.sh/docs/webhooks/domains/updated Markdown: https://reloop.sh/docs/webhooks/domains/updated.md The `domain.update` event is triggered when a domain's settings change (tracking, TLS, send/receive flags, etc.). ## Event Details All webhook payloads follow a consistent top-level structure with event-specific data nested within the `data` object. ### type `string` The event type that triggered the webhook (`domain.update`). ### created_at `string` ISO 8601 timestamp when the webhook event was created. ### data `object` Contains the updated domain identity and status (`id`, `name`, `status`). ## Handling this event When your endpoint receives a `domain.update` event, you might want to: - Refresh cached domain configuration. - Re-run internal validation against the new settings. ```json { "id": "whev_01h…", "type": "domain.update", "created_at": "2026-07-22T12:00:00.000Z", "data": { "id": "dom_123456789", "name": "example.com", "status": "active" } } ``` ## Learn More - [Webhooks Introduction](/docs/webhooks) - [All Event Types](/docs/webhooks/event-types) --- # webhooks/emails/bounced.mdx Source: https://reloop.sh/docs/webhooks/emails/bounced Markdown: https://reloop.sh/docs/webhooks/emails/bounced.md The `email.bounced` event is triggered when delivery permanently fails (hard bounce, admin bounce, or OOB). ## Event Details All webhook payloads follow a consistent top-level structure with event-specific data nested within the `data` object. ### type `string` The event type that triggered the webhook (`email.bounced`). ### created_at `string` ISO 8601 timestamp when the webhook event was created. ### data `object` Includes standard email fields plus `error` with SMTP details when available. ## Handling this event When your endpoint receives an `email.bounced` event, you might want to: - Suppress the recipient from future sends. - Notify the sender or update CRM status. ```json { "id": "whev_01h…", "type": "email.bounced", "created_at": "2026-07-22T12:00:00.000Z", "data": { "email_id": "em_123456789", "from": "sender@example.com", "to": ["bad@example.com"], "subject": "Hello World", "status": "bounced", "error": { "code": 550, "message": "User unknown" } } } ``` ## Learn More - [Webhooks Introduction](/docs/webhooks) - [All Event Types](/docs/webhooks/event-types) --- # webhooks/emails/clicked.mdx Source: https://reloop.sh/docs/webhooks/emails/clicked Markdown: https://reloop.sh/docs/webhooks/emails/clicked.md The `email.clicked` event is triggered when click tracking records a link click. ## Event Details All webhook payloads follow a consistent top-level structure with event-specific data nested within the `data` object. ### type `string` The event type that triggered the webhook (`email.clicked`). ### created_at `string` ISO 8601 timestamp when the webhook event was created. ### data `object` Standard outbound email fields plus `url` for the clicked destination. ## Handling this event When your endpoint receives an `email.clicked` event, you might want to: - Track link engagement. - Personalize follow-up based on which URL was clicked. ```json { "id": "whev_01h…", "type": "email.clicked", "created_at": "2026-07-22T12:00:00.000Z", "data": { "email_id": "em_123456789", "from": "sender@example.com", "to": ["recipient@example.com"], "subject": "Hello World", "status": "delivered", "url": "https://example.com/pricing" } } ``` ## Learn More - [Webhooks Introduction](/docs/webhooks) - [All Event Types](/docs/webhooks/event-types) --- # webhooks/emails/complained.mdx Source: https://reloop.sh/docs/webhooks/emails/complained Markdown: https://reloop.sh/docs/webhooks/emails/complained.md The `email.complained` event is triggered when a feedback loop reports spam. ## Event Details All webhook payloads follow a consistent top-level structure with event-specific data nested within the `data` object. ### type `string` The event type that triggered the webhook (`email.complained`). ### created_at `string` ISO 8601 timestamp when the webhook event was created. ### data `object` Includes standard email fields; `status` is `spam` and `error` may include FBL details. ## Handling this event When your endpoint receives an `email.complained` event, you might want to: - Immediately suppress the recipient. - Review content or list hygiene. ```json { "id": "whev_01h…", "type": "email.complained", "created_at": "2026-07-22T12:00:00.000Z", "data": { "email_id": "em_123456789", "from": "sender@example.com", "to": ["recipient@example.com"], "subject": "Hello World", "status": "spam", "error": { "message": "Feedback loop: spam complaint" } } } ``` ## Learn More - [Webhooks Introduction](/docs/webhooks) - [All Event Types](/docs/webhooks/event-types) --- # webhooks/emails/delivered.mdx Source: https://reloop.sh/docs/webhooks/emails/delivered Markdown: https://reloop.sh/docs/webhooks/emails/delivered.md The `email.delivered` event is triggered when an email is delivered to the recipient MTA. ## Event Details All webhook payloads follow a consistent top-level structure with event-specific data nested within the `data` object. ### type `string` The event type that triggered the webhook (`email.delivered`). ### created_at `string` ISO 8601 timestamp when the webhook event was created. ### data `object` Outbound email fields: `email_id`, `from`, `to`, `subject`, `status`. ## Handling this event When your endpoint receives an `email.delivered` event, you might want to: - Update the status in your internal database. - Trigger an automated confirmation email. - Log the event for analytics purposes. ```json { "id": "whev_01h…", "type": "email.delivered", "created_at": "2026-07-22T12:00:00.000Z", "data": { "email_id": "em_123456789", "from": "sender@example.com", "to": ["recipient@example.com"], "subject": "Hello World", "status": "delivered" } } ``` ## Learn More - [Webhooks Introduction](/docs/webhooks) - [All Event Types](/docs/webhooks/event-types) --- # webhooks/emails/delivery-delayed.mdx Source: https://reloop.sh/docs/webhooks/emails/delivery-delayed Markdown: https://reloop.sh/docs/webhooks/emails/delivery-delayed.md The `email.delivery_delayed` event is triggered on a transient delivery failure (soft bounce / deferral). ## Event Details All webhook payloads follow a consistent top-level structure with event-specific data nested within the `data` object. ### type `string` The event type that triggered the webhook (`email.delivery_delayed`). ### created_at `string` ISO 8601 timestamp when the webhook event was created. ### data `object` Includes standard email fields plus `error` describing the temporary failure. ## Handling this event When your endpoint receives an `email.delivery_delayed` event, you might want to: - Track deliverability health without treating it as a permanent failure. - Alert if delays spike for a domain. ```json { "id": "whev_01h…", "type": "email.delivery_delayed", "created_at": "2026-07-22T12:00:00.000Z", "data": { "email_id": "em_123456789", "from": "sender@example.com", "to": ["recipient@example.com"], "subject": "Hello World", "status": "sent", "error": { "code": 450, "message": "Mailbox temporarily unavailable" } } } ``` ## Learn More - [Webhooks Introduction](/docs/webhooks) - [All Event Types](/docs/webhooks/event-types) --- # webhooks/emails/failed.mdx Source: https://reloop.sh/docs/webhooks/emails/failed Markdown: https://reloop.sh/docs/webhooks/emails/failed.md The `email.failed` event is triggered when an email fails permanently before delivery (provider error at send time) or expires in the queue. ## Event Details All webhook payloads follow a consistent top-level structure with event-specific data nested within the `data` object. ### type `string` The event type that triggered the webhook (`email.failed`). ### created_at `string` ISO 8601 timestamp when the webhook event was created. ### data `object` Includes standard email fields plus `error`. ## Handling this event When your endpoint receives an `email.failed` event, you might want to: - Notify the user about the failure. - Check the error details for troubleshooting. - Update the status in your internal database. ```json { "id": "whev_01h…", "type": "email.failed", "created_at": "2026-07-22T12:00:00.000Z", "data": { "email_id": "em_123456789", "from": "sender@example.com", "to": ["recipient@example.com"], "subject": "Hello World", "status": "failed", "error": { "message": "Upstream provider rejected the message" } } } ``` ## Learn More - [Webhooks Introduction](/docs/webhooks) - [All Event Types](/docs/webhooks/event-types) --- # webhooks/emails/opened.mdx Source: https://reloop.sh/docs/webhooks/emails/opened Markdown: https://reloop.sh/docs/webhooks/emails/opened.md The `email.opened` event is triggered when open tracking records a pixel load. ## Event Details All webhook payloads follow a consistent top-level structure with event-specific data nested within the `data` object. ### type `string` The event type that triggered the webhook (`email.opened`). ### created_at `string` ISO 8601 timestamp when the webhook event was created. ### data `object` Standard outbound email fields. `status` reflects the email log status (usually `delivered` or `sent`), not a separate open status. ## Handling this event When your endpoint receives an `email.opened` event, you might want to: - Track email open rates. - Update user engagement scores. - Trigger follow-up workflows. ```json { "id": "whev_01h…", "type": "email.opened", "created_at": "2026-07-22T12:00:00.000Z", "data": { "email_id": "em_123456789", "from": "sender@example.com", "to": ["recipient@example.com"], "subject": "Hello World", "status": "delivered" } } ``` ## Learn More - [Webhooks Introduction](/docs/webhooks) - [All Event Types](/docs/webhooks/event-types) --- # webhooks/emails/received.mdx Source: https://reloop.sh/docs/webhooks/emails/received Markdown: https://reloop.sh/docs/webhooks/emails/received.md The `email.received` event is triggered when an inbound email is successfully received by Reloop. ## Event Details All webhook payloads follow a consistent top-level structure with event-specific data nested within the `data` object. ### type `string` The event type that triggered the webhook (`email.received`). ### created_at `string` ISO 8601 timestamp when the webhook event was created. ### data `object` Inbound fields: `email_id`, `mailbox_id`, `from`, `from_name`, `to`, `cc`, `subject`, `thread_id`, `has_attachments`, `is_spam`, `status`, `message_id`. ## Handling this event When your endpoint receives an `email.received` event, you might want to: - Process inbound messages for your application. - Fetch the full body via the inbox API using `email_id`. - Store attachments in your cloud storage. ```json { "id": "whev_01h…", "type": "email.received", "created_at": "2026-07-22T12:00:00.000Z", "data": { "email_id": "in_123456789", "mailbox_id": "mb_123456789", "from": "sender@example.com", "from_name": "Sender", "to": ["inbound@yourdomain.com"], "cc": [], "subject": "Inbound Message", "thread_id": "thr_123456789", "has_attachments": false, "is_spam": false, "status": "received", "message_id": "" } } ``` ## Learn More - [Webhooks Introduction](/docs/webhooks) - [All Event Types](/docs/webhooks/event-types) --- # webhooks/emails/scheduled.mdx Source: https://reloop.sh/docs/webhooks/emails/scheduled Markdown: https://reloop.sh/docs/webhooks/emails/scheduled.md The `email.scheduled` event is triggered when an email is accepted with a future `scheduled_at` time. It replaces `email.sent` for that message; later lifecycle events (`email.delivered`, `email.bounced`, …) still fire when the message is actually processed. ## Event Details All webhook payloads follow a consistent top-level structure with event-specific data nested within the `data` object. ### type `string` The event type that triggered the webhook (`email.scheduled`). ### created_at `string` ISO 8601 timestamp when the webhook event was created. ### data `object` Standard outbound email fields with `status: "scheduled"` and `scheduled_at` (ISO 8601). ## Handling this event When your endpoint receives an `email.scheduled` event, you might want to: - Show the message as queued for a future send in your UI. - Cancel or reschedule downstream automations until delivery. ```json { "id": "whev_01h…", "type": "email.scheduled", "created_at": "2026-07-22T12:00:00.000Z", "data": { "email_id": "em_123456789", "from": "sender@example.com", "to": ["recipient@example.com"], "subject": "Hello World", "status": "scheduled", "scheduled_at": "2026-07-23T09:00:00.000Z" } } ``` ## Learn More - [Webhooks Introduction](/docs/webhooks) - [All Event Types](/docs/webhooks/event-types) --- # webhooks/emails/sent.mdx Source: https://reloop.sh/docs/webhooks/emails/sent Markdown: https://reloop.sh/docs/webhooks/emails/sent.md The `email.sent` event is triggered when an email is accepted for delivery by Reloop. ## Event Details All webhook payloads follow a consistent top-level structure with event-specific data nested within the `data` object. ### type `string` The event type that triggered the webhook (`email.sent`). ### created_at `string` ISO 8601 timestamp when the webhook event was created. ### data `object` Outbound email fields: `email_id`, `from`, `to`, `subject`, `status`. ## Handling this event When your endpoint receives an `email.sent` event, you might want to: - Update the status in your internal database. - Trigger automated workflows or notifications. - Log the event for analytics purposes. ```json { "id": "whev_01h…", "type": "email.sent", "created_at": "2026-07-22T12:00:00.000Z", "data": { "email_id": "em_123456789", "from": "sender@example.com", "to": ["recipient@example.com"], "subject": "Hello World", "status": "sent" } } ``` ## Learn More - [Webhooks Introduction](/docs/webhooks) - [All Event Types](/docs/webhooks/event-types) --- # webhooks/emails/suppressed.mdx Source: https://reloop.sh/docs/webhooks/emails/suppressed Markdown: https://reloop.sh/docs/webhooks/emails/suppressed.md The `email.suppressed` event ID is reserved for when Reloop rejects a send because the recipient is on a suppression list. **Status:** inactive — not available for new webhook subscriptions until pre-send suppression publishes this event. Contact suppressions currently surface as `contact.blocked` when auto-capture blocks a recipient. ## Planned `data` shape ```json { "id": "whev_01h…", "type": "email.suppressed", "created_at": "2026-07-22T12:00:00.000Z", "data": { "email_id": "em_123456789", "from": "sender@example.com", "to": ["blocked@example.com"], "subject": "Hello World", "status": "failed", "error": { "message": "Recipient is on the suppression list" } } } ``` ## Learn More - [Webhooks Introduction](/docs/webhooks) - [All Event Types](/docs/webhooks/event-types) --- # webhooks/event-types.mdx Source: https://reloop.sh/docs/webhooks/event-types Markdown: https://reloop.sh/docs/webhooks/event-types.md Reloop supports the following **active** event types. Each delivery uses a consistent top-level envelope; event-specific fields live under `data` and use **snake_case**. ## Email lifecycle | Event | Description | | --- | --- | | `email.sent` | Email accepted for delivery (immediate send) | | `email.scheduled` | Email accepted with a future `scheduled_at` (replaces `email.sent` for that message) | | `email.delivered` | Delivered to the recipient MTA | | `email.bounced` | Permanent delivery failure | | `email.delivery_delayed` | Transient failure / delay | | `email.complained` | Recipient marked as spam (feedback loop) | | `email.failed` | Permanent send failure before delivery (or message expired) | | `email.opened` | Recipient opened the email | | `email.clicked` | Recipient clicked a link in the email | | `email.received` | Inbound email successfully received | ### Email `data` shape (outbound) ```json { "email_id": "em_…", "from": "Acme ", "to": ["user@example.com"], "subject": "Hello", "status": "delivered", "error": { "code": 550, "message": "User unknown" }, "url": "https://example.com/path" } ``` - `error` is present on bounce, delay, complaint, and failure events. - `url` is present on `email.clicked`. - `scheduled_at` is present on `email.scheduled`. ### Inbound `email.received` `data` shape ```json { "email_id": "in_…", "mailbox_id": "mb_…", "from": "sender@example.com", "from_name": "Sender", "to": ["inbox@yourdomain.com"], "cc": [], "subject": "Inbound Message", "thread_id": "thr_…", "has_attachments": false, "is_spam": false, "status": "received", "message_id": "" } ``` ## Domain lifecycle | Event | Description | | --- | --- | | `domain.create` | Domain created | | `domain.update` | Domain updated | | `domain.delete` | Domain deleted | | `domain.undelete` | Domain restored | | `domain.verify` | Domain DNS verified | ### Domain `data` shape ```json { "id": "dom_…", "name": "example.com", "status": "active" } ``` ## API key lifecycle | Event | Description | | --- | --- | | `api-key.create` | API key created | | `api-key.update` | API key updated / enabled / rotated | | `api-key.delete` | API key deleted | | `api-key.revoke` | API key revoked (disabled) | ### API key `data` shape ```json { "api_key_id": "key_…", "status": "disabled", "action": "revoked" } ``` `status` and `action` are optional and only set for some transitions. ## Contact lifecycle | Event | Description | | --- | --- | | `contact.create` | Contact created | | `contact.update` | Contact updated | | `contact.delete` | Contact deleted | | `contact.subscribed` | Contact status set to subscribed | | `contact.unsubscribed` | Contact status set to unsubscribed | | `contact.blocked` | Contact status set to blocked | | `contact.group.create` | Contact group created | | `contact.group.update` | Contact group updated | | `contact.group.delete` | Contact group deleted | ### Contact `data` shape ```json { "id": "con_…", "email": "contact@example.com", "first_name": "Ada", "last_name": "Lovelace", "status": "subscribed" } ``` ### Contact group `data` shape ```json { "id": "grp_…", "name": "VIP" } ``` ## Envelope ```json { "id": "whev_…", "type": "email.delivered", "created_at": "2026-07-22T12:00:00.000Z", "data": { } } ``` ## Coming soon (not subscribable yet) These event IDs exist in the catalog but are **inactive** until the pipeline emits them: | Event | Notes | | --- | --- | | `email.suppressed` | Pre-send suppression event not wired yet | | `api-key.rate_limited` | Rate-limit publisher not wired yet | --- ## Learn More - [Introduction](/docs/webhooks) - [Verify Webhooks Requests](/docs/webhooks/verify-webhooks-requests) - [Retries and Replays](/docs/webhooks/retries-and-replays) --- # webhooks/index.mdx Source: https://reloop.sh/docs/webhooks Markdown: https://reloop.sh/docs/webhooks.md Webhooks allow you to build or set up integrations which subscribe to certain events on Reloop. When one of those events is triggered, we'll send a HTTP POST payload to the webhook's configured URL. ## What is a webhook? Webhooks are "user-defined HTTP callbacks". They are usually triggered by some event, such as an email being delivered or a domain being verified. When that event occurs, the source site makes an HTTP request to the URL configured for the webhook. Users can configure them to cause events on one site to invoke behavior on another. ## Why use webhooks? - Automatically remove bounced email addresses from mailing lists - Create alerts in your messaging or incident tools based on event types - Store all send events in your own database for custom reporting/retention - Receive emails using [Inbound](/docs/webhooks/ingester) ## How to receive webhooks ### 1. Create a dev endpoint to receive requests. Set up a URL on your server that can receive HTTP POST requests. ```javascript if (req.method === 'POST') { const event = req.body; console.log(event); res.status(200).send('OK'); } }; ``` You can use tools like [ngrok](https://ngrok.com) or [VS Code Port Forwarding](https://code.visualstudio.com/docs/debugtest/port-forwarding) to expose your local server to the internet. ### 2. Add a webhook in Reloop. Go to the [Webhooks page](https://app.reloop.sh/webhooks) in your dashboard. 1. Add your publicly accessible HTTPS URL. 2. Select all events you want to observe. ### 3. Test your local endpoint. When you send an email or trigger an event, Reloop will send a payload like this to your endpoint: ```json { "id": "whev_01h…", "type": "email.bounced", "created_at": "2026-07-22T23:41:12.126Z", "data": { "email_id": "em_123456789", "from": "Acme ", "to": ["bounced@reloop.sh"], "subject": "Sending this example", "status": "bounced", "error": { "code": 550, "message": "User unknown" } } } ``` All `data` fields use **snake_case**. See [Event Types](/docs/webhooks/event-types) for the full catalog and per-category shapes. Headers include `Reloop-Id`, `Reloop-Timestamp`, and `Reloop-Signature` for verification. ### 4. Update and deploy your production endpoint. Once you've tested your logic, update your endpoint to handle specific event types and deploy it to your production server. ```javascript if (req.method === 'POST') { const event = req.body; if (event.type === "email.bounced") { // Handle bounce logic } res.status(200).send('OK'); } }; ``` ### 5. Register your production webhook endpoint Update your webhook URL in the [Reloop Dashboard](https://app.reloop.sh/webhooks) with your production URL. ## FAQ If your server returns a non-2xx response, we retry up to 7 attempts: - Immediate - 5 seconds - 5 minutes - 30 minutes - 2 hours - 5 hours - 10 hours Use your endpoint secret (`whsec_…`) to verify `Reloop-Signature`. See [Verify Webhooks Requests](/docs/webhooks/verify-webhooks-requests). - `54.148.139.208` - `2600:1f24:64:8000::/52` Reloop guarantees "at-least-once" delivery of webhooks. Each webhook has a unique `reloop-id` (or Svix ID) header that you can use for idempotency to ensure you don't process the same event twice. We do not guarantee that events will arrive in the order they occurred. For example, an `email.opened` event might arrive before an `email.delivered` event due to network latency or retries. You should use the `created_at` timestamp in the payload to order them. Yes, you can manually replay any failed or successful webhook event from the [Reloop Dashboard](https://app.reloop.sh/webhooks). --- ## Learn More - [Event Types](/docs/webhooks/event-types) - [Webhook Ingester](/docs/webhooks/ingester) - [Verifying Requests](/docs/webhooks/verify-webhooks-requests) --- # webhooks/ingester.mdx Source: https://reloop.sh/docs/webhooks/ingester Markdown: https://reloop.sh/docs/webhooks/ingester.md The Webhook Ingester is a self-hosted tool that allows you to store all your Reloop webhook events directly in your own database. This is ideal for long-term data retention, custom analytics, and building robust event-driven workflows without worrying about webhook delivery order or duplicate handling. ## Why use the Webhook Ingester? - **Signature Verification**: Built-in verification to ensure webhook authenticity. - **Idempotency**: Safely handles duplicate webhook deliveries using unique event IDs. - **Multiple Databases**: Support for PostgreSQL, MySQL, MongoDB, and data warehouses. - **Easy Deployment**: One-click deployment to Vercel, Railway, or Render. ## Deploy You can run the ingester using our official Docker image: ```bash docker pull ghcr.io/reloop-labs/reloop-webhooks-ingester ``` ## Supported Databases We support a wide range of databases to store your webhook events: - **PostgreSQL** (including Supabase and Neon) - **MySQL** (including PlanetScale) - **MongoDB** - **Data Warehouses** (Snowflake, BigQuery, ClickHouse) ## Quick Start Clone the repository and install dependencies: ```bash git clone https://github.com/reloop-labs/reloop-webhooks-ingester.git cd reloop-webhooks-ingester pnpm install ``` Copy the example environment file and add your credentials: ```bash cp .env.example .env.local ``` Required variables: ```bash # Your Reloop webhook signing secret from the dashboard RELOOP_WEBHOOK_SECRET=whsec_xxxxxxxxxxxxxxxxxxxxx # Database connection string POSTGRESQL_URL=postgresql://user:password@host:5432/database ``` Run the setup command to create the necessary tables/collections: ```bash pnpm db:setup --postgresql # or --mysql, --mongodb ``` Deploy your instance and add the endpoint in the [Reloop Dashboard](https://app.reloop.sh/webhooks). Your endpoint URL will be: `https://your-app.com/postgresql` (or your chosen connector). ## Database Schemas The ingester creates tables with a standardized schema for different event categories: - `reloop_wh_emails`: Stores all email-related events. - `reloop_wh_contacts`: Stores audience and contact events. - `reloop_wh_domains`: Stores domain verification events. ### Core Fields Every event includes these essential fields: - `event_id`: Unique webhook event ID for idempotency. - `event_type`: The type of event (e.g., `email.delivered`). - `event_created_at`: When the event occurred in Reloop. - `webhook_received_at`: When the webhook was stored in your database. - `data`: JSON object containing the full event payload. ## Idempotency The ingester uses the unique event ID provided by Reloop to ensure that even if a webhook is delivered multiple times, it is only stored once in your database. ## Configuration Reference ### Required Environment Variables | Variable | Description | |----------|-------------| | `RELOOP_WEBHOOK_SECRET` | The signing secret used to verify webhook authenticity. | ### Database-Specific Variables #### Supabase / PostgreSQL ```bash POSTGRESQL_URL=postgresql://user:password@host:5432/database ``` #### MongoDB ```bash MONGODB_URI=mongodb+srv://username:password@cluster.mongodb.net/ MONGODB_DATABASE=reloop_webhooks ``` ## Example Queries Once your data is in your database, you can run powerful queries: **Count daily events by type:** ```sql SELECT DATE(event_created_at) AS day, event_type, COUNT(*) AS count FROM reloop_wh_emails GROUP BY DATE(event_created_at), event_type ORDER BY day DESC; ``` ## Data Retention Since the data is in your own database, you have full control over retention. You can set up TTL indexes in MongoDB or use a cron job to purge old data: ```sql DELETE FROM reloop_wh_emails WHERE event_created_at < NOW() - INTERVAL '90 days'; ``` ## Troubleshooting - **Signature failing**: Ensure `RELOOP_WEBHOOK_SECRET` matches your dashboard secret. - **Connection errors**: Check your database firewall rules and connection string. - **Webhooks not received**: Verify your endpoint is publicly accessible and returning a 200 OK. --- ## Learn More - [Verifying Webhooks](/docs/webhooks/verify-webhooks-requests) - [Event Types Reference](/docs/webhooks/event-types) --- # webhooks/retries-and-replays.mdx Source: https://reloop.sh/docs/webhooks/retries-and-replays Markdown: https://reloop.sh/docs/webhooks/retries-and-replays.md Reloop delivers webhooks with at-least-once semantics. If your server is down or returns a non-2xx status, we automatically retry the delivery. ## Automatic Retries Each delivery is attempted up to **`maxRetries` times** (default **7**, maximum **7**) with a fixed schedule. `maxRetries` is total attempts including the first try. Delays are measured from the previous failure: | Attempt | Delay after previous failure | | --- | --- | | 1 | Immediate | | 2 | 5 seconds | | 3 | 5 minutes | | 4 | 30 minutes | | 5 | 2 hours | | 6 | 5 hours | | 7 | 10 hours | If you set a lower `maxRetries` on the endpoint (for example `3`), only the first rows of the schedule apply. SSRF-blocked or non-HTTPS endpoints are **not** retried (terminal failure). After many consecutive **terminal** failures on an endpoint, Reloop may disable the webhook (`status: failed`). Re-enable it from the dashboard after fixing your endpoint. ## Outbound rate limiting When `rateLimitEnabled` is true (default), Reloop caps outbound POSTs per endpoint at `maxRequestsPerMinute` (default **60**). Extra deliveries are delayed into the next minute window rather than dropped. ## Filtering Optional `filteringOptions` on an endpoint: - **`matchConditions`** — only deliver when every listed top-level `data` field equals the expected value (shallow equality). - **`excludeFields`** — strip listed top-level keys from `data` before POST (and in the stored delivery payload). Example: ```json { "filteringOptions": { "matchConditions": { "status": "bounced" }, "excludeFields": ["subject"] } } ``` ## Manual Replays You can manually replay any delivery from the dashboard or API. Replay creates a **new** delivery row (linked to the original) so history stays intact, then enqueues it on the delivery queue using the endpoint's current `maxRetries`. Navigate to the Webhooks page in your dashboard. Open the webhook endpoint you are using. Locate the delivery in the delivery logs. Trigger a manual redelivery. --- ## Learn More - [Webhooks Introduction](/docs/webhooks) - [Event Types](/docs/webhooks/event-types) - [Verify Webhooks Requests](/docs/webhooks/verify-webhooks-requests) --- # webhooks/verify-webhooks-requests.mdx Source: https://reloop.sh/docs/webhooks/verify-webhooks-requests Markdown: https://reloop.sh/docs/webhooks/verify-webhooks-requests.md To ensure that webhook requests are authentic and coming from Reloop, verify the signature included in the request headers. This prevents unauthorized requests from reaching your application logic. ## Headers Every delivery includes: | Header | Description | | --- | --- | | `Reloop-Id` | Event id (`whev_…`), same as body `id` | | `Reloop-Timestamp` | Unix timestamp (seconds) used in the signature | | `Reloop-Signature` | `t=,v1=` | ## Signature algorithm 1. Read the **raw** request body bytes (do not re-serialize JSON). 2. Read `Reloop-Timestamp` (or parse `t=` from `Reloop-Signature`). 3. Compute HMAC-SHA256 over the string `` `${timestamp}.${rawBody}` `` using your endpoint secret (`whsec_…`). 4. Compare the hex digest to the `v1=` value with a constant-time compare. 5. Reject if the timestamp is older than ~5 minutes (replay protection). ```typescript secret: string; rawBody: string; signatureHeader: string; toleranceSeconds?: number; }): boolean { const parts = Object.fromEntries( input.signatureHeader.split(",").map((p) => { const [k, ...rest] = p.trim().split("="); return [k, rest.join("=")]; }), ); const timestamp = Number(parts.t); const v1 = parts.v1; if (!Number.isFinite(timestamp) || !v1) return false; const now = Math.floor(Date.now() / 1000); if (Math.abs(now - timestamp) > (input.toleranceSeconds ?? 300)) return false; const expected = createHmac("sha256", input.secret) .update(`${timestamp}.${input.rawBody}`) .digest("hex"); try { const a = Buffer.from(expected, "hex"); const b = Buffer.from(v1, "hex"); return a.length === b.length && timingSafeEqual(a, b); } catch { return false; } } ``` ## Payload shape ```json { "id": "whev_01h…", "type": "email.delivered", "created_at": "2026-07-22T12:00:00.000Z", "data": { "email_id": "em_…", "from": "hello@example.com", "to": ["user@example.com"], "subject": "Welcome", "status": "delivered" } } ``` ## Why verify webhooks? Verification is critical because it allows you to: - Confirm the request was signed with your endpoint secret - Reject forged events from third parties - Detect and drop replayed requests outside the time window --- # integrations/ai-tools/cli-agents.mdx Source: https://reloop.sh/docs/integrations/ai-tools/cli-agents Markdown: https://reloop.sh/docs/integrations/ai-tools/cli-agents.md The [Reloop CLI](/sdk/cli) is purpose-built for AI agent workflows — every command supports machine-readable JSON output, deterministic exit codes, and stdin piping. See the full [CLI reference](/sdk/cli) for all available commands. ## Agent Skills Install the CLI agent skill so your agent knows how to use the Reloop CLI effectively: ```bash npx skills add reloop/reloop-cli ``` ## Non-interactive mode Every CLI command supports `--json` for machine-readable output: - **Output**: JSON to stdout, no progress indicators - **Exit codes**: `0` for success, `1` for errors - **Errors**: Always include `message` and `code` fields ```json { "error": { "message": "No API key found", "code": "auth_error" } } ``` ## Piping from stdin Use `-` as the value of any file flag to read from stdin: ```bash echo "Your order has shipped." | reloop emails send \ --from "Acme " \ --to delivered@example.com \ --subject "Order update" \ --text-file - ``` This also works with `--html-file -` and `--file -` for [batch commands](#batch-sending). ## Batch sending Use `emails batch` to send up to 100 emails in a single request: ```bash cat emails.json | reloop emails batch --file - ``` ## Safe retries Use `--idempotency-key` to safely retry failed sends without risking duplicates: ```bash reloop emails send \ --from "Acme " \ --to delivered@example.com \ --subject "Welcome" \ --text "Hello!" \ --idempotency-key "welcome-user-123" ``` Idempotency keys are supported on both `emails send` and `emails batch` commands. ## Scheduling Use `--scheduled-at` to schedule emails for future delivery: ```bash reloop emails send \ --from "Acme " \ --to delivered@example.com \ --subject "Your trial ends soon" \ --text "Your free trial expires in 3 days." \ --scheduled-at "tomorrow at 9am ET" ``` You can cancel or reschedule with: ```bash reloop emails cancel reloop emails update --scheduled-at ``` ## Reading inbound emails The `emails receiving listen` command starts a long-running process that watches for new inbound emails: ```bash reloop emails receiving listen --json ``` To fetch a specific received email: ```bash reloop emails receiving get ``` Make sure you have a [verified domain](/learn/domain) with receiving enabled. ## Closing the loop with webhooks The `webhooks listen` command subscribes to [webhook events](/docs/webhooks) and streams them to your terminal: ```bash reloop webhooks listen \ --url https://hostname.tailnet-name.ts.net \ --events email.delivered email.bounced email.received ``` Press `Ctrl+C` to stop listening. The webhook is automatically removed when you disconnect. To forward webhooks to a local development server, use `--forward-to`: ```bash reloop webhooks listen \ --url https://hostname.tailnet-name.ts.net \ --forward-to http://localhost:4321/api/webhook ``` The `--url` flag requires a publicly reachable URL. We recommend [Tailscale Funnel](https://tailscale.com/kb/1223/funnel), [ngrok](https://ngrok.com/), or [localtunnel](https://theboringtech.io/) for local development. If you prefer to set up webhooks manually, use `reloop webhooks create`. --- # integrations/ai-tools/mcp-server.mdx Source: https://reloop.sh/docs/integrations/ai-tools/mcp-server Markdown: https://reloop.sh/docs/integrations/ai-tools/mcp-server.md ## What is an MCP Server? The Model Context Protocol (MCP) is an open standard that lets AI models connect to external tools and data sources. An MCP server acts as a bridge between your AI agent and the Reloop API, allowing the agent to send emails, manage contacts, handle domains, and more — all through natural language. ## What can Reloop's MCP Server do? The [Reloop MCP Server](https://github.com/reloop-labs/reloop-mcp) exposes the full Reloop API as MCP tools: - **Emails** — Send, list, get, cancel, update, and batch send emails. Supports HTML, plain text, attachments (local file, URL, or base64), CC/BCC, reply-to, scheduling, tags, and topic-based sending. - **Received Emails** — List and read inbound emails. List and download received email attachments. - **Contacts** — Create, list, get, update, and remove contacts. Manage segment memberships and topic subscriptions. Supports custom contact properties. - **Broadcasts** — Create, send, list, get, update, and remove broadcast campaigns. Supports scheduling, personalization placeholders, and preview text. - **Domains** — Create, list, get, update, remove, and verify sender domains. Configure tracking, TLS, and sending/receiving capabilities. - **Segments** — Create, list, get, and remove audience segments. - **Topics** — Create, list, get, update, and remove subscription topics. - **Contact Properties** — Create, list, get, update, and remove custom contact attributes. - **API Keys** — Create, list, and remove API keys. - **Webhooks** — Create, list, get, update, and remove webhooks for event notifications. - **Templates** — Create, list, get, update, and remove email templates. ## Prerequisites You'll need a supported MCP client and `npx` installed on your machine. - [Create an API key](https://app.reloop.sh/api-keys) - [Verify your domain](https://app.reloop.sh/domains) ## How to use the MCP Server Replace `rl_xxxxxxxxx` with your actual Reloop API key. ### Stdio Transport (Default) ```bash claude mcp add reloop -e RELOOP_API_KEY=rl_xxxxxxxxx -- npx -y reloop-mcp ``` ```bash codex mcp add reloop \ --env RELOOP_API_KEY=rl_xxxxxxxxx \ -- npx -y reloop-mcp ``` ```json { "mcpServers": { "reloop": { "command": "npx", "args": ["-y", "reloop-mcp"], "env": { "RELOOP_API_KEY": "rl_xxxxxxxxx" } } } } ``` ```json { "mcpServers": { "reloop": { "command": "npx", "args": ["-y", "reloop-mcp"], "env": { "RELOOP_API_KEY": "rl_xxxxxxxxx" } } } } ``` Add the following to your VS Code `settings.json`: ```json { "mcp": { "servers": { "reloop": { "command": "npx", "args": ["-y", "reloop-mcp"], "env": { "RELOOP_API_KEY": "rl_xxxxxxxxx" } } } } } ``` ```json { "mcpServers": { "reloop": { "command": "npx", "args": ["-y", "reloop-mcp"], "env": { "RELOOP_API_KEY": "rl_xxxxxxxxx" } } } } ``` Add to your `opencode.json`: ```json { "$schema": "https://opencode.ai/config.json", "mcp": { "reloop": { "type": "local", "command": ["npx", "-y", "reloop-mcp"], "enabled": true, "environment": { "RELOOP_API_KEY": "rl_xxxxxxxxx" } } } } ``` ```json { "mcpServers": { "reloop": { "command": "npx", "args": ["-y", "reloop-mcp"], "env": { "RELOOP_API_KEY": "rl_xxxxxxxxx" } } } } ``` ### HTTP Transport For HTTP transport, the API key is passed via the `Authorization` header instead of an environment variable. Start the server: ```bash npx -y reloop-mcp --http --port 3000 ``` The server will be available at `http://127.0.0.1:3000` with the MCP endpoint at `/mcp`. ```bash claude mcp add reloop --transport http http://127.0.0.1:3000/mcp --header "Authorization: Bearer rl_xxxxxxxxx" ``` ```json { "mcpServers": { "reloop": { "url": "http://127.0.0.1:3000/mcp", "headers": { "Authorization": "Bearer rl_xxxxxxxxx" } } } } ``` You can customize the port with the `MCP_PORT` environment variable: ```bash MCP_PORT=3000 npx -y reloop-mcp --http ``` ### Options **CLI flags:** - `--key`: Your Reloop API key (stdio mode only; HTTP mode uses the Bearer token from the client) - `--sender`: Default sender email address from a verified domain - `--reply-to`: Default reply-to email address (can be specified multiple times) - `--http`: Use HTTP transport instead of stdio (default: stdio) - `--port`: HTTP port when using `--http` (default: 3000, or `MCP_PORT` env var) **Environment variables:** - `RELOOP_API_KEY`: Your Reloop API key (required for stdio, optional for HTTP) - `SENDER_EMAIL_ADDRESS`: Default sender email address from a verified domain (optional) - `REPLY_TO_EMAIL_ADDRESSES`: Comma-separated reply-to email addresses (optional) - `MCP_PORT`: HTTP port when using `--http` (optional) ## Local Development ```bash git clone https://github.com/reloop-labs/reloop-mcp.git pnpm install pnpm run build ``` Replace `npx` commands above with direct `node` commands. ### Stdio ```bash claude mcp add reloop -e RELOOP_API_KEY=rl_xxxxxxxxx -- node ABSOLUTE_PATH_TO_PROJECT/dist/index.js ``` ```bash codex mcp add reloop \ --env RELOOP_API_KEY=rl_xxxxxxxxx \ -- node ABSOLUTE_PATH_TO_PROJECT/dist/index.js ``` ```json { "mcpServers": { "reloop": { "command": "node", "args": ["ABSOLUTE_PATH_TO_PROJECT/dist/index.js"], "env": { "RELOOP_API_KEY": "rl_xxxxxxxxx" } } } } ``` ### HTTP ```bash node ABSOLUTE_PATH_TO_PROJECT/dist/index.js --http --port 3000 ``` ```bash claude mcp add reloop --transport http http://127.0.0.1:3000/mcp --header "Authorization: Bearer rl_xxxxxxxxx" ``` ```json { "mcpServers": { "reloop": { "url": "http://127.0.0.1:3000/mcp", "headers": { "Authorization": "Bearer rl_xxxxxxxxx" } } } } ``` ## Testing with MCP Inspector Follow the [Local Development](#local-development) steps above first. ### Using Stdio Transport 1. Set your API key: ```bash ``` 2. Start the inspector: ```bash pnpm inspector ``` 3. Configure in the browser: - Choose **stdio** (launch a process) - Command: `node` - Args: `dist/index.js` (or the full path to `dist/index.js`) - Env: `RELOOP_API_KEY=rl_your_key_here` - Click **Connect**, then use "List tools" to verify the server is working ### Using HTTP Transport 1. Start the HTTP server: ```bash node dist/index.js --http --port 3000 ``` 2. Start the inspector: ```bash pnpm inspector ``` 3. Configure in the browser: - Choose **Streamable HTTP** (connect to URL) - URL: `http://127.0.0.1:3000/mcp` - Add a custom header: `Authorization: Bearer rl_your_key_here` and activate the toggle - Click **Connect**, then use "List tools" to verify the server is working --- # integrations/ai-tools/openclaw-guide.mdx Source: https://reloop.sh/docs/integrations/ai-tools/openclaw-guide Markdown: https://reloop.sh/docs/integrations/ai-tools/openclaw-guide.md Learn how to give your AI agent a dedicated email inbox using Reloop, so it can send and receive emails autonomously. ## Why should I give my agent an inbox? An AI agent with its own email address can: - Sign up for its own accounts to GitHub, hosting platforms, and more, so you don't need to share your own credentials. - Process attachments (like receipts, invoices, etc.) and act accordingly - Receive newsletters, parse them, and send the most important information to you - Send you daily reports and digests - Send and receive emails on your behalf ## How to set up an inbox for OpenClaw ### Step 1: Install the skill Tell your agent: ``` Let's get you set up with an email inbox! Install the reloop-skills from https://github.com/reloop-labs/reloop-skills and review them before continuing. ``` Alternatively, you can install the skills using the [Reloop CLI](/sdk/cli): ```bash npx skills add reloop/reloop-skills ``` ### Step 2: Get an API key 1. Open the [API Keys](https://app.reloop.sh/api-keys) page 2. Choose a name and permission scope 3. Create the API key Store the key securely: 1. SSH into your agent's machine and store the API key in an `.env` file. 2. Store the API key in a password manager like 1Password, and give your agent access to its own vault. This can be done using a [1Password Service Account](https://developer.1password.com/docs/service-accounts/) on team plans. ### Step 3: Verify a domain We [strongly recommend](/learn/domain) using a subdomain like `agent.example.com` rather than your root `example.com` domain. This keeps your agent's email reputation separate. You can set up a domain using the [Reloop CLI](/sdk/cli) or through the dashboard: 1. Go to the [Domains tab](https://app.reloop.sh/domains) and add a domain 2. Select a subdomain and region 3. Configure DNS: - **Auto Configure**: Automatically configure DNS records if your provider supports it. - **Go to (provider)**: Open your provider's website to add records manually. - **I've added the records**: Manually add DNS records via your DNS provider. 4. Enable receiving on the domain 5. Add the DNS records and wait for verification See our [guide on verifying a domain](/learn/domain) for detailed instructions. ### Step 4: Use webhooks to receive emails **Ask your agent to set up a webhook server:** ``` I want you to be able to receive emails, too. Let's set up a webhook to receive emails at my domain using the agent email inbox agent skill. ``` **Set up a tunnel:** Use [Tailscale Funnel](https://tailscale.com/kb/1223/funnel) to expose your agent's webhook server: ```bash tailscale funnel 3000 ``` This gives you a public URL like `https://hostname.tailnet-name.ts.net`. **Give your agent access to secrets securely** (see [Step 2](#step-2-get-an-api-key)). **Add the webhook to Reloop:** ``` Let's add a webhook to Reloop using the server you just built. Use the email.received event, as instructed by the reloop-skills agent skill, and securely save the returned webhook signing secret. ``` **Test receiving an email:** ```typescript const reloop = new Reloop(process.env.RELOOP_API_KEY); // Security: strict allowlist const ALLOWED_SENDERS = ['your@email.com']; async function handler(req) { const payload = await req.text(); const id = req.headers.get('svix-id'); const timestamp = req.headers.get('svix-timestamp'); const signature = req.headers.get('svix-signature'); if (!id || !timestamp || !signature) { return new Response('Missing headers', { status: 400 }); } const event = reloop.webhooks.verify({ payload, headers: { id, timestamp, signature }, webhookSecret: process.env.RELOOP_WEBHOOK_SECRET, }); if (event.type === 'email.received') { // Security check if (!ALLOWED_SENDERS.includes(event.data.from.toLowerCase())) { return new Response('OK', { status: 200 }); } // Get full email const { data: email } = await reloop.emails.receiving.get( event.data.email_id, ); // Notify user instantly await notifyUser(email); } return new Response('OK', { status: 200 }); } ``` See our [guide on receiving emails with Reloop](/learn/receiving) for more details. ### Step 5: Hook into OpenClaw's APIs for instant notifications **Ask your agent to hook into the Gateway API:** ``` Use the OpenClaw Gateway API to notify me instantly when you receive an email webhook call from Reloop. Use the reloop-skills agent skill for guidance. ``` **Test instant notifications** by sending an email to your agent's address and verifying it receives it. ## Security considerations The [Agent Email Inbox skill](https://github.com/reloop-labs/reloop-skills/blob/main/skills/agent-email-inbox/SKILL.md#security-levels) includes security guidelines with five levels: 1. **Strict Allowlist**: Only allow emails from specific senders. Recommended for most use cases. 2. **Domain Allowlist**: Allow emails from any sender from a given domain (e.g. anyone from `example.com`). 3. **Content Filtering with Sanitization**: Accept emails from anyone, but sanitize content to remove potential injection attempts. 4. **Sandboxed Processing**: Process all emails but in a restricted context where the agent has limited capabilities. 5. **Human-in-the-Loop**: Process all emails but require human approval for each email. Review the [Reloop Skill](https://github.com/reloop-labs/reloop-skills/blob/main/skills/agent-email-inbox/SKILL.md#security-levels) for detailed security guidance. If you have questions, [contact support](https://reloop.sh/help). --- # integrations/agent-skills/agent-email-inbox.mdx Source: https://reloop.sh/docs/integrations/agent-skills/agent-email-inbox Markdown: https://reloop.sh/docs/integrations/agent-skills/agent-email-inbox.md Give your AI agent a secure email inbox to receive and act on inbound emails. This skill provides your agent with the knowledge to set up, secure, and manage an email inbox for receiving messages. ## Installation The Agent Email Inbox skill is part of the [reloop-skills](https://github.com/reloop-labs/reloop-skills) collection: ```bash npx skills add reloop/reloop-skills ``` ## Features - **Webhook-based receiving**: Set up webhooks to receive inbound emails in real-time - **Email parsing**: Extract structured data from incoming emails (sender, subject, body, attachments) - **Attachment handling**: Download and process email attachments securely - **Security guidelines**: Built-in security levels from strict allowlists to sandboxed processing - **Event-driven architecture**: React to incoming emails with automated workflows ## Security Levels The skill includes five security levels you can implement based on your needs: 1. **Strict Allowlist** — Only process emails from pre-approved senders. Recommended for most use cases. 2. **Domain Allowlist** — Allow emails from any sender at approved domains. 3. **Content Filtering** — Accept all emails but sanitize content before processing. 4. **Sandboxed Processing** — Process in a restricted context with limited agent capabilities. 5. **Human-in-the-Loop** — Queue all emails for human approval before agent processing. ## How it works Your agent needs a verified domain with receiving enabled. See [Domains](/learn/domain). Your agent creates an HTTP endpoint to receive webhook events from Reloop. Subscribe to `email.received` events via the Reloop API or CLI. When an email arrives, Reloop sends a webhook to your endpoint. Your agent verifies the signature, fetches the full email, and processes it. ## Learn More - [OpenClaw Guide](/integrations/openclaw-guide) — Step-by-step guide for setting up an agent inbox - [Receiving Emails](/learn/receiving) — General guide on receiving emails with Reloop - [Webhooks](/docs/webhooks) — Webhook setup and event types - [View on GitHub](https://github.com/reloop-labs/reloop-skills/tree/main/skills/agent-email-inbox) --- # integrations/agent-skills/email-best-practices.mdx Source: https://reloop.sh/docs/integrations/agent-skills/email-best-practices Markdown: https://reloop.sh/docs/integrations/agent-skills/email-best-practices.md A comprehensive skill that teaches your AI agent best practices for building production-ready email systems. This skill covers deliverability, authentication, content guidelines, and compliance. ## Installation ```bash npx skills add reloop/email-best-practices ``` ## What's covered ### Deliverability - SPF, DKIM, and DMARC authentication setup - Domain warmup strategies for new sending domains - Reputation management and monitoring - Bounce handling and suppression lists - Throttling and rate limiting best practices ### Content Guidelines - Subject line optimization for engagement - Plain text vs HTML email best practices - Image-to-text ratio recommendations - Call-to-action (CTA) best practices - Mobile-responsive email design ### Compliance - CAN-SPAM Act requirements - GDPR considerations for email - Unsubscribe link requirements - Physical address requirements - Consent management (opt-in/opt-out) ### Transactional vs Marketing - When to use transactional emails vs marketing emails - Separate sending domains and IP pools - Appropriate content for each type - Legal distinctions and requirements ### Error Handling - Retry strategies for failed sends - Handling bounces (hard vs soft) - Managing complaint feedback loops - Monitoring delivery rates and engagement metrics ## Rules The skill provides your agent with actionable rules such as: - Always include a plain text version alongside HTML - Never use a no-reply sender address for marketing emails - Always verify your sending domain before sending at scale - Use dedicated subdomains for transactional and marketing email - Implement exponential backoff for API retries - Always include an unsubscribe mechanism in marketing emails ## Learn More - [Sending Emails](/learn/sending) — Guide to sending emails with Reloop - [Domains](/learn/domain) — Domain verification and DNS configuration - [View on GitHub](https://github.com/reloop-labs/reloop-skills/tree/main/skills/email-best-practices) --- # integrations/agent-skills/reloop-skill.mdx Source: https://reloop.sh/docs/integrations/agent-skills/reloop-skill Markdown: https://reloop.sh/docs/integrations/agent-skills/reloop-skill.md Send emails through the Reloop API with AI agents. This skill gives your agent comprehensive knowledge of the Reloop API, including sending, receiving, and managing emails. ## Installation The Reloop skill is part of the [reloop-skills](https://github.com/reloop-labs/reloop-skills) collection. It also includes the [Agent Email Inbox](/integrations/agent-email-inbox) skill. ```bash npx skills add reloop/reloop-skills ``` ## Advantages - **Single and batch email sending**: Send individual emails or batch up to 100 emails per request. - **Built-in error handling and retry logic**: Automatic retries with exponential backoff for transient failures. - **Idempotency key support**: Prevent duplicate sends with idempotency keys for safe retries. - **Multi-language SDK support**: Works with Node.js, Python, Ruby, Go, and other supported SDKs. - **Automatic activation for email tasks**: AI agents automatically use this skill when email sending is needed. ## What's included The skill teaches your agent: - How to authenticate with the Reloop API - Sending emails (single and batch) - Managing contacts and audiences - Working with templates - Handling webhooks and events - Domain verification and configuration - Best practices for deliverability ## Learn More - [Reloop API Reference](/api) - [SDKs](/resources/sdks) - [View on GitHub](https://github.com/reloop-labs/reloop-skills/tree/main/skills/reloop) --- # resources/cli.mdx Source: https://reloop.sh/docs/resources/cli Markdown: https://reloop.sh/docs/resources/cli.md # CLI Coming soon. --- # resources/sdks.mdx Source: https://reloop.sh/docs/resources/sdks Markdown: https://reloop.sh/docs/resources/sdks.md Official Node.js SDK for server-side JavaScript and TypeScript. Official Python client library for the Reloop API. Official Go client library for the Reloop API. Official Java SDK for JVM-based applications. Official PHP library for integrating with Reloop. Official Ruby gem for integrating with Reloop. Official Rust crate for integrating with Reloop. Official Elixir library for integrating with Reloop. Official .NET library for C# and other JVM/.NET applications. ## Missing your language? We're actively expanding our SDK coverage. If your language or framework isn't listed above, you can: Integrate directly with our raw REST API endpoints. Open an issue on GitHub to request or upvote a new SDK. All SDKs are open-source and contributions are welcome. --- # resources/security.mdx Source: https://reloop.sh/docs/resources/security Markdown: https://reloop.sh/docs/resources/security.md # Security Coming soon. --- # examples/go/gin.mdx Source: https://reloop.sh/docs/examples/go/gin Markdown: https://reloop.sh/docs/examples/go/gin.md # Gin Integration Integrate Reloop into your Go web application using the Gin framework. ## Installation Install the official Go SDK: ```bash go get github.com/reloop-labs/reloop-go ``` ## Sending an Email ```go package main "context" "net/http" "os" "github.com/gin-gonic/gin" "github.com/reloop-labs/reloop-go" ) func main() { r := gin.Default() client := reloop.NewClient(os.Getenv("RELOOP_API_KEY")) r.POST("/send-email", func(c *gin.Context) { params := &reloop.SendEmailParams{ From: "onboarding@reloop.sh", To: []string{"delivered@resend.dev"}, Subject: "Hello from Gin", HTML: "

Congrats on sending your first email via Reloop from Go Gin!

", } res, err := client.Emails.Send(context.Background(), params) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, res) }) r.Run(":8080") } ``` --- # examples/index.mdx Source: https://reloop.sh/docs/examples Markdown: https://reloop.sh/docs/examples.md # Examples Explore code examples and integration guides to connect Reloop using your favorite language, framework, or SMTP. ## Node.js Integrate Reloop into Node.js applications. Send emails in Next.js Server Actions and Route Handlers. Connect Reloop to an Express REST API backend. ## Python Integrate Reloop into Python applications. Asynchronous email sending with FastAPI. Configure email sending using Django's backend. Simple email templates in Flask. ## Go Integrate Reloop into Go applications. Send emails through a Go Gin web server. ## Ruby Integrate Reloop into Ruby applications. Configure Rails Action Mailer to send via Reloop. ## PHP Integrate Reloop into PHP applications. Configure Laravel Mail driver to route through Reloop. ## Rust Integrate Reloop into Rust applications. Asynchronous email dispatch inside an Axum web framework. ## SMTP Relay Configure standard SMTP library examples. Standard Node SMTP using Nodemailer. Built-in smtplib Python SMTP. Built-in net/smtp Go implementation. Standard PHP SMTP connection. Standard Ruby Net::SMTP integration. Lettre SMTP library for Rust. --- # examples/nodejs/express.mdx Source: https://reloop.sh/docs/examples/nodejs/express Markdown: https://reloop.sh/docs/examples/nodejs/express.md # Express Integration Reloop can be easily integrated into any Express application. ## Installation Install the official Node.js SDK: ```bash npm install reloop-email ``` ## Setup Environment Variables Add your Reloop API key to your environment variables or a `.env` file: ```env RELOOP_API_KEY=re_your_api_key_here ``` ## Sending an Email Here is an example of an Express route that sends an email: ```typescript const app = express(); const reloop = new Reloop(process.env.RELOOP_API_KEY); app.post('/send-email', async (req, res) => { try { const data = await reloop.mail.send({ from: 'onboarding@reloop.sh', to: 'delivered@resend.dev', subject: 'Hello from Express', html: '

Congrats on sending your first email via Reloop from an Express app!

', }); res.json(data); } catch (error) { res.status(500).json({ error }); } }); app.listen(3000, () => { console.log('App listening on port 3000'); }); ``` --- # examples/nodejs/nextjs.mdx Source: https://reloop.sh/docs/examples/nodejs/nextjs Markdown: https://reloop.sh/docs/examples/nodejs/nextjs.md # Next.js Integration Reloop is easy to integrate with Next.js, whether you are using the App Router or Pages Router. ## Installation First, install the official Node.js SDK: ```bash npm install reloop-email ``` ## Setup Environment Variables Add your Reloop API key to your `.env.local` file: ```env RELOOP_API_KEY=re_your_api_key_here ``` ## Sending an Email You can send emails from a Next.js Server Action or Route Handler. Here is an example of a Route Handler: ```typescript const reloop = new Reloop(process.env.RELOOP_API_KEY); try { const data = await reloop.mail.send({ from: 'onboarding@reloop.sh', to: 'delivered@resend.dev', subject: 'Hello World', html: '

Congrats on sending your first email via Reloop!

', }); return NextResponse.json(data); } catch (error) { return NextResponse.json({ error }, { status: 500 }); } } ``` --- # examples/php/laravel.mdx Source: https://reloop.sh/docs/examples/php/laravel Markdown: https://reloop.sh/docs/examples/php/laravel.md # Laravel Integration Integrate Reloop into your Laravel application. ## Installation Install the official PHP SDK via Composer: ```bash composer require reloop-labs/reloop-php ``` ## Setup Configuration Add the API key to your `.env` file: ```env RELOOP_API_KEY=re_your_api_key_here ``` ## Sending an Email Here is an example of sending an email from a controller: ```php mail->send([ 'from' => 'onboarding@reloop.sh', 'to' => 'delivered@resend.dev', 'subject' => 'Hello from Laravel', 'html' => '

Congrats on sending your first email via Reloop from Laravel!

', ]); return response()->json($response); } catch (\Exception $e) { return response()->json(['error' => $e->getMessage()], 500); } } } ``` --- # examples/python/django.mdx Source: https://reloop.sh/docs/examples/python/django Markdown: https://reloop.sh/docs/examples/python/django.md # Django Integration Integrate Reloop into your Django application using the Python SDK. ## Installation ```bash pip install reloop-email ``` ## Setup settings.py Add your API key to your settings: ```python # settings.py RELOOP_API_KEY = os.environ.get("RELOOP_API_KEY", "re_your_api_key_here") ``` ## Sending an Email Use the client within your Django views: ```python from django.http import JsonResponse from django.conf import settings from reloop_email import Reloop reloop = Reloop(api_key=settings.RELOOP_API_KEY) def send_email_view(request): if request.method == 'POST': try: result = reloop.mail.send({ "from": "onboarding@reloop.sh", "to": "delivered@resend.dev", "subject": "Hello from Django", "html": "

Congrats on sending your first email via Reloop from Django!

", }) if result.email_error: raise result.email_error return JsonResponse(result.response) except Exception as e: return JsonResponse({"error": str(e)}, status=500) ``` --- # examples/python/fastapi.mdx Source: https://reloop.sh/docs/examples/python/fastapi Markdown: https://reloop.sh/docs/examples/python/fastapi.md # FastAPI Integration Reloop can be easily integrated into any FastAPI application. ## Installation Install the official Python SDK: ```bash pip install reloop-email ``` ## Setup Environment Variables Add your API key to your environment: ```bash ``` ## Sending an Email Here is a simple FastAPI route that sends an email: ```python from fastapi import FastAPI, HTTPException from reloop_email import Reloop app = FastAPI() reloop = Reloop(api_key=os.environ.get("RELOOP_API_KEY")) @app.post("/send-email") async def send_email(): try: result = reloop.mail.send({ "from": "onboarding@reloop.sh", "to": "delivered@resend.dev", "subject": "Hello from FastAPI", "html": "

Congrats on sending your first email via Reloop from FastAPI!

", }) if result.email_error: raise result.email_error return result.response except Exception as e: raise HTTPException(status_code=500, detail=str(e)) ``` --- # examples/python/flask.mdx Source: https://reloop.sh/docs/examples/python/flask Markdown: https://reloop.sh/docs/examples/python/flask.md # Flask Integration Integrate Reloop into your Flask application. ## Installation ```bash pip install reloop-email ``` ## Sending an Email ```python from flask import Flask, jsonify from reloop_email import Reloop app = Flask(__name__) reloop = Reloop(api_key=os.environ.get("RELOOP_API_KEY")) @app.route("/send-email", methods=["POST"]) def send_email(): try: result = reloop.mail.send({ "from": "onboarding@reloop.sh", "to": "delivered@resend.dev", "subject": "Hello from Flask", "html": "

Congrats on sending your first email via Reloop from Flask!

", }) if result.email_error: raise result.email_error return jsonify(result.response) except Exception as e: return jsonify({"error": str(e)}), 500 if __name__ == "__main__": app.run(port=5000) ``` --- # examples/ruby/rails.mdx Source: https://reloop.sh/docs/examples/ruby/rails Markdown: https://reloop.sh/docs/examples/ruby/rails.md # Rails Integration Integrate Reloop into your Ruby on Rails application. ## Installation Add the official Ruby SDK to your Gemfile: ```ruby gem 'reloop-ruby' ``` And run: ```bash bundle install ``` ## Setup Credentials Set your API key in your environment variables: ```bash ``` ## Sending an Email Define a controller or a mailer to send emails: ```ruby class EmailsController < ApplicationController def create reloop = Reloop::Client.new(api_key: ENV['RELOOP_API_KEY']) begin response = reloop.mail.send( from: 'onboarding@reloop.sh', to: 'delivered@resend.dev', subject: 'Hello from Rails', html: '

Congrats on sending your first email via Reloop from Ruby on Rails!

' ) render json: response rescue => e render json: { error: e.message }, status: :internal_server_error end end end ``` --- # examples/rust/axum.mdx Source: https://reloop.sh/docs/examples/rust/axum Markdown: https://reloop.sh/docs/examples/rust/axum.md # Axum Integration Integrate Reloop into your Rust application using the Axum web framework. ## Installation Add the official Rust SDK and standard tokio dependencies to your `Cargo.toml`: ```toml [dependencies] axum = "0.7" tokio = { version = "1", features = ["full"] } reloop = "0.1" serde_json = "1" ``` ## Sending an Email ```rust use axum::{routing::post, Json, Router}; use reloop::ReloopClient; use serde_json::json; use std::env; #[tokio::main] async fn main() { let app = Router::new().route("/send-email", post(send_email)); let listener = tokio::net::TcpListener::bind("127.0.0.1:3000").await.unwrap(); axum::serve(listener, app).await.unwrap(); } async fn send_email() -> Result, (axum::http::StatusCode, String)> { let api_key = env::var("RELOOP_API_KEY").map_err(|_| { (axum::http::StatusCode::INTERNAL_SERVER_ERROR, "Missing API Key".to_string()) })?; let client = ReloopClient::new(api_key, None); match client.mail().send(json!({ "from": "onboarding@reloop.sh", "to": "delivered@resend.dev", "subject": "Hello from Axum", "html": "

Congrats on sending your first email via Reloop from Rust Axum!

", })).await { Ok(res) => Ok(Json(res)), Err(e) => Err((axum::http::StatusCode::INTERNAL_SERVER_ERROR, e.to_string())), } } ``` --- # examples/smtp/go.mdx Source: https://reloop.sh/docs/examples/smtp/go Markdown: https://reloop.sh/docs/examples/smtp/go.md # Go SMTP Integration Use Go's standard library `net/smtp` package to send emails. [View complete runnable example on GitHub ↗](https://github.com/reloop-labs/reloop-examples/tree/main/smtp-go) ## Code Example ```go package main "crypto/tls" "fmt" "net/smtp" "os" ) func main() { apiKey := os.Getenv("RELOOP_API_KEY") // SMTP server configuration smtpHost := "smtp.reloop.sh" smtpPort := "587" auth := smtp.PlainAuth("", apiKey, apiKey, smtpHost) to := []string{"delivered@resend.dev"} msg := []byte("To: delivered@resend.dev\r\n" + "Subject: Hello from Go net/smtp\r\n" + "Content-Type: text/html; charset=UTF-8\r\n" + "\r\n" + "

Congrats on sending your first email via Reloop SMTP using net/smtp!

\r\n") err := smtp.SendMail(smtpHost+":"+smtpPort, auth, "onboarding@reloop.sh", to, msg) if err != nil { fmt.Println("Error connecting:", err) return } defer conn.Close() client, err := smtp.NewClient(conn, host) if err != nil { fmt.Println("Error creating client:", err) return } defer client.Close() if err = client.Auth(auth); err != nil { fmt.Println("Auth failed:", err) return } if err = client.Mail(from); err != nil { fmt.Println("MAIL FROM failed:", err) return } for _, addr := range to { if err = client.Rcpt(addr); err != nil { fmt.Println("RCPT TO failed:", err) return } } w, err := client.Data() if err != nil { fmt.Println("DATA failed:", err) return } if _, err = w.Write(msg); err != nil { fmt.Println("Write failed:", err) return } if err = w.Close(); err != nil { fmt.Println("Close failed:", err) return } _ = client.Quit() fmt.Println("Email sent successfully!") } ``` --- # examples/smtp/introduction.mdx Source: https://reloop.sh/docs/examples/smtp/introduction Markdown: https://reloop.sh/docs/examples/smtp/introduction.md # SMTP Integration Reloop provides a high-performance SMTP relay that allows you to send emails from any application, mail client, or framework that supports SMTP. ## SMTP Credentials To connect to the Reloop SMTP server, use the following configuration settings: | Setting | Value | | :--- | :--- | | **Host** | `smtp.reloop.sh` | | **Port** | `587` (TLS) or `2525` / `25` | | **Username** | Your Reloop API Key | | **Password** | Your Reloop API Key | | **Encryption** | SSL/TLS (`465`) or STARTTLS (`587`) | ## Code Examples Configure standard SMTP library examples or explore step-by-step guides for your language: Standard Node SMTP using Nodemailer. Built-in smtplib Python SMTP. Built-in net/smtp Go implementation. Standard PHP SMTP connection. Standard Ruby Net::SMTP integration. Lettre SMTP library for Rust. --- # examples/smtp/nodemailer.mdx Source: https://reloop.sh/docs/examples/smtp/nodemailer Markdown: https://reloop.sh/docs/examples/smtp/nodemailer.md # Nodemailer SMTP Integration You can send emails through Reloop using **Nodemailer** in a Node.js environment. [View complete runnable example on GitHub ↗](https://github.com/reloop-labs/reloop-examples/tree/main/smtp-nodemailer) ## Installation Install Nodemailer: ```bash npm install nodemailer ``` ## Code Example ```javascript const nodemailer = require('nodemailer'); const transporter = nodemailer.createTransport({ host: 'smtp.reloop.sh', port: 587, secure: false, // true for port 465, false for other ports auth: { user: 'reloop', pass: process.env.RELOOP_API_KEY, }, }); async function main() { const info = await transporter.sendMail({ from: '"Onboarding" ', to: 'delivered@resend.dev', subject: 'Hello from Nodemailer', html: '

Congrats on sending your first email via Reloop SMTP using Nodemailer!

', }); console.log('Message sent: %s', info.messageId); } main().catch(console.error); ``` --- # examples/smtp/php.mdx Source: https://reloop.sh/docs/examples/smtp/php Markdown: https://reloop.sh/docs/examples/smtp/php.md # PHPMailer SMTP Integration Use the popular **PHPMailer** library to send transactional emails via Reloop. [View complete runnable example on GitHub ↗](https://github.com/reloop-labs/reloop-examples/tree/main/smtp-php) ## Installation Install PHPMailer via Composer: ```bash composer require phpmailer/phpmailer ``` ## Code Example ```php isSMTP(); $mail->Host = 'smtp.reloop.sh'; $mail->SMTPAuth = true; $mail->Username = 'reloop'; $mail->Password = getenv('RELOOP_API_KEY'); $mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS; $mail->Port = 465; // Recipients $mail->setFrom('onboarding@reloop.sh', 'Onboarding'); $mail->addAddress('delivered@resend.dev'); // Content $mail->isHTML(true); $mail->Subject = 'Hello from PHPMailer'; $mail->Body = '

Congrats on sending your first email via Reloop SMTP using PHPMailer!

'; $mail->send(); echo 'Message has been sent'; } catch (Exception $e) { echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}"; } ``` --- # examples/smtp/python.mdx Source: https://reloop.sh/docs/examples/smtp/python Markdown: https://reloop.sh/docs/examples/smtp/python.md # Python SMTP Integration Python's built-in `smtplib` and `email` packages can be used to send emails through Reloop SMTP. [View complete runnable example on GitHub ↗](https://github.com/reloop-labs/reloop-examples/tree/main/smtp-python) ## Code Example ```python from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText api_key = os.environ.get("RELOOP_API_KEY") # Create message msg = MIMEMultipart() msg['From'] = 'onboarding@reloop.sh' msg['To'] = 'delivered@resend.dev' msg['Subject'] = 'Hello from Python smtplib' body = '

Congrats on sending your first email via Reloop SMTP using smtplib!

' msg.attach(MIMEText(body, 'html')) try: # Connect to the server server = smtplib.SMTP('smtp.reloop.sh', 587) server.starttls() # Upgrade connection to secure server.login(api_key, api_key) # Send email server.sendmail(msg['From'], msg['To'], msg.as_string()) server.quit() print("Email sent successfully!") except Exception as e: print(f"Error: {e}") ``` --- # examples/smtp/ruby.mdx Source: https://reloop.sh/docs/examples/smtp/ruby Markdown: https://reloop.sh/docs/examples/smtp/ruby.md # Ruby SMTP Integration You can send emails through Reloop using Ruby's standard `net/smtp` library. [View complete runnable example on GitHub ↗](https://github.com/reloop-labs/reloop-examples/tree/main/smtp-ruby) ## Code Example ```ruby require 'net/smtp' require 'openssl' api_key = ENV['RELOOP_API_KEY'] message = <Congrats on sending your first email via Reloop SMTP using net/smtp!

MESSAGE_END begin Net::SMTP.start('smtp.reloop.sh', 587, 'localhost', api_key, api_key, :plain) do |smtp| smtp.send_message message, 'onboarding@reloop.sh', 'delivered@resend.dev' end puts "Email sent successfully!" rescue => e puts "Error: #{e.message}" end ``` --- # examples/smtp/rust.mdx Source: https://reloop.sh/docs/examples/smtp/rust Markdown: https://reloop.sh/docs/examples/smtp/rust.md # Rust SMTP Integration Send emails in Rust using the high-performance **Lettre** crate. [View complete runnable example on GitHub ↗](https://github.com/reloop-labs/reloop-examples/tree/main/smtp-rust) ## Installation Add `lettre` to your `Cargo.toml`: ```toml [dependencies] lettre = "0.11" ``` ## Code Example ```rust use lettre::transport::smtp::authentication::Credentials; use lettre::{Message, SmtpTransport, Transport}; use std::env; fn main() -> Result<(), Box> { let api_key = env::var("RELOOP_API_KEY")?; let email = Message::builder() .from("onboarding@reloop.sh".parse()?) .to("delivered@resend.dev".parse()?) .subject("Hello from Lettre") .header(lettre::message::header::ContentType::TEXT_HTML) .body(String::from("

Congrats on sending your first email via Reloop SMTP using Lettre!

"))?; let creds = Credentials::new("reloop".to_string(), api_key); // Open a local connection on port 587 let mailer = SmtpTransport::starttls_relay("smtp.reloop.sh")? .credentials(creds) .build(); // Send the email match mailer.send(&email) { Ok(_) => println!("Email sent successfully!"), Err(e) => panic!("Could not send email: {:?}", e), } Ok(()) } ``` --- # guides/account-quotas-limits.mdx Source: https://reloop.sh/docs/guides/account-quotas-limits Markdown: https://reloop.sh/docs/guides/account-quotas-limits.md Understanding Reloop sending quotas and rate limits. ## Overview This guide helps you understand and configure this sending feature in Reloop. ## Details Understanding your sending configuration is key to successful email delivery. Review the [Reloop dashboard](https://app.reloop.sh) for your current settings and limits. ## Configuration Check your current plan and usage in the [Reloop dashboard](https://app.reloop.sh/settings). Adjust your sending configuration based on your requirements and plan limits. Keep track of your sending volume and adjust as needed to stay within limits. ## Learn More - [Account Quotas and Limits](/docs/guides/account-quotas-limits) - [Sending Emails](/docs/learn/sending) - [Email Best Practices](/docs/integrations/email-best-practices) --- # guides/apple-branded-mail.mdx Source: https://reloop.sh/docs/guides/apple-branded-mail Markdown: https://reloop.sh/docs/guides/apple-branded-mail.md Apple Mail supports Brand Indicators for Message Identification (BIMI), which lets you display your brand logo next to your emails in the recipient's inbox. ## Prerequisites - A verified domain with DMARC set to `quarantine` or `reject` - A square SVG logo in Tiny PS format - A VMC (Verified Mark Certificate) from a trusted authority ## Setup Your DMARC policy must be set to at least `p=quarantine`: ``` v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com ``` Create a square SVG logo that meets BIMI requirements. The logo must be in Tiny PS format. Add a TXT record at `default._bimi.yourdomain.com`: ``` v=BIMI1; l=https://example.com/logo.svg; a=https://example.com/vmc.pem ``` BIMI adoption is growing but not yet universal. Apple Mail, Gmail, and Yahoo support it. Outlook does not yet. --- # guides/apple-private-relay.mdx Source: https://reloop.sh/docs/guides/apple-private-relay Markdown: https://reloop.sh/docs/guides/apple-private-relay.md How to send emails to Apple Private Relay addresses. ## Overview Understanding this topic is important for maintaining good email deliverability with Reloop. ## Key Points - Follow email sending best practices to maintain a strong sender reputation - Monitor your delivery rates in the [Reloop dashboard](https://app.reloop.sh) - Keep your email lists clean and up-to-date ## Best Practices Regularly check your delivery, bounce, and complaint rates in the Reloop dashboard. Ensure SPF, DKIM, and DMARC are properly configured for your domain. Always include an unsubscribe mechanism in marketing emails and honor opt-out requests promptly. For detailed guidance on email deliverability, see our [Email Best Practices](/docs/integrations/email-best-practices) skill documentation. ## Learn More - [Emails Going to Spam](/docs/guides/emails-going-to-spam) - [Warm-up Guide](/docs/guides/warmup-guide) - [Audience Hygiene](/docs/guides/audience-hygiene) - [Domains Guide](/docs/learn/domain) --- # guides/audience-hygiene.mdx Source: https://reloop.sh/docs/guides/audience-hygiene Markdown: https://reloop.sh/docs/guides/audience-hygiene.md Best practices for maintaining a clean email list. ## Overview Understanding this topic is important for maintaining good email deliverability with Reloop. ## Key Points - Follow email sending best practices to maintain a strong sender reputation - Monitor your delivery rates in the [Reloop dashboard](https://app.reloop.sh) - Keep your email lists clean and up-to-date ## Best Practices Regularly check your delivery, bounce, and complaint rates in the Reloop dashboard. Ensure SPF, DKIM, and DMARC are properly configured for your domain. Always include an unsubscribe mechanism in marketing emails and honor opt-out requests promptly. For detailed guidance on email deliverability, see our [Email Best Practices](/docs/integrations/email-best-practices) skill documentation. ## Learn More - [Emails Going to Spam](/docs/guides/emails-going-to-spam) - [Warm-up Guide](/docs/guides/warmup-guide) - [Audience Hygiene](/docs/guides/audience-hygiene) - [Domains Guide](/docs/learn/domain) --- # guides/avoid-gmail-spam.mdx Source: https://reloop.sh/docs/guides/avoid-gmail-spam Markdown: https://reloop.sh/docs/guides/avoid-gmail-spam.md Tips to prevent your emails from landing in Gmail spam. ## Overview This article covers common causes and solutions for this issue when using Reloop. ## Common Causes - Misconfigured DNS records - API key permissions not matching the domain - Rate limiting or account restrictions ## Resolution Steps Review your domain settings in the [Reloop dashboard](https://app.reloop.sh/domains) and ensure all DNS records are correctly configured. Ensure your API key has the correct permissions for the operation you're performing. Go to [API Keys](https://app.reloop.sh/api-keys) to review. If the issue persists, reach out to [Reloop support](https://reloop.sh/help) with your error details and domain information. ## Learn More - [Domain Not Verifying](/docs/guides/domain-not-verifying) - [Avoid MX Conflicts](/docs/guides/avoid-mx-conflicts) - [Emails Going to Spam](/docs/guides/emails-going-to-spam) --- # guides/avoid-mx-conflicts.mdx Source: https://reloop.sh/docs/guides/avoid-mx-conflicts Markdown: https://reloop.sh/docs/guides/avoid-mx-conflicts.md This guide moved to **[MX conflicts](/docs/guides/connect-domain/troubleshoot/mx-conflicts)** under Connect a domain. Also see [Sending vs receiving](/docs/guides/connect-domain/sending-vs-receiving) and [Root vs subdomain](/docs/guides/connect-domain/what-is-a-domain). --- # guides/avoid-outlook-spam.mdx Source: https://reloop.sh/docs/guides/avoid-outlook-spam Markdown: https://reloop.sh/docs/guides/avoid-outlook-spam.md Tips to prevent your emails from landing in Outlook spam. ## Overview This article covers common causes and solutions for this issue when using Reloop. ## Common Causes - Misconfigured DNS records - API key permissions not matching the domain - Rate limiting or account restrictions ## Resolution Steps Review your domain settings in the [Reloop dashboard](https://app.reloop.sh/domains) and ensure all DNS records are correctly configured. Ensure your API key has the correct permissions for the operation you're performing. Go to [API Keys](https://app.reloop.sh/api-keys) to review. If the issue persists, reach out to [Reloop support](https://reloop.sh/help) with your error details and domain information. ## Learn More - [Domain Not Verifying](/docs/guides/domain-not-verifying) - [Avoid MX Conflicts](/docs/guides/avoid-mx-conflicts) - [Emails Going to Spam](/docs/guides/emails-going-to-spam) --- # guides/change-email-address.mdx Source: https://reloop.sh/docs/guides/change-email-address Markdown: https://reloop.sh/docs/guides/change-email-address.md How to change the email address associated with your Reloop account. ## Overview Manage your Reloop account settings effectively to ensure smooth operation. ## Steps Navigate to the [Account Settings](https://app.reloop.sh/settings) page in your Reloop dashboard. Follow the on-screen instructions to update your account configuration. Review and confirm your changes. Some changes may require email verification. If you need assistance with account changes, contact [Reloop support](https://reloop.sh/help). ## Learn More - [Handling API Keys](/docs/guides/handling-api-keys) - [Account Quotas and Limits](/docs/guides/account-quotas-limits) --- # guides/configuring-tls.mdx Source: https://reloop.sh/docs/guides/configuring-tls Markdown: https://reloop.sh/docs/guides/configuring-tls.md The difference between opportunistic and enforced TLS. ## Overview Manage your Reloop account settings effectively to ensure smooth operation. ## Steps Navigate to the [Account Settings](https://app.reloop.sh/settings) page in your Reloop dashboard. Follow the on-screen instructions to update your account configuration. Review and confirm your changes. Some changes may require email verification. If you need assistance with account changes, contact [Reloop support](https://reloop.sh/help). ## Learn More - [Handling API Keys](/docs/guides/handling-api-keys) - [Account Quotas and Limits](/docs/guides/account-quotas-limits) --- # guides/connect-domain/add-domain.mdx Source: https://reloop.sh/docs/guides/connect-domain/add-domain Markdown: https://reloop.sh/docs/guides/connect-domain/add-domain.md This is the main path from “I have a domain” to “I can send as `@mydomain.com`.” ## Before you start - You can log in to the place that manages **nameservers** for the domain ([find your DNS provider](/docs/guides/connect-domain/find-dns-provider)). - Decide [root vs subdomain](/docs/guides/connect-domain/what-is-a-domain) — Reloop supports either, or both. - Decide if you need [receiving](/docs/guides/connect-domain/sending-vs-receiving) or only sending. ## Steps ![Domains list in the Reloop dashboard](/docs/images/docs/guides/connect-domain/overview/domains-list.png) Go to [Domains](https://reloop.sh/dashboard/domain) in the Reloop dashboard (or finish the onboarding domain step). Click **Add domain**. Enter the hostname you want to send from, for example: - `acme.com` (root) - `mail.acme.com` or `notifications.acme.com` (subdomain) Confirm organization and create the domain. Reloop generates DNS records and DKIM keys. On the domain page, Reloop shows a provider when nameservers are recognized. - **Auto-populate available** → continue with [Auto-populate](/docs/guides/connect-domain/auto-populate) - **Provider known, manual only** → [Manual setup](/docs/guides/connect-domain/manual-setup) + that host’s [guide](/docs/guides/connect-domain/providers) - **Unknown** → [Unknown provider](/docs/guides/connect-domain/providers/unknown-provider) Either complete the Domain Connect consent flow, or copy every required record into your DNS panel. Do not skip DKIM or SPF. Click **Verify** (or wait for automatic checks). Status moves through [pending → verifying → active](/docs/guides/connect-domain/verification/statuses) when public DNS matches. Use [Test your domain](/docs/guides/connect-domain/after/test-domain) to confirm SPF/DKIM/DMARC in a real inbox. ## Domain already in use If another Reloop organization already verified the domain, see [Domain already registered](/docs/guides/connect-domain/troubleshoot/domain-already-registered). --- # guides/connect-domain/after/change-dns.mdx Source: https://reloop.sh/docs/guides/connect-domain/after/change-dns Markdown: https://reloop.sh/docs/guides/connect-domain/after/change-dns.md ## Safe migration checklist From the old DNS host (or Reloop dashboard), note SPF, DKIM, DMARC, MX, and tracking values. Add the domain/zone at Cloudflare, Route 53, etc., and recreate **all** important records (website + mail), including Reloop’s. A day before, set TTL to 300s on old NS-related records if your registrar allows. Point NS to the new host. Keep the old zone until dig shows the new NS everywhere. After NS propagate, open the domain → **Verify**. Auto populate may appear if the new host supports Reloop’s Domain Connect template. ## Avoid - Deleting Reloop records on the old host **before** the new host is live - Switching NS without recreating MX if you still need inbound mail ## Related - [Wrong nameservers](/docs/guides/connect-domain/troubleshoot/wrong-nameservers) - [Find your DNS provider](/docs/guides/connect-domain/find-dns-provider) --- # guides/connect-domain/after/index.mdx Source: https://reloop.sh/docs/guides/connect-domain/after Markdown: https://reloop.sh/docs/guides/connect-domain/after.md Once status is **active**: - [Test your domain](/docs/guides/connect-domain/after/test-domain) - [Change DNS later](/docs/guides/connect-domain/after/change-dns) - [Remove a domain](/docs/guides/connect-domain/after/remove-domain) For inbox placement and reputation, continue with deliverability guides under [Guides](/docs/guides) (warmup, spam folders, suppression list). --- # guides/connect-domain/after/remove-domain.mdx Source: https://reloop.sh/docs/guides/connect-domain/after/remove-domain Markdown: https://reloop.sh/docs/guides/connect-domain/after/remove-domain.md ## In Reloop From [Domains](https://reloop.sh/dashboard/domain), open the domain and use the delete/remove action. After removal: - You can no longer send with that domain’s identities in Reloop - API/SMTP From addresses on that domain will fail authentication checks ## DNS cleanup (optional but recommended) At your DNS host, remove Reloop-specific rows you no longer need: - `reloop._domainkey` TXT - Reloop SPF include (or whole SPF if unused) - Reloop DMARC if you added it only for Reloop - Reloop MX / tracking CNAME Do **not** remove Google/Microsoft records if you still use those services. ## Re-adding later You can add the same domain again later and re-verify, subject to [already registered](/docs/guides/connect-domain/troubleshoot/domain-already-registered) rules if another org holds it. --- # guides/connect-domain/after/test-domain.mdx Source: https://reloop.sh/docs/guides/connect-domain/after/test-domain Markdown: https://reloop.sh/docs/guides/connect-domain/after/test-domain.md ## In Reloop 1. Confirm domain status is **active**. 2. Send a test message using the dashboard send flow or your API/SMTP integration with a `From` on the verified domain. 3. Open the message in Gmail/Outlook and check authentication results. ## What “good” looks like In Gmail → Show original (or equivalent): - `SPF: PASS` - `DKIM: PASS` (selector often `reloop`) - `DMARC: PASS` (when aligned) ## If authentication fails but Reloop says active - Wait for propagation on the receiver’s resolvers - Re-check public DNS with `dig` - Confirm you did not remove records after verify - See [Domain not verifying](/docs/guides/connect-domain/troubleshoot/not-verifying) if Reloop flipped back to failed ## Related - [Warm-up guide](/docs/guides/warmup-guide) - [Emails going to spam](/docs/guides/emails-going-to-spam) --- # guides/connect-domain/auto-populate.mdx Source: https://reloop.sh/docs/guides/connect-domain/auto-populate Markdown: https://reloop.sh/docs/guides/connect-domain/auto-populate.md **Auto-populate** uses the open [Domain Connect](https://www.domainconnect.org/) standard. Reloop opens your DNS provider, you approve a template, and the provider writes SPF, DKIM, DMARC, MX, and tracking records for you. Which hosts can do this **changes over time**. Reloop does not rely on a fixed allowlist in the docs — it checks live whether your domain’s DNS host supports Reloop’s Domain Connect template (`reloop.sh` / `email-setup` in the [Domain Connect Templates](https://github.com/Domain-Connect/Templates) registry). ## When you see the button On the domain page (and during onboarding DNS step): - **Auto populate** → your host can apply Reloop’s template; use this flow - **Open DNS settings** (or no Auto populate) → use [manual setup](/docs/guides/connect-domain/manual-setup) Trust the dashboard for your domain. A host that supports Domain Connect in general may still lack Reloop’s template until they onboard it. ## How the flow works Reloop runs Domain Connect **discovery** against your domain (`_domainconnect` DNS + provider API) and confirms the Reloop template is available. A new tab opens on your DNS host. Sign in if needed, review the records, and confirm. After success you are redirected back (or you can return manually). Click **Verify** if status is still pending. Reloop re-checks live discovery when you click Auto populate. If the provider dropped the template or discovery fails, you get an error toast and should continue manually. ## What gets applied The Reloop Domain Connect template typically applies: - DKIM TXT on `reloop._domainkey` - SPF via SPFM / merge (`include:reloop.sh`) - DMARC on `_dmarc` - MX for sending/receiving as defined in the template - Tracking CNAME `link` → `link.reloop.sh` Exact groups can depend on template version; the consent screen lists what will change. ## If Auto-populate fails See [Auto-populate failed](/docs/guides/connect-domain/troubleshoot/auto-populate-failed) for: - Popup blocked - User cancelled consent - Template not found at provider - Domain Connect not supported on that zone You can always fall back to [manual setup](/docs/guides/connect-domain/manual-setup) using the same dashboard records. ## Security notes - Only approve the flow while logged into **your** DNS account for that domain. - Reloop signs Domain Connect apply URLs; do not reuse apply links from untrusted sources. - After you approve, check the records in your DNS panel, then click **Verify** in Reloop. --- # guides/connect-domain/dns-records-explained.mdx Source: https://reloop.sh/docs/guides/connect-domain/dns-records-explained Markdown: https://reloop.sh/docs/guides/connect-domain/dns-records-explained.md When you add a domain, Reloop generates the exact records to publish. Always prefer the dashboard values over examples here. Your **DKIM key is unique**. ## Quick map | Purpose | Typical type | Example host | What it does | | --- | --- | --- | --- | | **SPF** | TXT | `@` | Authorizes Reloop to send for your domain | | **DKIM** | TXT | `reloop._domainkey` | Cryptographic signature so receivers trust the message | | **DMARC** | TXT | `_dmarc` | Policy if SPF/DKIM fail (Reloop suggests a strict policy) | | **Sending MX** | MX | `@` | Used in Reloop’s sending/return-path setup as shown in the dashboard | | **Receiving MX** | MX | `@` or your subdomain | Routes **inbound** mail to Reloop (`inbound.reloop.sh`) when receiving is on | | **Tracking** | CNAME | `link` | Click/open tracking (`link.yourdomain.com` → `link.reloop.sh`) | Hosts and whether MX/tracking appear depend on your domain settings (apex vs subdomain, sending/receiving toggles). ## SPF (Sender Policy Framework) **Type:** TXT **Example value:** ``` v=spf1 include:reloop.sh -all ``` SPF lists which servers may send mail as your domain. Reloop’s include is `include:reloop.sh` (hosted product). You may only have **one SPF TXT** on a given host. If you already have SPF (Google, Microsoft, Mailchimp, …), **merge** Reloop’s `include:reloop.sh` into that record — do not add a second SPF. See [SPF conflicts](/docs/guides/connect-domain/troubleshoot/spf-conflicts). ## DKIM (DomainKeys Identified Mail) **Type:** TXT **Host:** usually `reloop._domainkey` (selector `reloop`) **Value:** looks like: ``` v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A... ``` The long `p=` string is your public key. Reloop signs outbound mail with the matching private key. If the TXT is truncated, quoted wrongly, or split incorrectly, verification fails. See [DKIM / DMARC typos](/docs/guides/connect-domain/troubleshoot/dkim-dmarc-typos). ## DMARC **Type:** TXT **Host:** `_dmarc` **Example value:** ``` v=DMARC1; p=reject; ``` DMARC tells receivers what to do when authentication fails. Reloop’s default template uses `p=reject`. If you already have DMARC for Google/Microsoft, review carefully before overwriting — you may keep your existing policy and align later. ## MX (mail exchange) MX records control **where inbound mail is delivered**. - **Sending-only:** you may still see MX-related rows in Reloop; follow the dashboard. Reloop sending does not require replacing your existing inbox MX if you only send from Reloop. - **Receiving enabled:** Reloop expects MX pointing at `inbound.reloop.sh` (priority typically `10`). That **will conflict** with another inbox already using MX on the same hostname. Use a [separate hostname](/docs/guides/connect-domain/what-is-a-domain) for Reloop receiving, or see [MX conflicts](/docs/guides/connect-domain/troubleshoot/mx-conflicts). ## Tracking CNAME **Type:** CNAME **Host:** usually `link` **Value:** `link.reloop.sh` Used for branded click/open tracking links (`https://link.yourdomain.com/...`). Conflicts if `link` already points elsewhere, or if your provider disallows CNAMEs in that spot. See [Tracking CNAME issues](/docs/guides/connect-domain/troubleshoot/tracking-cname). ## How to read a Reloop dashboard row For each row, match three things in your DNS UI: 1. **Type** (TXT / MX / CNAME) 2. **Name / Host** — some UIs want `@` for the root; others want a blank host or the bare domain 3. **Value** — paste exactly; for MX also set **Priority** Provider-specific quirks (Cloudflare proxy, GoDaddy host field, Route 53 hosted zone) are in each [provider guide](/docs/guides/connect-domain/providers). ## Related - [Manual setup](/docs/guides/connect-domain/manual-setup) - [Auto-populate](/docs/guides/connect-domain/auto-populate) - [Sending vs receiving](/docs/guides/connect-domain/sending-vs-receiving) --- # guides/connect-domain/find-dns-provider.mdx Source: https://reloop.sh/docs/guides/connect-domain/find-dns-provider Markdown: https://reloop.sh/docs/guides/connect-domain/find-dns-provider.md You need to know **who hosts your nameservers** before you can publish Reloop records (or before Auto-populate can work). ## Method 1 — Reloop dashboard (easiest) 1. Add the domain at [Domains](https://reloop.sh/dashboard/domain) if you have not already. 2. Open the domain detail page. 3. Reloop reads public nameservers and shows a **Provider** chip when it recognizes the host (Cloudflare, GoDaddy, Vercel, Namecheap, …). If Reloop shows a provider: - **Auto populate** on the domain page → use [Auto-populate](/docs/guides/connect-domain/auto-populate) - **Otherwise** → open that host’s guide under [Provider guides](/docs/guides/connect-domain/providers) and add records manually If Reloop cannot detect a provider, use Method 2 or 3. ## Method 2 — Registrar control panel 1. Log in where you **bought / renew** the domain. 2. Open the domain → **Nameservers** / **DNS** / **Manage DNS**. 3. Note the nameserver hostnames, for example: | Nameserver contains | Likely DNS host | | --- | --- | | `cloudflare.com` | Cloudflare | | `vercel-dns.com` | Vercel | | `domaincontrol.com` | GoDaddy | | `registrar-servers.com` | Namecheap | | `awsdns-` | AWS Route 53 | | `domainchief.` | Domain Chief | | `dnsowl.com` / `hostsilo.com` | NameSilo | | `ui-dns.` | IONOS | | `squarespace.com` / `googledomains.com` | Squarespace | | `hetzner.com` / `hetzner.de` | Hetzner | | `hostinger.` / `dns-parking.com` | Hostinger | | `gandi.net` | Gandi | | `porkbun.com` | Porkbun | | `strato.de` / `strato-hosting.eu` | Strato | | `dreamhost.com` / `dreamhosters.com` | DreamHost | | `as207960.net` / `glauca.digital` | Glauca Digital | | `wordpress.com` / `wp.com` | WordPress.com | | `plesk` | Plesk (or your host’s Plesk panel) | Then open the matching [provider guide](/docs/guides/connect-domain/providers). ## Method 3 — Public lookup ### In the browser Use any “DNS lookup” / “whois” tool and query **NS** records for your domain (e.g. `acme.com`). ### On your computer ```bash dig NS acme.com +short # or nslookup -type=NS acme.com ``` Example output: ``` ada.ns.cloudflare.com. bob.ns.cloudflare.com. ``` → DNS is on **Cloudflare**. ## Bought at A, DNS at B If the registrar is GoDaddy but NS are Cloudflare, **ignore GoDaddy’s DNS record editor** for Reloop. Edit Cloudflare. Full explanation: [Registrar vs DNS host](/docs/guides/connect-domain/registrar-vs-dns-host). ## Still stuck? Use the [Unknown provider](/docs/guides/connect-domain/providers/unknown-provider) guide: open whatever panel controls the NS hosts you found, and paste the records from Reloop. --- # guides/connect-domain/index.mdx Source: https://reloop.sh/docs/guides/connect-domain Markdown: https://reloop.sh/docs/guides/connect-domain.md Reloop can send (and optionally receive) email for **any domain you control**. You do not need to buy the domain from Reloop — register it anywhere, point DNS at the records Reloop shows you, and verify. The [Domains](https://reloop.sh/dashboard/domain) page lists every sending domain in your organization, with status and shortcuts to DNS guides. ![Domains list in the Reloop dashboard](/docs/images/docs/guides/connect-domain/overview/domains-list.png) ## What you will do Open [Domains](https://reloop.sh/dashboard/domain) and click **Add domain**. Enter `example.com` or a subdomain like `mail.example.com`. Reloop detects your nameservers when possible. If you are unsure who hosts DNS, see [Find your DNS provider](/docs/guides/connect-domain/find-dns-provider). On the domain page, follow the banner Reloop shows for your DNS host — see below. Click **Verify** (or wait for automatic checks). When status is **active**, you can send from that domain. ## Configuring DNS from the banner After you add a domain, Reloop shows a banner based on the nameservers it detected. - If the banner names your DNS host and offers **Auto populate**, click it. Approve the consent screen at your provider and Reloop’s records are written for you. More detail: [Auto populate](/docs/guides/connect-domain/auto-populate). - If the banner does not offer Auto populate (or you prefer not to use it), copy the Type / Host / Value rows from the dashboard into your DNS panel. More detail: [Manual setup](/docs/guides/connect-domain/manual-setup) and the [DNS guides](/docs/guides/connect-domain/providers). Either way, Reloop checks public DNS afterward and marks the domain verified when the records match. ## New to DNS? Start here — you do not need to be a network engineer: 1. [What is a domain?](/docs/guides/connect-domain/what-is-a-domain) 2. [What is DNS?](/docs/guides/connect-domain/what-is-dns) 3. [Registrar vs DNS host](/docs/guides/connect-domain/registrar-vs-dns-host) 4. [Find your DNS provider](/docs/guides/connect-domain/find-dns-provider) 5. [DNS records Reloop needs](/docs/guides/connect-domain/dns-records-explained) ## Full map - **Setup** — [Add a domain](/docs/guides/connect-domain/add-domain) · [What is a domain?](/docs/guides/connect-domain/what-is-a-domain) · [Sending vs receiving](/docs/guides/connect-domain/sending-vs-receiving) - **DNS guides** — [All DNS hosts](/docs/guides/connect-domain/providers) - **Verification** — [Statuses](/docs/guides/connect-domain/verification/statuses) · [Propagation](/docs/guides/connect-domain/verification/propagation) - **Troubleshoot** — [Domain not verifying](/docs/guides/connect-domain/troubleshoot/not-verifying) and more - **After connect** — [Test](/docs/guides/connect-domain/after/test-domain) · [Change DNS](/docs/guides/connect-domain/after/change-dns) · [Remove](/docs/guides/connect-domain/after/remove-domain) Always copy values from your domain’s page in the Reloop dashboard. Examples in docs use placeholders; your DKIM key and hosts are unique to your domain. --- # guides/connect-domain/manual-setup.mdx Source: https://reloop.sh/docs/guides/connect-domain/manual-setup Markdown: https://reloop.sh/docs/guides/connect-domain/manual-setup.md ## Prerequisites - Domain added in [Reloop](https://reloop.sh/dashboard/domain) - Access to the DNS panel for the **nameserver** host ([find your provider](/docs/guides/connect-domain/find-dns-provider)) ## Steps Go to [Domains](https://reloop.sh/dashboard/domain) → select the domain. Keep this tab open — you will copy each row. Use **Open DNS settings** in Reloop if shown, or jump to the matching [provider guide](/docs/guides/connect-domain/providers). For every required row in Reloop: 1. Choose the same **type** (TXT, MX, CNAME) 2. Set **name/host** as shown (`@`, `reloop._domainkey`, `_dmarc`, `link`, …) 3. Paste **value** exactly 4. For MX, set **priority** (often `10`) 5. Save Provider UIs differ: - Some want blank host instead of `@` - Some auto-append your domain — do not enter `reloop._domainkey.acme.com` if the UI already adds `acme.com` - Cloudflare: keep records **DNS only** (grey cloud) unless you know you need a proxy (almost never for mail TXT/MX) If an SPF TXT already exists, merge `include:reloop.sh` into it. Do not create a second SPF. See [SPF conflicts](/docs/guides/connect-domain/troubleshoot/spf-conflicts). Return to Reloop → **Verify**. Allow time for [propagation](/docs/guides/connect-domain/verification/propagation) if checks fail immediately. ## Checklist before you verify - [ ] Edited the DNS host that matches your **NS** records (not only the registrar invoice) - [ ] DKIM TXT is complete (long `p=` value not cut off) - [ ] Only one SPF record on that host - [ ] MX only changed if you intend to ([sending vs receiving](/docs/guides/connect-domain/sending-vs-receiving)) - [ ] Tracking CNAME host is free or intentionally replaced ## Provider-specific guides See the full list: [Provider guides](/docs/guides/connect-domain/providers). ## Related - [DNS records explained](/docs/guides/connect-domain/dns-records-explained) - [Domain not verifying](/docs/guides/connect-domain/troubleshoot/not-verifying) --- # guides/connect-domain/providers/cloudflare.mdx Source: https://reloop.sh/docs/guides/connect-domain/providers/cloudflare Markdown: https://reloop.sh/docs/guides/connect-domain/providers/cloudflare.md ## Add domain to Reloop First, log in to [Reloop](https://reloop.sh/dashboard/domain) and [add a domain](/docs/guides/connect-domain/add-domain). It is [best practice to use a subdomain](/docs/guides/connect-domain/what-is-a-domain) (for example `mail.example.com` or `team.example.com`) instead of the root domain (`example.com`). A subdomain keeps sending reputation separate and is especially important if you enable receiving with Reloop. ## Automatic setup (recommended) The fastest way to verify your domain on Cloudflare is **Auto populate** in Reloop. This uses [Domain Connect](https://www.domainconnect.org/) to configure your DNS records. 1. Go to your [Domains](https://reloop.sh/dashboard/domain) page in Reloop and open the domain. 2. (Optional) If you want to receive emails, turn **Receiving** on before Auto-populate so the inbound MX is included. [Learn more below](#receiving-emails). 3. Click **Auto populate**. 4. Authorize Reloop in Cloudflare and approve the records. 5. Return to Reloop — records are written automatically.