diff --git a/category/security.mdx b/category/security.mdx index 93a0b25e..92abd6e3 100644 --- a/category/security.mdx +++ b/category/security.mdx @@ -103,4 +103,14 @@ holistic security model in-depth, and speaks to our vision for building verifiab Overview of Turnkey's responsible disclosure program + + Overview of Turnkey's responsible disclosure program + + diff --git a/concepts/users/best-practices.mdx b/concepts/users/best-practices.mdx index be625e3a..eae0ee0b 100644 --- a/concepts/users/best-practices.mdx +++ b/concepts/users/best-practices.mdx @@ -5,17 +5,13 @@ description: "This page describes some best practices to consider as you set up ## Managing users -**Enforce a security policy of least privilege for your users** - Users on Turnkey should have the minimum required privilege to accomplish their job. When setting up users, consider this for their access type and policies that will grant the user permissions. +**Enforce a security policy of least privilege for your users** Users on Turnkey should have the minimum required privilege to accomplish their job. When setting up users, consider this for their access type and policies that will grant the user permissions. -**Use user tags to create groups of users with equal permissions** -Referencing user tags in policies instead of individual users allows for clearer management of permissions. +**Use user tags to create groups of users with equal permissions** Referencing user tags in policies instead of individual users allows for clearer management of permissions. -**When creating new users, consider verifying onboarding before adding tags** -When inviting a web user to your Turnkey organization, you should consider real-life verification to confirm that they have onboarded correctly before granting that user permissions via tags. Granting tags prior to verification could provide an attacker permissions in your Turnkey organization if they are able to access the signup link. +**When creating new users, consider verifying onboarding before adding tags** When inviting a web user to your Turnkey organization, you should consider real-life verification to confirm that they have onboarded correctly before granting that user permissions via tags. Granting tags prior to verification could provide an attacker permissions in your Turnkey organization if they are able to access the signup link. -**Regularly review and remove unused users, user tags, and policies** -If a user is unused or the user has left your company, you should remove them from your Turnkey organization to avoid compromise. +**Regularly review and remove unused users, user tags, and policies** If a user is unused or the user has left your company, you should remove them from your Turnkey organization to avoid compromise. **Attach multiple authenticators to web users** @@ -33,6 +29,10 @@ This reduces the ways that a hacker could acquire your API key. Our SDKs and CLI This allows you to isolate permissions and differentiate activities between those applications. In the case that an API key is lost or stolen, it also allows you to revoke access solely for the affected application. +**Use IP allowlisting to restrict where API keys can be used from** + +Turnkey supports [IP allowlisting](/security/ip-allowlisting) at both the organization and per-API-key level. For production keys, configure an allowlist that limits requests to known server IPs or CIDR ranges — this ensures that even a leaked key cannot be used from an unauthorized network. + **Use a secret management system to protect your API keys** Tools like Hashicorp Vault or AWS KMS can help you protect your API key from malicious access. @@ -66,8 +66,8 @@ Within this principle of least privilege, Some actions should be treated more sensitively: -* Adding policies -* Signing transactions +- Adding policies +- Signing transactions **Use allowlisting if you only send to a set of addresses** @@ -79,4 +79,4 @@ If your use case for Turnkey only requires you to send funds to a certain set of "effect": "EFFECT_ALLOW", "condition": "eth.tx.to == ''" } -``` +``` \ No newline at end of file diff --git a/docs.json b/docs.json index 990e00ee..c73a7a5c 100644 --- a/docs.json +++ b/docs.json @@ -872,6 +872,7 @@ "category/security", "security/our-approach", "security/non-custodial-key-mgmt", + "security/ip-allowlisting", "security/secure-enclaves", "security/quorum-deployments", "security/verifiable-data", diff --git a/embedded-wallets/features/overview.mdx b/embedded-wallets/features/overview.mdx index af174bf6..f819d4cb 100644 --- a/embedded-wallets/features/overview.mdx +++ b/embedded-wallets/features/overview.mdx @@ -5,57 +5,57 @@ sidebarTitle: "Overview" - + - - + - + - + + - + {" "} - + {" "} - + {" "} - + - + - + - + - + - + - + - - + + \ No newline at end of file diff --git a/getting-started/launch-checklist.mdx b/getting-started/launch-checklist.mdx index bce88878..0e1a558f 100644 --- a/getting-started/launch-checklist.mdx +++ b/getting-started/launch-checklist.mdx @@ -10,7 +10,7 @@ description: "Before deploying your Turnkey integration in production, take a lo - If you are on an Enterprise plan, confirm your production organization ID with your account rep. -Double check our [resource limits](/concepts/resource-limits) and [rate limits](/faq#do-you-have-any-rate-limits-in-place-in-your-public-api) to ensure your implementation will not trigger these limits at production scale.** + Double check our [resource limits](/concepts/resource-limits) and [rate limits](/faq#do-you-have-any-rate-limits-in-place-in-your-public-api) to ensure your implementation will not trigger these limits at production scale.\*\* ## Security @@ -19,6 +19,7 @@ Double check our [resource limits](/concepts/resource-limits) and [rate limits]( - Ensure any team members with critical permissions, especially root quorum members, have set up at least two authenticators for their account (e.g., touchID plus a hardware authenticator like a Yubikey). - Avoid using root user permissions for routine operations and instead use standard users with permissions explicitly granted via policies to limit the surface area of a compromised user. - Confirm that all API keys are stored securely and not embedded in exposed or vulnerable parts of the codebase. API keys should be stored in a secure, encrypted environment and should never be hard-coded in publicly accessible repositories or client-side code. +- Enable IP allowlisting on your organization and any production API keys to restrict API access to known, authorized networks. For keys used in automated backend workflows, lock them down to specific server IPs or CIDR ranges to prevent misuse even in the event of a key compromise. ## Logging @@ -29,4 +30,4 @@ Double check our [resource limits](/concepts/resource-limits) and [rate limits]( - Activity submission is optimistically synchronous. In most cases activities will be completed and returned right away (synchronously), but if there is a lot of activity in a single organization, activities will be processed asynchronously. Make sure you handle PENDING activities by polling a few times until their completion. You can use [createActivityPoller](https://github.com/tkhq/sdk/blob/d9ed2aefc92d298826a40e821f959b019ea1936f/packages/http/src/async.ts#L101) to do this if you're using our Typescript SDK. - Implement retry strategies for API calls, adjusting for various error types and avoiding over-retrying on critical failures. Incorporate [rate limiting](/faq#do-you-have-any-rate-limits-in-place-in-your-public-api) and exponential backoff in retry mechanisms. -- Set up monitoring to detect and alert on patterns of failures +- Set up monitoring to detect and alert on patterns of failures \ No newline at end of file diff --git a/production-checklist/company-wallet.mdx b/production-checklist/company-wallet.mdx index 1011b04d..871cb079 100644 --- a/production-checklist/company-wallet.mdx +++ b/production-checklist/company-wallet.mdx @@ -3,19 +3,16 @@ title: "Company Wallets implementation guide" description: "Implementing Company Wallets with Turnkey" --- -Turnkey's infrastructure provides a secure, flexible way to manage crypto operations at scale, letting you automate everything from -routine payments and treasury transfers to smart contract deployments and NFT minting. +Turnkey's infrastructure provides a secure, flexible way to manage crypto operations at scale, letting you automate everything from routine payments and treasury transfers to smart contract deployments and NFT minting. -In this guide, we'll walk through the key decisions you'll face integrating Turnkey, and how to design a high-throughput workflow -without compromising on security or user experience. +In this guide, we'll walk through the key decisions you'll face integrating Turnkey, and how to design a high-throughput workflow without compromising on security or user experience. ## Wallet structure: how to organize and scale your wallets Every transaction starts with a wallet. The way you structure them will shape how scalable and maintainable your automation setup is. -**Option 1:** Single wallet with many accounts (HD path fan-out) -By default, Turnkey wallets use a hierarchical deterministic (HD) structure. That means you can generate unlimited accounts -from a single wallet seed, each with its own address. This is ideal for: +**Option 1:** Single wallet with many accounts (HD path fan-out)\ +By default, Turnkey wallets use a hierarchical deterministic (HD) structure. That means you can generate unlimited accounts from a single wallet seed, each with its own address. This is ideal for: - Managing multiple user deposit addresses - Creating large numbers of accounts for batching or privacy @@ -23,20 +20,17 @@ from a single wallet seed, each with its own address. This is ideal for: This approach scales well and stays simple: one wallet, one policy, multiple accounts. -**Option 2:** Multiple wallets in a single org +**Option 2:** Multiple wallets in a single org\ Use this when you need separation by use case. For example: - One wallet for treasury ops - One for NFT mints - One for sequencing contracts -Policies can be set at the wallet level to enforce clear boundaries (e.g. only certain users or services can touch the NFT minting wallet). -Note Turnkey's [resource limits](https://docs.turnkey.com/concepts/resource-limits#resource-limits) and ensure your intended -scaled implementation fits within those limits. +Policies can be set at the wallet level to enforce clear boundaries (e.g. only certain users or services can touch the NFT minting wallet). Note Turnkey's [resource limits](https://docs.turnkey.com/concepts/resource-limits#resource-limits) and ensure your intended scaled implementation fits within those limits. -**Option 3:** Separate sub-orgs per wallet -This option is best when you need strict isolation — e.g. multi-tenant environments, or wallets with different authentication requirements. -Each sub-org has its own root users and policy namespace. Downside: more setup, more moving parts. +**Option 3:** Separate sub-orgs per wallet\ +This option is best when you need strict isolation — e.g. multi-tenant environments, or wallets with different authentication requirements. Each sub-org has its own root users and policy namespace. Downside: more setup, more moving parts. Most teams use a combination: they generate many accounts under a few wallets and reserve sub-orgs for user-facing or high-risk cases. @@ -44,7 +38,7 @@ Most teams use a combination: they generate many accounts under a few wallets an Transaction automation can be reactive, proactive, or user-driven. The right model depends on your use case. -**Event-driven (most common):** +**Event-driven (most common):**\ A transaction is triggered by an external event — a webhook, an internal job, or an offchain signal. Examples: - Market resolution triggers a payout @@ -53,21 +47,21 @@ A transaction is triggered by an external event — a webhook, an internal job, Use a background worker or event system to translate that trigger into a signing request. -**Scheduled:** +**Scheduled:**\ Useful for treasury management, yield compounding, or periodic distribution flows. Run a job hourly/daily and trigger signing from there. -**Manual with automation fallback:** -Sometimes a human should have the final say, but you want the transaction to be ready to go. You can submit a tx to Turnkey -that requires approval, then notify a signer via Slack, email, or dashboard. +**Manual with automation fallback:**\ +Sometimes a human should have the final say, but you want the transaction to be ready to go. You can submit a tx to Turnkey that requires approval, then notify a signer via Slack, email, or dashboard. -Tip: Think in terms of "intent capture" (when does your system decide something needs to happen) vs. "signing execution" -(when and how does it actually get signed). +Tip: Think in terms of "intent capture" (when does your system decide something needs to happen) vs. "signing execution" (when and how does it actually get signed). ## Policy model: what rules do you want enforced? Policies are your automation safety net. Every action goes through the policy engine before it's allowed, and is explicitly denied by default. -You'll want to decide: +For an additional layer of network-level protection, consider enabling [IP allowlisting](/security/ip-allowlisting) to restrict which source IPs can make API requests in the first place — a useful complement to policy rules for backend automation keys. + +You'll want to decide:\ **How many approvers?** - Use single-party approvals for low-risk flows (e.g. daily payouts) @@ -98,17 +92,16 @@ Most automation systems have 3-5 core policies and evolve them as their product All interfaces (CLI, SDK, API) go through the same policy and enclave flow. The only difference is where your logic lives. -**CLI:** +**CLI:**\ Best for prototyping or scripting internal workflows (e.g. rotate a key, create a wallet). You can also use it in CI pipelines. -**SDK:** -Ideal for integrating into apps or backend services. Available in multiple programming languages. Handles signing, retries, -and activity submission. +**SDK:**\ +Ideal for integrating into apps or backend services. Available in multiple programming languages. Handles signing, retries, and activity submission. -**Direct API:** +**Direct API:**\ Use this if you want full control or are building from a non-standard language. Slightly more effort to get right, but fully supported. -**Dashboard:** +**Dashboard:**\ Not for automation — but useful for manual approval flows, audit trails, and monitoring. **Common pattern:** @@ -120,22 +113,17 @@ Not for automation — but useful for manual approval flows, audit trails, and m Graveyard - add back when IndexedDb launches -By default, session keys are stored in IndexedDB when running in the browser. These keys are non-extractable and can't be accessed by your app, -by Turnkey, or by anything else running on the page. On mobile, session keys will typically be stored in the device's secure storage layer -(e.g. Keychain or Keystore) depending on the SDK and environment. +By default, session keys are stored in IndexedDB when running in the browser. These keys are non-extractable and can't be accessed by your app, by Turnkey, or by anything else running on the page. On mobile, session keys will typically be stored in the device's secure storage layer (e.g. Keychain or Keystore) depending on the SDK and environment. -The biggest decision is how long sessions should last. Longer-lived sessions reduce friction, enabling users to stay signed in across reloads, -tabs, or app restarts. For most embedded wallet use cases, long-lived sessions in IndexedDB strike a good balance between usability and safety. +The biggest decision is how long sessions should last. Longer-lived sessions reduce friction, enabling users to stay signed in across reloads, tabs, or app restarts. For most embedded wallet use cases, long-lived sessions in IndexedDB strike a good balance between usability and safety. -Scoping +Scoping\ You'll also want to decide whether your sessions should be scoped. -Scoped sessions allow you to define exactly what a given session key is allowed to do — and enforce it via Turnkey's policy engine. For example, -you can issue sessions that: +Scoped sessions allow you to define exactly what a given session key is allowed to do — and enforce it via Turnkey's policy engine. For example, you can issue sessions that: - are read-only - can only sign transactions below a certain value - can only interact with specific contracts or functions (e.g. a swap function on Uniswap) -This gives you a flexible way to enforce step-up authentication flows (e.g. OTP for read-only, passkey + OTP for full signing), -build approval-based transaction flows, or safely grant session access in more complex environments. +This gives you a flexible way to enforce step-up authentication flows (e.g. OTP for read-only, passkey \+ OTP for full signing), build approval-based transaction flows, or safely grant session access in more complex environments. \ No newline at end of file diff --git a/production-checklist/production-checklist.mdx b/production-checklist/production-checklist.mdx index 84fc51e0..ac8bb7d7 100644 --- a/production-checklist/production-checklist.mdx +++ b/production-checklist/production-checklist.mdx @@ -10,9 +10,7 @@ description: "This checklist contains recommendations and steps specifically for - If you are on an Enterprise plan, confirm your production organization ID with your account rep. - Double check our [resource limits](/concepts/resource-limits) and [rate - limits](/faq#do-you-have-any-rate-limits-in-place-in-your-public-api) to - ensure your implementation will not trigger these limits at production scale. + Double check our [resource limits](/concepts/resource-limits) and [rate limits](/faq#do-you-have-any-rate-limits-in-place-in-your-public-api) to ensure your implementation will not trigger these limits at production scale. ## Security @@ -21,6 +19,7 @@ description: "This checklist contains recommendations and steps specifically for - Ensure any team members with critical permissions, especially root quorum members, have set up at least two authenticators for their account (e.g., touchID plus a hardware authenticator like a Yubikey). - Avoid using root user permissions for routine operations and instead use standard users with permissions explicitly granted via policies to limit the surface area of a compromised user. - Confirm that all API keys are stored securely and not embedded in exposed or vulnerable parts of the codebase. API keys should be stored in a secure, encrypted environment and should never be hard-coded in publicly accessible repositories or client-side code. +- Enable IP allowlisting on your organization and any production API keys to restrict API access to known, authorized networks. For keys used in automated backend workflows, lock them down to specific server IPs or CIDR ranges to prevent misuse even in the event of a key compromise. ## Logging @@ -31,4 +30,4 @@ description: "This checklist contains recommendations and steps specifically for - Activity submission is optimistically synchronous. In most cases activities will be completed and returned right away (synchronously), but if there is a lot of activity in a single organization, activities will be processed asynchronously. Make sure you handle PENDING activities by polling a few times until their completion. You can use [createActivityPoller](https://github.com/tkhq/sdk/blob/d9ed2aefc92d298826a40e821f959b019ea1936f/packages/http/src/async.ts#L101) to do this if you're using our Typescript SDK. - Implement retry strategies for API calls, adjusting for various error types and avoiding over-retrying on critical failures. Incorporate [rate limiting](/faq#do-you-have-any-rate-limits-in-place-in-your-public-api) and exponential backoff in retry mechanisms. -- Set up monitoring to detect and alert on patterns of failures +- Set up monitoring to detect and alert on patterns of failures \ No newline at end of file diff --git a/security/ip-allowlisting.mdx b/security/ip-allowlisting.mdx new file mode 100644 index 00000000..6b138173 --- /dev/null +++ b/security/ip-allowlisting.mdx @@ -0,0 +1,349 @@ +--- +title: "IP Allowlisting" +description: "Restrict API access to your Turnkey organization based on the source IP address of incoming requests." +--- + +IP Allowlist is a security feature that lets you define a set of trusted CIDR blocks (IP ranges), ensuring that only requests originating from known, authorized networks can interact with your organization's resources. + + + + Applies to all API requests made to your organization, regardless of which API key is used. Acts as a global default. + + + + Applies only to requests authenticated with a specific API key. Overrides the organization-level allowlist for that key when present. + + + +This feature is ideal for: + +- Locking down production API keys to specific server IPs +- Preventing API access from outside your organization's network +- Enforcing per-key access controls across different environments + +## Before you begin + + + Enabling an organization-level allowlist with no CIDR rules configured will **block all API traffic**. Stage your rules with `enabled: false` first, verify they're correct, then set `enabled: true`. + + +- **The org-level allowlist must be enabled for API key-level rules to take effect.** If the org-level allowlist is disabled, API key-level allowlists are not enforced. +- **Dashboard actions are never subject to IP allowlisting.** You can always use the Dashboard to manage your configuration, even if you misconfigure your rules. +- **Unresolvable source IPs default to fail-open.** In rare cases, intermediary infrastructure may prevent Turnkey from resolving a request's source IP. The `onEvaluationError` parameter controls whether these requests are allowed (fail-open) or denied (fail-closed). It defaults to `ALLOW`. + + + **IP Allowlisting **is available to [**Enterprise clients**](https://www.turnkey.com/pricing) on the **Scale tier** or higher. If you would like to access this feature please reach out to your Turnkey representative. + + +## How it works + + + + Submit one or more CIDR blocks (e.g., `192.168.1.0/24`) with optional human-readable labels (e.g., `"Office VPN"`). + + + When you're ready, set `enabled: true` to begin enforcement. Via the Dashboard, you can add rules and enable separately. Via the API, you can define rules and enable in a single `set_ip_allowlist` call — but we recommend staging rules with `enabled: false` first to verify your configuration. + + + Any API request whose source IP does not fall within an allowed CIDR block is rejected automatically. + + + Query the current allowlist with `get_ip_allowlist`, then resubmit the full updated rule set via `set_ip_allowlist`. There is no partial-update operation — each call fully replaces the existing rules. + + + + + IP Allowlist operations follow Turnkey's [activity model](/concepts/transaction-management). Creating or removing an allowlist is an auditable activity that goes through policy evaluation and approval before execution. + + +## Organization-level vs. API key-level + +| Aspect | Organization-level | API key-level | +| --- | --- | --- | +| Scope | All API requests for the org | Requests using a specific API key only | +| `publicKey` parameter | Omitted or `null` | Set to the API key's public key | +| `enabled` parameter | Required (`true` or `false`) | Not applicable — always enforced if present | +| Precedence | Default for all keys | Overrides the org-level allowlist for that key | +| Limit | One per organization | One per API key | + +### Precedence rules + +- The org-level allowlist **must be enabled** for API key-level allowlists to be evaluated. +- If an API key has its own allowlist, only that key-level allowlist is checked for requests using that key. +- If an API key does not have its own allowlist, the org-level allowlist is checked (if enabled). +- If neither exists, requests are allowed from any IP. + +## CIDR rules + +### Format + +Both IPv4 and IPv6 are supported. The maximum prefix length is `/20` for IPv4 and `/48` for IPv6. + +| Format | Examples | +| --- | --- | +| IPv4 | `10.0.0.0/20`, `192.168.1.0/24`, `203.0.113.42/32` (single IP) | +| IPv6 | `2001:db8::/48`, `::1/128` (single IP) | + +CIDRs are normalized on submission — e.g., `192.168.1.100/24` becomes `192.168.1.0/24`. + +### Labels + +Each rule accepts an optional `label` string for human-readable identification (e.g., `"Office VPN"`, `"Production Server"`). Labels are stored and returned in responses but have no effect on enforcement. + +### Limits and validation + +- Maximum of **10 IPv4 CIDRs** and **10 IPv6 CIDRs** per allowlist (20 total) +- Duplicate CIDRs within a single submission are automatically deduplicated — only the first occurrence and its label are kept +- The `rules` array can be empty (creates an allowlist with no rules) +- Invalid CIDRs are rejected with an error indicating the index and value that failed + +### Replacement semantics + +`set_ip_allowlist` always **fully replaces** the existing rule set. To add a single rule without losing existing ones, first retrieve the current rules with `get_ip_allowlist`, append your new rule, then resubmit the complete list. + +## API reference + +All endpoints use `HTTP POST` and require a signed request body stamped with your API key. + +| Endpoint | Description | +| --- | --- | +| `POST /public/v1/submit/set_ip_allowlist` | Create or update an IP allowlist | +| `POST /public/v1/submit/remove_ip_allowlist` | Remove an IP allowlist | +| `POST /public/v1/query/get_ip_allowlist` | Retrieve the current IP allowlist | + +### Set IP allowlist + +Creates or updates an IP allowlist. If one already exists for the specified scope, it is fully replaced. + +```json Request body +{ + "type": "ACTIVITY_TYPE_SET_IP_ALLOWLIST", + "timestampMs": "", + "organizationId": "", + "parameters": { + "rules": [ + { + "cidr": "", + "label": "" + } + ], + "enabled": true, + "publicKey": "", + "onEvaluationError": "ALLOW" + } +} +``` + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `type` | string | Yes | Must be `"ACTIVITY_TYPE_SET_IP_ALLOWLIST"` | +| `timestampMs` | string | Yes | Current timestamp in milliseconds (epoch) — used for request liveness verification | +| `organizationId` | string | Yes | Your Turnkey organization ID | +| `parameters.rules` | array | Yes | Array of allowlist rules. Can be empty. | +| `parameters.rules[].cidr` | string | Yes | CIDR block (e.g., `"192.168.1.0/24"`, `"2001:db8::/48"`) | +| `parameters.rules[].label` | string | No | Optional human-readable label (e.g., `"Office VPN"`) | +| `parameters.enabled` | boolean | No | Whether the allowlist is enforced. Only meaningful for org-level policies. | +| `parameters.publicKey` | string | No | Public key of an API key. If omitted, the allowlist applies at the org level. | +| `parameters.onEvaluationError` | string | No | `"ALLOW"` or `"DENY"` — controls behavior when the source IP cannot be determined | + +```json Response +{ + "activity": { + "id": "", + "organizationId": "", + "status": "ACTIVITY_STATUS_COMPLETED", + "type": "ACTIVITY_TYPE_SET_IP_ALLOWLIST", + "intent": { + "setIpAllowlistIntent": { + "rules": [ + { "cidr": "10.0.0.0/20", "label": "Office" }, + { "cidr": "192.168.1.0/24", "label": "VPN" } + ], + "enabled": true + } + }, + "result": { + "setIpAllowlistResult": {} + } + } +} +``` + +### Remove IP allowlist + +Deletes an IP allowlist and all its associated rules. After removal, access falls back to the next applicable allowlist or is allowed from all IPs. + +```json Request body +{ + "type": "ACTIVITY_TYPE_REMOVE_IP_ALLOWLIST", + "timestampMs": "", + "organizationId": "", + "parameters": { + "publicKey": "" + } +} +``` + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `type` | string | Yes | Must be `"ACTIVITY_TYPE_REMOVE_IP_ALLOWLIST"` | +| `timestampMs` | string | Yes | Current timestamp in milliseconds (epoch) | +| `organizationId` | string | Yes | Your Turnkey organization ID | +| `parameters.publicKey` | string | No | If omitted, removes the org-level allowlist. If set, removes the allowlist for that specific API key. | + +### Get IP allowlist + +Retrieves the current IP allowlist and rules for an organization or specific API key. + +```json Request body +{ + "organizationId": "", + "publicKey": "" +} +``` + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `organizationId` | string | Yes | Your Turnkey organization ID | +| `publicKey` | string | No | If provided, returns the allowlist for that API key. If omitted, returns the org-level allowlist. | + +```json Response +{ + "allowlist": { + "organizationId": "", + "publicKey": "", + "enabled": true, + "rules": [ + { + "cidr": "10.0.0.0/20", + "label": "Office", + "createdAt": "1717000000000" + }, + { + "cidr": "192.168.1.0/24", + "label": "VPN", + "createdAt": "1717000000000" + } + ] + } +} +``` + + + If the allowlist has been removed, `get_ip_allowlist` returns an `allowlist` object with an empty `rules` array. + + +### Data types + +#### `IpAllowlistRule` (response) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `cidr` | string | Yes | CIDR block | +| `label` | string | No | Human-readable label (empty string if not set) | +| `createdAt` | string | No | Creation timestamp as millisecond epoch string | + +#### `IpAllowlist` (response) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `organizationId` | string | Yes | The organization this allowlist belongs to | +| `publicKey` | string | No | The API key this applies to. `null` for org-level policies. | +| `enabled` | boolean | No | Whether the allowlist is active. Only present for org-level policies. | +| `rules` | `IpAllowlistRule[]` | Yes | Array of allowlist rules | + +## Code examples + + + + ```shell + curl -X POST https://api.turnkey.com/public/v1/submit/set_ip_allowlist \ + -H "Content-Type: application/json" \ + -H "X-Stamp: " \ + -d '{ + "type": "ACTIVITY_TYPE_SET_IP_ALLOWLIST", + "timestampMs": "1717000000000", + "organizationId": "", + "parameters": { + "enabled": true, + "rules": [ + { "cidr": "10.0.0.0/20", "label": "Office" }, + { "cidr": "192.168.1.0/24", "label": "VPN" } + ] + } + }' + ``` + + + ```shell + curl -X POST https://api.turnkey.com/public/v1/submit/set_ip_allowlist \ + -H "Content-Type: application/json" \ + -H "X-Stamp: " \ + -d '{ + "type": "ACTIVITY_TYPE_SET_IP_ALLOWLIST", + "timestampMs": "1717000000000", + "organizationId": "", + "parameters": { + "publicKey": "", + "rules": [ + { "cidr": "10.0.1.0/24", "label": "Production Server" } + ] + } + }' + ``` + + + ```shell + curl -X POST https://api.turnkey.com/public/v1/query/get_ip_allowlist \ + -H "Content-Type: application/json" \ + -H "X-Stamp: " \ + -d '{ + "organizationId": "" + }' + ``` + + + Since `set_ip_allowlist` always replaces all rules, adding a single rule requires fetching first, then resubmitting the full list. + + ```shell + # 1. Get the current allowlist + curl -X POST https://api.turnkey.com/public/v1/query/get_ip_allowlist \ + -H "Content-Type: application/json" \ + -H "X-Stamp: " \ + -d '{ + "organizationId": "" + }' + + # 2. Resubmit with existing rules + new rule appended + curl -X POST https://api.turnkey.com/public/v1/submit/set_ip_allowlist \ + -H "Content-Type: application/json" \ + -H "X-Stamp: " \ + -d '{ + "type": "ACTIVITY_TYPE_SET_IP_ALLOWLIST", + "timestampMs": "1717000000000", + "organizationId": "", + "parameters": { + "enabled": true, + "rules": [ + { "cidr": "10.0.0.0/20", "label": "Office" }, + { "cidr": "192.168.1.0/24", "label": "VPN" }, + { "cidr": "203.0.113.0/24", "label": "New Rule" } + ] + } + }' + ``` + + + ```shell + curl -X POST https://api.turnkey.com/public/v1/submit/remove_ip_allowlist \ + -H "Content-Type: application/json" \ + -H "X-Stamp: " \ + -d '{ + "type": "ACTIVITY_TYPE_REMOVE_IP_ALLOWLIST", + "timestampMs": "1717000000000", + "organizationId": "", + "parameters": {} + }' + ``` + + \ No newline at end of file