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

# Create experiment

> Creates a new experiment request for the Adaptyv Foundry platform.

The payload captures the target (from the catalog), antibody sequences,
replicate plan, assay parameters, optional metadata, and an optional webhook
for notifications. By default, experiments are created
in Draft status so clients can review inputs before submission.

Set `skip_draft: true` to bypass Draft status and submit directly for processing.
This is useful for automated pipelines with pre-validated payloads that
don't require manual review. The experiment will be created in
"Waiting for confirmation" status instead of Draft.

API-originated experiments are automatically assigned to the organization's
API submissions project for traceability.

# ExperimentSpec fields

Validation is strict: fields that are not applicable to a given experiment
type (e.g., `method` on a non-binding type) cause a 400 rejection. Multiple
validation errors are accumulated and returned together so callers can fix
everything in one round-trip.

| Field | Type | Description |
|-------|------|-------------|
| `experiment_type` | string | **Required.** One of `affinity`, `screening`, `thermostability`, `fluorescence`, `expression`, `epitope_binning`, `enzyme_activity`. |
| `method` | string | Required for `affinity`/`screening` (`bli` or `spr`). **Rejected** for all other types. |
| `target_id` | string | Target UUID from the catalog. Required for `affinity`, `screening`, and `epitope_binning`. **Rejected** for non-binding types. |
| `sequences` | object | **Required.** Map of sequence name to amino acid string. `epitope_binning` requires exactly 4-28 sequences in multiples of 4. |
| `n_replicates` | integer | Optional for most types (default 3, range 1-5). **Rejected** for `epitope_binning`. |
| `antigen_concentrations` | array | `affinity` only; optional, defaults to `[1000.0, 316.2, 100.0, 31.6, 0.0]` nM. |
| `parameters` | object | Optional. Experiment-specific settings |

# Sequence Formats

The `sequences` field accepts two formats:

**Simple format** — amino acid string only:
```json
"sequences": {
  "seq1": "EVQLVESGGGLVQPGGSLRLSCAAS"
}
```

**Object format** — with metadata:
```json
"sequences": {
  "seq1": {
    "aa_string": "EVQLVESGGGLVQPGGSLRLSCAAS",
    "control": false,
    "metadata": { "type": "scfv", "tag_location": "C" }
  }
}
```

# Example: Affinity (BLI)

Full kinetic characterization measuring on/off rates and KD.
Target ID `019a03da-b87f-7e15-8b02-cef171c9871d` is Human PD-L1 from the catalog.

```json
{
  "name": "PD-L1 affinity panel",
  "experiment_spec": {
    "experiment_type": "affinity",
    "method": "bli",
    "target_id": "019a03da-b87f-7e15-8b02-cef171c9871d",
    "sequences": {
      "pembrolizumab_vh": "QVQLVQSGVEVKKPGASVKVSCKASGYTFTNYYMYWVRQAPGQGLEWMGGINPSNGGTNFNEKFKNRVTLTTDSSTTTAYMELKSLQFDDTAVYYCARRDYRFDMGFDYWGQGTTVTVSS",
      "pembrolizumab_vl": "EIVLTQSPATLSLSPGERATLSCRASKGVSTSGYSYLHWYQQKPGQAPRLLIYLASYLESGVPARFSGSGSGTDFTLTISSLEPEDFAVYYCQHSRDLPLTFGGGTKVEIK"
    },
    "n_replicates": 3,
    "antigen_concentrations": [1000.0, 316.2, 100.0, 31.6, 0.0]
  },
  "webhook_url": "https://example.com/webhook"
}
```

# Example: Screening (SPR)

High-throughput yes/no binding assessment using SPR.

```json
{
  "name": "Library screening round 1",
  "experiment_spec": {
    "experiment_type": "screening",
    "method": "spr",
    "target_id": "019a03da-b87f-7e15-8b02-cef171c9871d",
    "sequences": {
      "clone_A1": "EVQLVESGGGLVQPGGSLRLSCAASGFTFSSYAMSWVRQAPGKGLEWVSAISGSGGSTYYADSVKGRFTISRDNSKNTLYLQMNSLRAEDTAVYYCAKDRLSITIRPRYYGLDVWGQGTLVTVSS",
      "clone_A2": "QVQLVQSGAEVKKPGASVKVSCKASGYTFTSYGISWVRQAPGQGLEWMGWISAYNGNTNYAQKLQGRVTMTTDTSTSTAYMELRSLRSDDTAVYYCARDVGYCTDYSCYFDYWGQGTLVTVSS",
      "clone_A3": "EVQLLESGGGLVQPGGSLRLSCAASGFTFSTYAMSWVRQAPGKGLEWVSSISSGGSYIYYADSVKGRFTISRDNAKNSLYLQMNSLRAEDTAVYYCARRPWGYYALDIWGQGTTVTVSS"
    },
    "n_replicates": 2
  }
}
```

# Example: Thermostability

Measures melting temperature (Tm) via differential scanning fluorimetry.
No target required.

