# Promo-code inventory with code pools
> Source: /guides/patterns/code-pools
> Upload and monitor promo-code inventory in bulk.

Code pools hold redemption codes that benefits hand out — a block of codes you
have generated elsewhere, loaded into Journey so it can issue them one at a
time.

## The sequence [#the-sequence]

<Steps>
  <Step title="Create a pool">
    `code-pools` create, which gives you a pool reference to add codes against.
  </Step>
  <Step title="Add codes in batches">
    Add up to **10,000 codes** per request, each optionally carrying an
    `expiresAt`.
  </Step>
  <Step title="Monitor the pool">
    List pools and read a single pool to track what has been consumed and what
    remains.
  </Step>
</Steps>

## Retries are safe [#retries-are-safe]

<Note>
  **Duplicates are reported, not rejected.** Adding a batch that overlaps one
  you already uploaded returns a report of which codes were duplicates, rather
  than failing the request. A retry after a timeout cannot corrupt the pool or
  double-add.
</Note>

That makes the add operation unusually forgiving, but still send an
`Idempotency-Key`: it gives you a replay of the original response rather than a
second pass over 10,000 codes.

## Things that catch people out [#things-that-catch-people-out]

- **Codes must be unique within the pool.** Generate them with enough entropy
  that collisions are not a routine occurrence.
- **Batch size is a hard ceiling, not a target.** If you are loading hundreds
  of thousands of codes, chunk them and checkpoint between batches so a failure
  does not mean starting over.
- **`expiresAt` is per code**, not per pool, so a single pool can hold codes
  with different lifetimes.
- **Set up pools before the benefit goes live.** A published benefit that draws
  from an empty pool has nothing to hand out.

## Scopes [#scopes]

Reading pools and writing codes are separate permissions. See the
[API reference](/api-reference/partner/explorer/code-pools/list-pools) for the
requirement on each endpoint.
