# Custom Config

**Custom Config** answers "**give me exactly these identity fields, under my custody**". You pick which document fields the user discloses, and your organization becomes the store of record: the verified result and every disclosed value are delivered to your webhook endpoint, and **Self never stores any of it**.

Where the other workspaces answer a yes/no question and Self retains the proof, **Custom Config is built for teams with their own compliance or data-residency requirements** who need the raw data and don't want a copy left behind.

:::cta{title="Enterprise only" href="mailto:sales@self.xyz" button="Contact sales"}
Custom Config is in early access and requires an Enterprise plan. Disclosed data is delivered directly to your server; Self stores none of it.
:::

## How custody changes the deal

- **Self keeps nothing.** The result and the disclosed fields are never written to Self's storage. Once delivered, no copy exists anywhere on Self's side.
- **Your server holds the only copy.** Self sends each result to your [webhook endpoint](/docs/self-enterprise/dashboard/webhooks/) once, and that delivery is the sole permanent record. Save what you need when it arrives; there is nothing to fetch from Self later.
- **A live webhook endpoint is mandatory.** You can't deploy a Custom Config or start live verifications until your organization has one set up, otherwise users would verify into the void. Test verifications are exempt, so you can build your receiver first.
- **You receive the proof on every outcome.** Even when a verification fails or expires, whatever proof material exists is delivered to you rather than kept by Self.

For the exact payload fields and error codes behind this (`storage_state: 'skipped'`, the `409 no_webhook_endpoint` rejection), see the [event catalog](/docs/self-enterprise/webhooks/events/) and [error handling](/docs/self-enterprise/sdk/error-handling/).

## What the user proves

- They hold a **genuine, government-signed document** (at your chosen [security level](/docs/self-enterprise/flows/disclosures/#security-level)).
- Optionally, that they **clear the OFAC sanctions list**.

## What you receive

- A `valid` / `invalid` result via the [`verification.completed` webhook](/docs/self-enterprise/webhooks/events/), with `product: 'custom_config'` for routing on a shared endpoint.
- **Every disclosed field you requested**, in `proof_attributes` on a `valid` event, using the same reveal mechanism as [Pre-KYC's Additional data](/docs/self-enterprise/flows/disclosures/#additional-data-reveals).
- The **raw proof envelope** in `proof`, on every status.
- A [nullifier](/docs/self-enterprise/get-started/how-it-works/#one-account-per-person-nullifiers) for duplicate detection.

For example, a `valid` webhook for a config that requests **all seven fields** with OFAC on carries:

```json
{
  "ofac": true,
  "name": "JANE DOE",
  "idNumber": "L898902C3",
  "dateOfBirth": "900115",
  "gender": "F",
  "nationality": "USA",
  "expiryDate": "300630",
  "issuingState": "USA"
}
```

`ofac` echoes the enforced rule; the rest is one key per enabled disclosure, present only on `valid` (fields the document didn't carry are dropped). Values arrive as they appear on the document, so passport dates use the MRZ `YYMMDD` format.

## Rules you can configure

| Rule             | Default     | Notes                                                                                                                           |
| ---------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------- |
| Disclosed fields | —           | Required, at least one: `Full name`, `ID number`, `Date of birth`, `Gender`, `Nationality`, `Expiration date`, `Issuing state`. |
| OFAC check       | on          | Match against the US Treasury OFAC sanctions list; only pass/fail is disclosed.                                                 |
| Security level   | Hi-security | Standard also accepts non-chip documents.                                                                                       |

Two more ways Custom Config differs from the other workspaces:

- **Backend mode only.** On-chain verification can't deliver disclosed data to your webhook, so it's rejected at deploy. See [Verification modes](/docs/self-enterprise/flows/verification-modes/).
- **Many active configs.** The other workspaces keep one active configuration at a time; a Custom Config workspace runs as many as you need side by side, each with its own `flowId`. The dashboard lists them with per-config **Activity log** and **Settings** actions.

## Use cases

- **Regulated onboarding with your own KYC vault**: collect name, date of birth, and document number straight into your compliance systems, with document-grade assurance and no third-party copy.
- **Data-residency requirements**: keep disclosed PII inside your own infrastructure and jurisdiction from the moment it exists.
- **Custom risk models**: feed exact document fields into your own scoring instead of consuming pass/fail answers.

## Cost

**25 credits** per completed verification. See [Credits and usage](/docs/self-enterprise/billing/credits-and-usage/).