```json
{
  "name": "Lead candidates stability",
  "experiment_spec": {
    "experiment_type": "thermostability",
    "sequences": {
      "candidate_1": "QVQLVQSGAEVKKPGASVKVSCKASGYTFTSYAMHWVRQAPGQRLEWMGWINAGNGNTKYSQKFQGRVTITRDTSASTAYMELSSLRSEDTAVYYCARAKFGATGAFDIWGQGTMVTVSS",
      "candidate_2": "EVQLVESGGGLVQPGGSLRLSCAASGFNIKDTYIHWVRQAPGKGLEWVARIYPTNGYTRYADSVKGRFTISADTSKNTAYLQMNSLRAEDTAVYYCSRWGGDGFYAMDYWGQGTLVTVSS"
    },
    "n_replicates": 3,
    "parameters": {
      "buffer": "PBS",
      "ph": 7.4
    }
  }
}
```

# Example: Fluorescence

Fluorescence-based protein characterization measuring intrinsic properties.
No target required.

```json
{
  "name": "Fluorescence characterization",
  "experiment_spec": {
    "experiment_type": "fluorescence",
    "sequences": {
      "variant_1": "QVQLVQSGAEVKKPGASVKVSCKASGYTFTSYDINWVRQATGQGLEWMGWMNPNSGNTGYAQKFQGRVTMTRDTSISTAYMELRSLRSDDTAVYYCARGGFYGSTIWFDYWGQGTLVTVSS",
      "variant_2": "EVQLVESGGGLVQPGGSLRLSCAASGFTFSSYWMSWVRQAPGKGLEWVANIKQDGSEKYYVDSVKGRFTISRDNAKNSLYLQMNSLRAEDTAVYYCARDRYGNYVDYWGQGTLVTVSS"
    },
    "n_replicates": 3
  }
}
```

# Example: Expression

Protein expression screening measuring yield and quality.
No target required.

```json
{
  "name": "Expression screening",
  "experiment_spec": {
    "experiment_type": "expression",
    "sequences": {
      "construct_A": "QVQLVQSGAEVKKPGASVKVSCKASGYTFTSYGISWVRQAPGQGLEWMGWISAYNGNTNYAQKLQGRVTMTTDTSTSTAYMELRSLRSDDTAVYYCARDVGYCTDYSCYFDYWGQGTLVTVSS",
      "construct_B": "EVQLVESGGGLVQPGGSLRLSCAASGFNIKDTYIHWVRQAPGKGLEWVARIYPTNGYTRYADSVKGRFTISADTSKNTAYLQMNSLRAEDTAVYYCSRWGGDGFYAMDYWGQGTLVTVSS"
    },
    "n_replicates": 2
  }
}
```

# Example: With skip_draft=true (Auto-Submit)

Bypass Draft status and submit directly for processing:

```json
{
  "name": "Pre-validated batch",
  "skip_draft": true,
  "experiment_spec": {
    "experiment_type": "thermostability",
    "sequences": {
      "seq1": "EVQLVESGGGLVQPGGSLRLSCAASGFTFSSYAMSWVRQAPGKGLEWVSAISGSGGSTYYADSVKGRFTISRDNSKNTLYLQMNSLRAEDTAVYYCAKDRLSITIRPRYYGLDVWGQGTLVTVSS"
    },
    "n_replicates": 2
  }
}
```



## OpenAPI

