## Generate a dataset from scratch

`datasets.invent(DatasetInventParams**kwargs)  -> DatasetInventResponse`

**post** `/api/v1/datasets/invent`

Creates a dataset and starts generating it from your domain selections. Returns immediately — poll `GET /datasets/{id}` for the status and `GET /datasets/{id}/download` once it reports `succeeded`. Set Set `estimate: true` to price a request without generating anything.

### Parameters

- `name: Optional[str]`

  Display name for the invented dataset.

- `training_type: Optional[Literal["instruction_dataset", "preference_pairs"]]`

  Shape of the generated data — the same field and values as `datasets.run`. `instruction_dataset` produces prompt/completion rows; `preference_pairs` produces ranked completion pairs. Note this is the shape of the DATA, not the training method (elsewhere `training_type` means LoRA vs full fine-tuning). Defaults to `instruction_dataset`. The download carries the generated text in `enhanced_prompt` / `enhanced_completion`; `original_*` are null, since invented data has no source rows it was derived from.

  - `"instruction_dataset"`

  - `"preference_pairs"`

- `domains: Optional[Sequence[str]]`

  Domain codes to generate from, e.g. `medical`. Supply at least one of `domains` or `subdomains` — omit this and the domains are inferred from the parents of your `subdomains`. When you do supply it, it is authoritative: a subdomain naming a domain that is not listed here is rejected rather than silently added. Retrieve the valid codes from `GET /datasets/invent/domains`.

- `subdomains: Optional[Sequence[str]]`

  Narrow generation to specific subdomains, as `domain.subdomain` codes e.g. `medical.symptoms_diagnosis`. Qualified by their domain because a bare code can belong to more than one (`wildlife` sits under both agriculture and animal nature). Requested domains with no subdomain listed here are generated across all of theirs. Supply at least one of `domains` or `subdomains`. Retrieve the valid codes from `GET /datasets/invent/domains`.

- `rows: int`

  Number of rows to generate, subject to your plan’s per-launch row cap. Treat it as a target: the delivered count can land slightly either side of it, so read `row_count` on the finished dataset for what was actually produced.

- `language_expansion: Optional[LanguageExpansion]`

  Optionally translate or localize the generated rows into further languages. Credits are billed on the POST-expansion row count, so setting this quotes and charges above `rows`. `sample_rate` (0-1) is the share of rows expanded.

  - `type: Literal["translate", "localize"]`

    Expansion mode. `translate` produces one new row variant per target language; `localize` produces one new row variant per country/language pair.

    - `"translate"`

    - `"localize"`

  - `languages: Optional[Sequence[str]]`

    Target ISO 639-1 language codes (required when type=translate, forbidden when type=localize). Validated against the supported language list at request time; unknown values return 400 with a sample of supported codes.

  - `pairs: Optional[Iterable[LanguageExpansionPair]]`

    Country/language pairs (required when type=localize, forbidden when type=translate). Each pair is validated against the supported country/language pair list at request time.

    - `country: str`

      ISO 3166-1 alpha-2 country code.

    - `language: str`

      ISO 639-1 language code.

  - `sample_rate: float`

    Fraction (0.01–1) of input rows that are expanded per target. Output rows ≈ input × (1 + sample_rate × target_count). Required. Credits are billed on the expanded output row count.

- `prompt: Optional[str]`

  Free-text description of the data you want, in your own words — the wizard shows this as "Dataset Details". Drives the semantic search that selects rows, so a specific prompt yields more relevant data, and it is woven into the generation instructions. Written for you from your domain selections when omitted.

- `estimate: Optional[bool]`

  Price the request without creating or charging anything. Mirrors `datasets.run` — the response carries the same fields either way, with the dataset fields null when this is set.

- `idempotency_key: Optional[str]`

  Client-supplied key making retries safe. Repeating a request with the same key returns the original dataset instead of generating again.

### Returns

- `class DatasetInventResponse: …`

  - `estimate: bool`

    True when this response priced the request without running it.

  - `id: Optional[str]`

    Dataset id, or null on an estimate. Pass it straight to `finetune_jobs.create` or `autoscientist.create` once the status is `succeeded`.

  - `name: str`

    Display name, echoed from the request or the default applied for you.

  - `training_type: Literal["instruction_dataset", "preference_pairs"]`

    Shape of the generated data, echoed from the request.

    - `"instruction_dataset"`

    - `"preference_pairs"`

  - `domains: List[str]`

    Domain codes the generation covers, echoed from the request — including any inferred from `subdomains`.

  - `subdomains: List[str]`

    Subdomain codes the generation is narrowed to, if any.

  - `rows: Optional[int]`

    Number of rows requested.

  - `status: Optional[Literal["pending", "running", "awaiting_input", 2 more]]`

    Lifecycle status, or null on an estimate. A fresh generation is always `running`; poll `GET /datasets/{dataset_id}` until it reports `succeeded` or `failed`.

    - `"pending"`

    - `"running"`

    - `"awaiting_input"`

    - `"succeeded"`

    - `"failed"`

  - `created_at: Optional[datetime]`

    When the dataset was created, or null on an estimate.

  - `estimated_credits: float`

    Credits this generation consumes. Billed on the post-expansion row count, so a translated request quotes above its `rows`. Invent pricing is still provisional, so treat the figure as indicative.

  - `available_credits: float`

    Credits currently available to your team.

### Example

```python
import os
from adaption import Adaption

client = Adaption(
    api_key=os.environ.get("ADAPTION_API_KEY"),  # This is the default and can be omitted
)
response = client.datasets.invent(
    rows=1000,
)
print(response.id)
```

#### Response

```json
{
  "estimate": false,
  "id": "3f1b9c62-6f3e-4a1e-9a5c-0b7d2f8e4a10",
  "name": "Clinical Q&A",
  "training_type": "instruction_dataset",
  "domains": [
    "medical"
  ],
  "subdomains": [
    "medical.symptoms_diagnosis"
  ],
  "rows": 1000,
  "status": "running",
  "created_at": "2026-08-03T16:12:04.000Z",
  "estimated_credits": 800,
  "available_credits": 5000
}
```
