> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.awardspring.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.awardspring.com/_mcp/server.

# Dry runs

Send `dry_run=true` and a write is fully validated but never persisted. You get the response body you would have received; the database is untouched and no side effects fire.

Either form works:

```bash
# query parameter
curl -X POST "https://api.awardspring.com/api/v1/donors?dry_run=true" \
  -H "X-Spring-API-Key: YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"role":"Individual","first_name":"Jordan","last_name":"Rivera"}'

# or header
curl -X POST https://api.awardspring.com/api/v1/donors \
  -H "X-Spring-API-Key: YOUR_KEY" \
  -H "Dry-Run: true" \
  -H "Content-Type: application/json" \
  -d '{"role":"Individual","first_name":"Jordan","last_name":"Rivera"}'
```

## What is actually checked

A dry run is not a schema check. It runs the same rules the real call runs, including the ones that need to look at your data:

* required and conditionally-required fields
* value constraints and allowed values
* referenced records exist and belong to your institution — award cycles, funds, donors, assigned users
* unrecognised field names
* uniqueness, such as an email already in use

So a dry run that succeeds is strong evidence the real call will succeed. That is the point: it is worth more than a validation you write yourself, because it is the same code path.

## Reading the response

You get the resource you would have created, with one tell: **on a create, the returned `id` is `null`.** The record was never written, so no [ID](/ids) was ever assigned.

Never store an id from a dry run. If you are checking whether a create succeeded by testing for an id, a dry run correctly reads as "did not create anything".

## Idempotency keys are not consumed

A dry run leaves an [`Idempotency-Key`](/idempotency) unused. You can validate a request and then send the same key for real. This makes the natural pattern safe:

1. Dry-run the request to confirm it validates.
2. Send it for real with an `Idempotency-Key`.
3. Retry on failure with the same key.

## Why this matters more here than elsewhere

There is no sandbox environment and no test-mode key, so there is nowhere to practise a write harmlessly. Dry runs are the closest thing available: they are the only way to exercise a real write path, against real data, without changing anything.

Use them for anything you have not sent before — a new integration, a changed payload shape, or a bulk operation where the first record failing tells you far more cheaply than the hundredth.