````yaml https://devs.adaptyvbio.com/api/v1/openapi.json post /api/v1/experiments
openapi: 3.1.0
info:
  title: Adaptyv Foundry API
  description: >

    The Foundry API enables programmatic access to Adaptyv Bio's protein
    characterization services.


    ## Getting Started


    1. **Obtain an API token** from the [Adaptyv
    Portal](https://foundry.adaptyvbio.com) or by
       contacting Adaptyv directly
    2. **Authenticate requests** using Bearer token in the Authorization header

    3. **Create experiments** to submit protein sequences for characterization

    4. **Monitor status** via webhooks or polling the experiment detail endpoint


    ## Authentication


    All requests require a Bearer token:


    ```

    Authorization: Bearer <your-token>

    ```


    Tokens can be attenuated (restricted) to specific organizations or
    capabilities via the `/tokens` endpoint.


    ## Pagination


    List endpoints support offset-based pagination:


    | Parameter | Description | Default |

    |-----------|-------------|---------|

    | `limit` | Maximum items per page | 50 |

    | `offset` | Number of items to skip | 0 |


    ## Filtering


    Most list endpoints support filtering via query parameters using comparison
    operators:


    - `equ(field)=value` — equals

    - `geq(field)=value` — greater than or equal

    - `gtr(field)=value` — greater than

    - `leq(field)=value` — less than or equal

    - `lss(field)=value` — less than


    Example: `GET /experiments?geq(created_at)=2025-01-01&status=draft`


    ## Environments


    | Environment | Base URL |

    |-------------|----------|

    | Production | `https://devs.adaptyvbio.com` |


    ## Support


    - **Email**: support@adaptyvbio.com

    - **Documentation**: [docs.adaptyvbio.com](https://docs.adaptyvbio.com)
  version: 0.0.2
servers:
  - url: https://devs.adaptyvbio.com/
    description: Production API (Public)
security:
  - adaptyv_biscuits_v0: []
tags:
  - name: experiments
    description: >

      Experiments are the core resource for submitting protein sequences to
      Adaptyv's characterization services.


      ## Lifecycle


      Experiments progress through these stages:


      1. **Draft** — Initial state for designing your experiment

      2. **In Review** — Submitted for validation and quote generation

      3. **Quote Sent** — Adaptyv has sent a pricing quote

      4. **Waiting for Confirmation** — Quote ready, awaiting acceptance

      5. **In Queue** — Confirmed and queued for lab scheduling

      6. **Waiting for Materials** — Confirmed, waiting for samples

      7. **In Production** — Lab work in progress

      8. **Data Analysis** — Characterization complete, processing results

      9. **Done** — Results available for download


      **Canceled** is a terminal state reachable from Draft, In Review, Waiting
      for Confirmation, or In Queue.


      ## Experiment Types


      | Type | Description | Target Required |

      |------|-------------|-----------------|

      | `screening` | High-throughput binding assessment | Yes |

      | `affinity` | Kinetic characterization (KD, kon, koff) | Yes |

      | `thermostability` | Thermal stability measurement (Tm) | No |

      | `expression` | Expression yield assessment | No |

      | `fluorescence` | Fluorescence-based characterization | No |


      ## Typical Workflow


      ```

      POST /experiments                    # Create experiment

      POST /experiments/cost-estimate      # Preview pricing

      POST /experiments/{id}/submit        # Submit for review

      GET /experiments/{id}/quote          # Retrieve quote when ready

      POST /experiments/{id}/quote/confirm # Accept quote

      GET /experiments/{id}                # Monitor progress

      GET /results?experiment_id={id}      # Retrieve results when done

      ```


      ## Related Resources


      - [Results](#tag/results) — Characterization data from completed
      experiments

      - [Sequences](#tag/sequences) — Individual sequences within experiments

      - [Targets](#tag/targets) — Target proteins for binding experiments
  - name: feedback
    description: >-
      Use this endpoint to give us feedback, report bugs that are not already
      caught by our observability or request features (or have your agents do
      it).
  - name: info
    description: >-
      Programmatic discovery and health probes. Anonymous-eligible liveness and
      database connectivity probes; admin-only assay-type catalog (internal
      builds).
  - name: quotes
    description: >-
      Stripe quote lifecycle: list, retrieve, confirm, and reject quotes for
      experiment pricing.
  - name: results
    description: >

      Results contain the characterization data from completed experiments.


      ## Result Availability


      Results appear when an experiment reaches the **Done** status. Some
      experiment types provide partial results during **Data Analysis**.


      ## Result Types by Experiment


      | Experiment Type | Result Data |

      |-----------------|-------------|

      | Affinity | KD, kon, koff, sensorgrams |

      | Screening | Binding yes/no, response units |

      | Thermostability | Tm values, melting curves |

      | Expression | Yield measurements |


      ## Downloading Results


      Use the result `id` to fetch detailed data. Result downloads may include:


      - Raw sensorgram data

      - Fitted kinetic parameters

      - Quality metrics

      - Summary reports


      ## Related Resources


      - [Experiments](#tag/experiments) — Parent resource that produces results
  - name: sequences
    description: >

      Sequences provide read-only access to protein sequences submitted across
      experiments.


      ## Sequence Format


      Sequences are amino acid strings in standard single-letter IUPAC format
      (e.g., `MKTLLLTLLV...`).


      ## Sequence Properties


      | Field | Description |

      |-------|-------------|

      | `aa_string` | The amino acid sequence |

      | `name` | Optional human-readable identifier |

      | `control` | Whether this is a control sequence |

      | `metadata` | Structural annotations (tag location, antibody type) |


      ## Querying Sequences


      Filter sequences by experiment or other criteria:


      ```

      GET /sequences?experiment_id={id}

      GET /sequences?name=mAb-001

      ```


      ## Related Resources


      - [Experiments](#tag/experiments) — Parent resource containing sequences
  - name: targets
    description: >

      Targets represent the molecules your samples will be tested against in
      binding experiments (affinity and screening).


      ## Target Catalog


      Adaptyv maintains a catalog of pre-validated target proteins with
      established pricing. Use `selfservice_only=true` to filter for targets
      with immediate pricing availability.


      ## Self-Service vs Custom Targets


      | Category | Description | Pricing |

      |----------|-------------|---------|

      | Self-service | Pre-validated catalog targets | Instant quote via cost
      estimate |

      | Custom | User-supplied or special request | Requires manual quote |


      ## Usage


      1. Browse targets with `GET /targets?selfservice_only=true`

      2. Use the target's `id` when creating an experiment

      3. For custom targets, provide a `requested_target` object in the
      experiment request


      ## Related Resources


      - [Experiments](#tag/experiments) — Create experiments using targets

      - [Cost Estimate](#operation/cost_estimate) — Preview pricing for
      self-service targets
  - name: tokens
    description: >

      Create restricted versions of your API token for delegation to team
      members or automated systems.


      ## Token Attenuation


      Attenuation **reduces** the permissions of your token—it cannot grant
      additional access. Attenuated tokens inherit a subset of the parent
      token's capabilities.


      ## Restriction Types


      | Restriction | Effect |

      |-------------|--------|

      | Organization | Limit access to specific organizations |

      | Resource | Limit to specific resource types (experiments, results) |

      | Action | Limit to specific actions (read, create, update) |

      | Expiry | Set a shorter expiration time |


      ## Security Best Practices


      - Create narrowly-scoped tokens for automated systems

      - Use short expiration times for temporary access

      - Revoke tokens promptly when no longer needed
  - name: updates
    description: >-
      Real-time feed of experiment status changes, progress notifications, and
      operational alerts. Supports cursor-based pagination for efficient
      polling.
  - name: whoami
    description: >-
      Identify yourself: the organizations your token can access (with the
      active one marked), your user id, the permissions your token grants, and
      its expiry.
paths:
  /api/v1/experiments:
    post:
      tags:
        - experiments
      summary: Create experiment
      description: >-
        Creates a new experiment request for the Adaptyv Foundry platform.


        The payload captures the target (from the catalog), antibody sequences,

        replicate plan, assay parameters, optional metadata, and an optional
        webhook

        for notifications. By default, experiments are created

        in Draft status so clients can review inputs before submission.


        Set `skip_draft: true` to bypass Draft status and submit directly for
        processing.

        This is useful for automated pipelines with pre-validated payloads that

        don't require manual review. The experiment will be created in

        "Waiting for confirmation" status instead of Draft.


        API-originated experiments are automatically assigned to the
        organization's

        API submissions project for traceability.


        # ExperimentSpec fields


        Validation is strict: fields that are not applicable to a given
        experiment

        type (e.g., `method` on a non-binding type) cause a 400 rejection.
        Multiple

        validation errors are accumulated and returned together so callers can
        fix

        everything in one round-trip.


        | Field | Type | Description |

        |-------|------|-------------|

        | `experiment_type` | string | **Required.** One of `affinity`,
        `screening`, `thermostability`, `fluorescence`, `expression`,
        `epitope_binning`, `enzyme_activity`. |

        | `method` | string | Required for `affinity`/`screening` (`bli` or
        `spr`). **Rejected** for all other types. |

        | `target_id` | string | Target UUID from the catalog. Required for
        `affinity`, `screening`, and `epitope_binning`. **Rejected** for
        non-binding types. |

        | `sequences` | object | **Required.** Map of sequence name to amino
        acid string. `epitope_binning` requires exactly 4-28 sequences in
        multiples of 4. |

        | `n_replicates` | integer | Optional for most types (default 3, range
        1-5). **Rejected** for `epitope_binning`. |

        | `antigen_concentrations` | array | `affinity` only; optional, defaults
        to `[1000.0, 316.2, 100.0, 31.6, 0.0]` nM. |

        | `parameters` | object | Optional. Experiment-specific settings |


        # Sequence Formats


        The `sequences` field accepts two formats:


        **Simple format** — amino acid string only:

        ```json

        "sequences": {
          "seq1": "EVQLVESGGGLVQPGGSLRLSCAAS"
        }

        ```


        **Object format** — with metadata:

        ```json

        "sequences": {
          "seq1": {
            "aa_string": "EVQLVESGGGLVQPGGSLRLSCAAS",
            "control": false,
            "metadata": { "type": "scfv", "tag_location": "C" }
          }
        }

        ```


        # Example: Affinity (BLI)


        Full kinetic characterization measuring on/off rates and KD.

        Target ID `019a03da-b87f-7e15-8b02-cef171c9871d` is Human PD-L1 from the
        catalog.


        ```json

        {
          "name": "PD-L1 affinity panel",
          "experiment_spec": {
            "experiment_type": "affinity",
            "method": "bli",
            "target_id": "019a03da-b87f-7e15-8b02-cef171c9871d",
            "sequences": {
              "pembrolizumab_vh": "QVQLVQSGVEVKKPGASVKVSCKASGYTFTNYYMYWVRQAPGQGLEWMGGINPSNGGTNFNEKFKNRVTLTTDSSTTTAYMELKSLQFDDTAVYYCARRDYRFDMGFDYWGQGTTVTVSS",
              "pembrolizumab_vl": "EIVLTQSPATLSLSPGERATLSCRASKGVSTSGYSYLHWYQQKPGQAPRLLIYLASYLESGVPARFSGSGSGTDFTLTISSLEPEDFAVYYCQHSRDLPLTFGGGTKVEIK"
            },
            "n_replicates": 3,
            "antigen_concentrations": [1000.0, 316.2, 100.0, 31.6, 0.0]
          },
          "webhook_url": "https://example.com/webhook"
        }

        ```


        # Example: Screening (SPR)


        High-throughput yes/no binding assessment using SPR.


        ```json

        {
          "name": "Library screening round 1",
          "experiment_spec": {
            "experiment_type": "screening",
            "method": "spr",
            "target_id": "019a03da-b87f-7e15-8b02-cef171c9871d",
            "sequences": {
              "clone_A1": "EVQLVESGGGLVQPGGSLRLSCAASGFTFSSYAMSWVRQAPGKGLEWVSAISGSGGSTYYADSVKGRFTISRDNSKNTLYLQMNSLRAEDTAVYYCAKDRLSITIRPRYYGLDVWGQGTLVTVSS",
              "clone_A2": "QVQLVQSGAEVKKPGASVKVSCKASGYTFTSYGISWVRQAPGQGLEWMGWISAYNGNTNYAQKLQGRVTMTTDTSTSTAYMELRSLRSDDTAVYYCARDVGYCTDYSCYFDYWGQGTLVTVSS",
              "clone_A3": "EVQLLESGGGLVQPGGSLRLSCAASGFTFSTYAMSWVRQAPGKGLEWVSSISSGGSYIYYADSVKGRFTISRDNAKNSLYLQMNSLRAEDTAVYYCARRPWGYYALDIWGQGTTVTVSS"
            },
            "n_replicates": 2
          }
        }

        ```


        # Example: Thermostability


        Measures melting temperature (Tm) via differential scanning fluorimetry.

        No target required.


        ```json

        {
          "name": "Lead candidates stability",
          "experiment_spec": {
            "experiment_type": "thermostability",
            "sequences": {
              "candidate_1": "QVQLVQSGAEVKKPGASVKVSCKASGYTFTSYAMHWVRQAPGQRLEWMGWINAGNGNTKYSQKFQGRVTITRDTSASTAYMELSSLRSEDTAVYYCARAKFGATGAFDIWGQGTMVTVSS",
              "candidate_2": "EVQLVESGGGLVQPGGSLRLSCAASGFNIKDTYIHWVRQAPGKGLEWVARIYPTNGYTRYADSVKGRFTISADTSKNTAYLQMNSLRAEDTAVYYCSRWGGDGFYAMDYWGQGTLVTVSS"
            },
            "n_replicates": 3,
            "parameters": {
              "buffer": "PBS",
              "ph": 7.4
            }
          }
        }

        ```


        # Example: Fluorescence


        Fluorescence-based protein characterization measuring intrinsic
        properties.

        No target required.


        ```json

        {
          "name": "Fluorescence characterization",
          "experiment_spec": {
            "experiment_type": "fluorescence",
            "sequences": {
              "variant_1": "QVQLVQSGAEVKKPGASVKVSCKASGYTFTSYDINWVRQATGQGLEWMGWMNPNSGNTGYAQKFQGRVTMTRDTSISTAYMELRSLRSDDTAVYYCARGGFYGSTIWFDYWGQGTLVTVSS",
              "variant_2": "EVQLVESGGGLVQPGGSLRLSCAASGFTFSSYWMSWVRQAPGKGLEWVANIKQDGSEKYYVDSVKGRFTISRDNAKNSLYLQMNSLRAEDTAVYYCARDRYGNYVDYWGQGTLVTVSS"
            },
            "n_replicates": 3
          }
        }

        ```


        # Example: Expression


        Protein expression screening measuring yield and quality.

        No target required.


        ```json

        {
          "name": "Expression screening",
          "experiment_spec": {
            "experiment_type": "expression",
            "sequences": {
              "construct_A": "QVQLVQSGAEVKKPGASVKVSCKASGYTFTSYGISWVRQAPGQGLEWMGWISAYNGNTNYAQKLQGRVTMTTDTSTSTAYMELRSLRSDDTAVYYCARDVGYCTDYSCYFDYWGQGTLVTVSS",
              "construct_B": "EVQLVESGGGLVQPGGSLRLSCAASGFNIKDTYIHWVRQAPGKGLEWVARIYPTNGYTRYADSVKGRFTISADTSKNTAYLQMNSLRAEDTAVYYCSRWGGDGFYAMDYWGQGTLVTVSS"
            },
            "n_replicates": 2
          }
        }

        ```


        # Example: With skip_draft=true (Auto-Submit)


        Bypass Draft status and submit directly for processing:


        ```json

        {
          "name": "Pre-validated batch",
          "skip_draft": true,
          "experiment_spec": {
            "experiment_type": "thermostability",
            "sequences": {
              "seq1": "EVQLVESGGGLVQPGGSLRLSCAASGFTFSSYAMSWVRQAPGKGLEWVSAISGSGGSTYYADSVKGRFTISRDNSKNTLYLQMNSLRAEDTAVYYCAKDRLSITIRPRYYGLDVWGQGTLVTVSS"
            },
            "n_replicates": 2
          }
        }

        ```
      operationId: create_exp
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateExpRequest'
        required: true
      responses:
        '201':
          description: Experiment created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateExpResponse'
        '400':
          description: Invalid request parameters (e.g. malformed target_id)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Invalid or missing authentication token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Insufficient permissions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: target_id references a target that is not in the catalog
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '415':
          description: >-
            Unsupported media type — the request body must be sent as
            application/json
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '422':
          description: >-
            Unprocessable request body (well-formed JSON that fails semantic
            validation, e.g. an invalid amino-acid sequence)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
components:
  schemas:
    CreateExpRequest:
      type: object
      description: |-
        Request payload for creating a new experiment.

        Created experiments start in Draft status. Use PATCH `/experiments/{id}`
        to modify existing experiments.
      required:
        - name
        - experiment_spec
      properties:
        auto_accept_quote:
          type: boolean
          description: >-
            Auto-accept the quote and create an invoice (without sending).


            When `true`, the system will:

            1. Create a Stripe quote (requires target_id and full pricing
            available)

            2. Finalize and accept the quote

            3. Create a draft invoice (not sent to customer)

            4. Advance the experiment to "Waiting for materials" status


            This enables fully automated experiment submission pipelines where
            payment

            is handled externally or the organization has pre-approved billing.

            Implies `skip_draft: true`.
          default: false
        experiment_spec:
          $ref: '#/components/schemas/ExperimentSpec'
          description: >-
            Structured experiment definition (type, target, sequences,
            parameters)
        name:
          type: string
          description: Human-readable name for the experiment
          example: PD-L1 affinity panel
        skip_draft:
          type: boolean
          description: >-
            Bypass Draft status and submit directly for processing.


            When `true`, the experiment is created in "Waiting for confirmation"

            status instead of Draft, skipping the manual review step. Use this
            for

            automated pipelines with pre-validated payloads.


            When an experiment is submitted with `skip_draft: true` and the
            target

            has existing inventory materials, those materials are automatically

            linked to expedite processing.
        webhook_url:
          type:
            - string
            - 'null'
          description: >-
            HTTPS URL for push notifications. Once set, Adaptyv POSTs an

            `experiment_update` event to this URL for every customer-facing
            update on

            the experiment — the same updates that trigger an email
            notification.

            Deliveries are signed with `X-Adaptyv-Signature` (HMAC-SHA256).
          example: https://example.com/webhook
    CreateExpResponse:
      type: object
      description: Response confirming experiment creation.
      required:
        - experiment_id
      properties:
        error:
          type:
            - string
            - 'null'
          description: Error message when the request fails validation or processing
        experiment_id:
          type: string
          description: Unique identifier assigned to the new experiment
        stripe_hosted_invoice_url:
          type:
            - string
            - 'null'
          description: |-
            Stripe hosted invoice page. When the invoice is unpaid this is the
            checkout/payment page; after payment it becomes a receipt viewer.
        stripe_invoice_id:
          type:
            - string
            - 'null'
          description: >-
            Stripe invoice ID, present when `auto_accept_quote` created an
            invoice.
    ErrorResponse:
      type: object
      description: >-
        Error response body returned by all endpoints on 4xx/5xx failures.


        Every error response contains a human-readable message and the request
        ID

        for support correlation. The `request_id` is also returned in the

        `x-request-id` response header.
      required:
        - error
        - request_id
      properties:
        error:
          type: string
          description: Human-readable error description.
          example: experiment not found
        request_id:
          type: string
          description: >-
            Request identifier for support correlation (also in `x-request-id`
            header).
          example: req_019462a4-b1c2-7def-8901-23456789abcd
    ExperimentSpec:
      allOf:
        - $ref: '#/components/schemas/ExperimentSpecCommon'
        - type: object
          properties:
            target_id:
              type:
                - string
                - 'null'
              format: uuid
              description: >-
                UUID of the target antigen from the catalog, required when
                creating

                binding experiments (affinity, screening, epitope binning); only
                catalog

                targets can be specified. On the experiment read response the
                resolved

                target is returned as `target` (see `target.target_catalog_id`).
              example: 019a03da-b87f-7e15-8b02-cef171c9871d
      description: >-
        Request body for creating an experiment (`POST /experiments`).


        Required fields differ by experiment type. The matrix below is the

        authoritative contract; submissions that violate it are rejected with a
        400

        listing every problem at once.


        * `required` — must be set.

        * `rejected` — must not be set for this type.

        * `optional` / `≥1` / ranges — accepted as stated; the noted default
        applies
          when omitted.

        | Field                         | Affinity   | Screening |
        Thermostability | Fluorescence | Expression | EpitopeBinning           
        | EnzymeActivity |

        |-------------------------------|------------|-----------|-----------------|--------------|------------|---------------------------|----------------|

        | `experiment_type`             | required   | required  |
        required        | required     | required   | required                 
        | required       |

        | `method` (`bli` \| `spr`)     | required   | required  |
        rejected        | rejected     | rejected   | rejected                 
        | rejected       |

        | `target_id` (UUID)            | required   | required  |
        rejected        | rejected     | rejected   | required                 
        | rejected       |

        | `sequences`                   | ≥1         | ≥1        |
        ≥1              | ≥1           | ≥1         | multiple of 4, range 4–28
        | ≥1             |

        | `n_replicates`                | optional   | optional  |
        optional        | optional     | optional   | rejected                 
        | optional       |

        | `antigen_concentrations`      | default `[1000.0, 316.2, 100.0, 31.6,
        0.0]` nM | — | — | — | — | — | — |

        | `parameters` (free-form JSON) | optional   | optional  |
        optional        | optional     | optional   | optional                 
        | optional       |


        # Example


        ```json

        {
          "experiment_type": "screening",
          "method": "bli",
          "target_id": "019a03da-b87f-7e15-8b02-cef171c9871d",
          "sequences": {
            "mAb1": "EVQLVESGGGLVQPGGSLRLSCAASGFTFS...",
            "control": {"aa_string": "MKTLVLLALLV...", "control": true}
          },
          "n_replicates": 3
        }

        ```
    ExperimentSpecCommon:
      type: object
      description: >-
        Fields an experiment carries on both create and read: the assay type and

        method, the sequences under test, the replicate plan, and optional
        parameters.
      required:
        - experiment_type
      properties:
        antigen_concentrations:
          type:
            - array
            - 'null'
          items:
            type: number
            format: double
          description: Antigen concentrations to test (in nanoMolar)
          example:
            - 1000
            - 316.2
            - 100
            - 31.6
            - 0
        experiment_type:
          $ref: '#/components/schemas/ExperimentType'
          description: >-
            Assay type: `affinity`, `screening`, `thermostability`,
            `fluorescence`, `expression`, `epitope_binning`, or
            `enzyme_activity`
        method:
          oneOf:
            - type: 'null'
            - $ref: '#/components/schemas/Method'
              description: >-
                Measurement method (BLI or SPR). Required for binding types
                (affinity,

                screening); omitting it for those types is an error. Absent in

                requests and responses for non-binding types (thermostability,

                fluorescence, expression).
        n_replicates:
          type:
            - integer
            - 'null'
          format: int32
          description: Number of technical replicates (minimum 1, recommended 3+)
          example: 3
          minimum: 0
        parameters:
          type:
            - object
            - 'null'
          description: >-
            Advanced experiment-specific settings. Most experiments leave this
            null.

            When provided, the object round-trips through the experiment detail
            with

            one addition: the read path merges the `experiment_type`
            discriminator

            into it, so a submitted `{"note":"x"}` reads back as

            `{"experiment_type":"...","note":"x"}`. A user-supplied
            `experiment_type`

            key is preserved as-is — the discriminator is only inserted when
            absent.
        sequences:
          type: object
          description: >-
            Sequences keyed by a human readable name. Accepts either simple
            amino acid strings

            or rich objects with control flags and metadata.
          additionalProperties:
            $ref: '#/components/schemas/SequenceValue'
          propertyNames:
            type: string
    ExperimentType:
      type: string
      description: Experiment type determining the assay workflow.
      enum:
        - affinity
        - screening
        - thermostability
        - fluorescence
        - expression
        - epitope_binning
        - enzyme_activity
    Method:
      type: string
      description: >-
        The measurement method (BLI or SPR).


        Required for affinity and screening; must be omitted for all other
        types.
      enum:
        - bli
        - spr
    SequenceValue:
      oneOf:
        - $ref: '#/components/schemas/AAString'
          description: 'Simple format: amino acid sequence string'
        - $ref: '#/components/schemas/SequenceInput'
          description: 'Rich format: sequence with optional control flag and metadata'
      description: >-
        Flexible sequence input for experiment creation.


        Accepts a simple amino acid string or a rich object with control flag
        and metadata.
    AAString:
      type: string
      description: >-
        A validated amino acid sequence string.


        Contains only the 20 natural amino acids (single-letter codes: A, C, D,
        E,

        F, G, H, I, K, L, M, N, P, Q, R, S, T, V, W, Y) and colons for
        multichain

        notation. Input is case-insensitive; stored uppercase.


        Multichain sequences use colon separators (e.g., `MVLS:EVQL` for a

        two-chain construct). Invalid characters or empty strings are rejected.
      example: EVQLVESGGGLVQPGGSLRLSCAAS
    SequenceInput:
      type: object
      description: Rich sequence input with control flag and optional structural metadata.
      required:
        - aa_string
      properties:
        aa_string:
          $ref: '#/components/schemas/AAString'
          description: >-
            Protein/peptide sequence in standard single-letter amino acid
            format.


            Valid characters: A,C,D,E,F,G,H,I,K,L,M,N,P,Q,R,S,T,V,W,Y and colon
            for multichain.
        control:
          type: boolean
          description: Whether the sequence should be treated as a control well
        metadata:
          oneOf:
            - type: 'null'
            - $ref: '#/components/schemas/SequenceMetadata'
              description: >-
                Structural metadata about the sequence (antibody type, tag
                location, etc.)
    SequenceMetadata:
      type: object
      description: >-
        Structural metadata for antibody sequences.


        The `type` field determines which other fields are required:


        | Type | Required | Optional |

        |------|----------|----------|

        | `sc_fv` | `vh`, `vl` | `linker` (defaults to `GGGGSGGGGSGGGGS`),
        `tag_location` |

        | `fab` | `framework_regions.ch`, `framework_regions.cl` |
        `tag_location` |

        | `single_chain` | (none) | `tag_location` |

        | `igg` | (none) | `tag_location` |


        When `type` is omitted, validation is skipped for backwards
        compatibility.


        # Examples


        ScFv with minimal required fields:

        ```json

        {
          "type": "sc_fv",
          "tag_location": "C",
          "vh": "EVQLVESGGGLVQPGGSLRLSCAASGFTFS",
          "vl": "DIQMTQSPSSLSASVGDRVTITC"
        }

        ```


        FAB with explicit constant regions:

        ```json

        {
          "type": "fab",
          "tag_location": "N",
          "framework_regions": {
            "ch": "ASTKGPSVFPLAPSSKSTSGGTAALGCLVK...",
            "cl": "RTVAAPSVFIFPPSDEQLKSGTASVVCLL..."
          }
        }

        ```
      properties:
        VH:
          type:
            - string
            - 'null'
          description: Variable heavy chain sequence (required for ScFv).
          example: EVQLVESGGGLVQPGGSLRLSCAASGFTFS
        VL:
          type:
            - string
            - 'null'
          description: Variable light chain sequence (required for ScFv).
          example: DIQMTQSPSSLSASVGDRVTITC
        chain_order:
          type:
            - array
            - 'null'
          items:
            type: string
          description: Chain ordering for complex multi-chain formats.
        framework_regions:
          oneOf:
            - type: 'null'
            - $ref: '#/components/schemas/FrameworkRegions'
              description: Constant region framework sequences (required for FAB).
        linker:
          type:
            - string
            - 'null'
          description: |-
            Flexible peptide linker connecting VH and VL domains.

            If omitted for ScFv, defaults to `GGGGSGGGGSGGGGS` (Gly₄Ser)₃.
          example: GGGGSGGGGSGGGGS
        tag_location:
          oneOf:
            - type: 'null'
            - $ref: '#/components/schemas/TagLocation'
              description: |-
                His-tag location for purification.

                `N` for N-terminal, `C` for C-terminal.
        type:
          oneOf:
            - type: 'null'
            - $ref: '#/components/schemas/SequenceType'
              description: >-
                Antibody format type determining required fields.


                Accepted values: `ScFv`, `FAB`, `SingleChain`, `IgG`
                (Portal-style).

                Also accepts: `sc_fv`, `fab`, `single_chain`, `igg` (API-style).
      additionalProperties: false
    FrameworkRegions:
      type: object
      description: >-
        Constant region framework sequences for FAB antibody format.


        Both `ch` and `cl` are required when the parent metadata has `type:
        fab`.


        # Example


        ```json

        {
          "ch": "ASTKGPSVFPLAPSSKSTSGGTAALGCLVK...",
          "cl": "RTVAAPSVFIFPPSDEQLKSGTASVVCLL..."
        }

        ```
      properties:
        ch:
          type:
            - string
            - 'null'
          description: |-
            Constant heavy chain (CH1) region sequence.

            Typically the human IgG1 CH1 domain (~100 amino acids).
          example: >-
            ASTKGPSVFPLAPSSKSTSGGTAALGCLVKDYFPEPVTVSWNSGALTSGVHTFPAVLQSSGLYSLSSVVTVPSSSLGTQTYICNVNHKPSNTKVDKKVEPKSC
        cl:
          type:
            - string
            - 'null'
          description: |-
            Constant light chain (CL) region sequence.

            Either kappa (~60% of human antibodies) or lambda (~40%).
          example: >-
            RTVAAPSVFIFPPSDEQLKSGTASVVCLLNNFYPREAKVQWKVDNALQSGNSQESVTEQDSKDSTYSLSSTLTLSKADYEKHKVYACEVTHQGLSSPVTKSFNRGEC
    TagLocation:
      type: string
      description: His-tag location on the expressed protein.
      enum:
        - 'N'
        - C
    SequenceType:
      type: string
      description: >-
        Antibody format types.


        Determines validation requirements and expected metadata fields.


        Serializes in Portal-style naming (`ScFv`, `FAB`, `SingleChain`, `IgG`)
        for

        consistency with existing database data. Deserializes both Portal-style
        and

        API-style (`sc_fv`, `fab`, `single_chain`, `igg`) for backwards
        compatibility.
      enum:
        - ScFv
        - FAB
        - SingleChain
        - IgG
  securitySchemes:
    adaptyv_biscuits_v0:
      type: http
      scheme: bearer
      bearerFormat: Adaptyv Biscuits v0
      description: >-
        Biscuit-based bearer token. Obtain tokens from the Adaptyv Portal or via
        the `/tokens` endpoint. Tokens encode organization membership and
        role-based capabilities; the API verifies the token's cryptographic
        signature and authorization claims before processing requests. Use
        `/tokens/attenuate` to create restricted tokens for delegation.

````