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

# Dedicated IPs and pools

> Allocate sending addresses, manage movable pool membership, and warm up traffic.

Dedicated IPs belong to your account. An IP can be unassigned or belong to a pool,
and can move between pools without being released. A pool groups addresses for
configuration sets; it does not own their allocations.

## Allocate and group addresses

<Tabs>
  <Tab title="Console">
    Open Email and **IP pools** to create a pool. In **Dedicated IPs**, request
    an address and optionally choose the pool. The address is allocated for you.
    Open a pool's **Member IPs** tab to attach or detach allocated addresses.
  </Tab>

  <Tab title="API">
    Create a pool with `POST /v1/ip-pools`:

    ```json theme={null}
    {"name":"transactional","description":"Transactional sending"}
    ```

    Request an address with `POST /v1/dedicated-ips`:

    ```json theme={null}
    {"ip_pool":"transactional"}
    ```

    Omit `ip_pool` to leave the allocation unassigned. The service chooses the
    address; customers do not supply an IP address in this request.
  </Tab>

  <Tab title="CLI">
    Save the JSON requests from the API tab, in order, as `request-1.json`, `request-2.json`. Use your configured account and region.

    ```bash theme={null}
    basaltic email ip-pool create --from-file request-1.json
    basaltic email dedicated-ip request --from-file request-2.json
    ```
  </Tab>

  <Tab title="Go">
    Save the JSON requests from the API tab, in order, as `request-1.json`, `request-2.json`. Configure credentials, account, and region through the SDK environment variables.

    ```go theme={null}
    package main

    import (
    	"context"
    	"encoding/json"
    	"fmt"
    	"os"

    	basaltic "github.com/basaltic-sh/sdk-go"
    	"github.com/basaltic-sh/sdk-go/email"
    )

    func readJSON(path string, value any) error {
    	data, err := os.ReadFile(path)
    	if err != nil {
    		return err
    	}
    	return json.Unmarshal(data, value)
    }

    func run() error {
    	ctx := context.Background()
    	cfg, err := basaltic.NewConfig(ctx)
    	if err != nil {
    		return err
    	}
    	client := email.New(cfg)
    	var request1 email.CreateIPPoolRequest
    	if err := readJSON("request-1.json", &request1); err != nil {
    		return err
    	}
    	result1, err := client.CreateIPPool(ctx, &request1)
    	if err != nil {
    		return err
    	}
    	fmt.Printf("%+v\n", result1)
    	var request2 email.RequestDedicatedIPRequest
    	if err := readJSON("request-2.json", &request2); err != nil {
    		return err
    	}
    	result2, err := client.RequestDedicatedIP(ctx, &request2)
    	if err != nil {
    		return err
    	}
    	fmt.Printf("%+v\n", result2)
    	return nil
    }

    func main() {
    	if err := run(); err != nil {
    		fmt.Fprintln(os.Stderr, err)
    		os.Exit(1)
    	}
    }
    ```
  </Tab>
</Tabs>

Update membership with `PATCH /v1/dedicated-ips/{dedicated_ip_id}`. A `ip_pool`
string selects a pool by UUID, name, or CRN; `null` detaches; omission preserves
the assignment. The response's optional `ip_pool` is a ResourceRef.

## Warmup

Warmup states are `new`, `warming`, and `warm`. A new address starts outside
the active sending rotation. Start warming before expecting the pool to select it.
The warmup percentage controls eligibility relative to shared sending capacity;
it is not a fixed messages-per-second limit.

Automatic warmup advances with completed UTC days containing successful sending
activity on the allocation. Idle time alone does not advance it. The default
sequence is 1%, 2%, 4%, 8%, 16%, 32%, 64%, and 100%. Inspect
`warmup_percentage` and `warmup_started_at` rather than assuming calendar age
means an address is ready.

## Detach, delete, and release

Detaching an IP leaves it allocated. Deleting a pool leaves its IPs unassigned
and clears configuration-set bindings to that pool. Releasing an IP returns the
allocation and stops its use for future selection. These are distinct operations.
Use the resource's danger zone for deletion or release.

A configuration set without an eligible pool address can use shared platform
sending IPs. Check the outgoing message's `outbound_ip` and [Email metrics](/email/metrics)
to understand traffic and outcomes.


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