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

# Build the Escrow Open Transaction

> Turns a quote into an unsigned `open` call on the LI.FI intents input settler escrow. When the quote carries a `quoteId` from the RFQ endpoint, the liquidity reservation is re-keyed to the resulting on-chain order id.

Turns a quote into an unsigned `open` call on the LI.FI input settler escrow. POST the quote object you received from [`GET /lifi-intents/rfq`](/api-reference/sprinter/lifi-intents/rfq); you get the same object back with `transactionRequest` populated.

Sending that transaction escrows the inputs on the origin chain and broadcasts the order to solvers.

<Warning>
  Include the `quoteId` from the RFQ response. Without it the endpoint still returns valid calldata, but **no liquidity is reserved** and the order is not guaranteed a Sprinter fill — you get no error saying so.
</Warning>

## Reservation window

Converting a quote **refreshes its reservation to 60 seconds, counted from this call** — not from the RFQ. That is the window you have to get the transaction signed and on-chain.

|                         |                                                                                                                                                                |
| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Held for**            | 60 seconds from the `/transaction` response                                                                                                                    |
| **Applies when**        | The posted quote carries a `quoteId`. The 15-second RFQ reservation is extended to the full 60 seconds and re-keyed from the quote id to the on-chain order id |
| **Without a `quoteId`** | Nothing is reserved and nothing is refreshed                                                                                                                   |
| **After it lapses**     | The liquidity is released back to the pool. The calldata stays valid and the order is still fillable, but no longer guaranteed a Sprinter fill                 |

<Note>
  Reservations come out of a pool **shared with other solvers**, so liquidity held against your quote is liquidity nobody else can be quoted. Each conversion holds its full amount for 60 seconds — four times the RFQ window — and the hold is not released early if you never send the transaction. Test this endpoint with small amounts: a loop over real quote sizes can take a meaningful share of a pool out of circulation a minute at a time.
</Note>

## What the endpoint fills in

You supply `preview`; everything else is derived:

| Field                         | Derived as                                                                                           |
| ----------------------------- | ---------------------------------------------------------------------------------------------------- |
| `nonce`                       | Generated per request                                                                                |
| `fillDeadline`                | \~6 minutes out — 1 minute exclusive to Sprinter, then 5 minutes open to any solver                  |
| `expires`                     | `fillDeadline` + a settlement buffer: \~13 minutes for same-chain orders, \~12 hours for cross-chain |
| `inputOracle` / output oracle | From Sprinter's configuration                                                                        |
| Exclusivity                   | Encoded per output; defaults to Sprinter's filler address                                            |
| `value`                       | Sum of native-token inputs, hex encoded. `0x0` for ERC-20-only orders                                |

You can override `nonce`, `expires`, `fillDeadline` and `inputOracle` by setting them in the `order` object on the request, and override the exclusive filler with `metadata.exclusiveFor`. Leave them unset unless you have a specific reason — the defaults are what the reservation is priced against.

## Constraints

* Every entry in `preview.inputs` must be on the same origin chain. Mixed origins are rejected with `400`.
* The returned transaction must be sent by `transactionRequest.from` — the payer named in the first input.
* Send it promptly — the reservation lapses 60 seconds after this call. See [Reservation window](#reservation-window).

<RequestExample>
  ```bash cURL theme={null}
  curl --request POST \
    --url 'https://api.sprinter.tech/lifi-intents/transaction' \
    --header 'Content-Type: application/json' \
    --data @quote.json
  ```

  ```python Python theme={null}
  import requests

  # `quote` is quotes[0] from the RFQ response, passed through unchanged
  response = requests.post(
      "https://api.sprinter.tech/lifi-intents/transaction",
      json=quote,
  )
  tx = response.json()["transactionRequest"]
  ```

  ```javascript JavaScript theme={null}
  // `quote` is quotes[0] from the RFQ response, passed through unchanged
  const response = await fetch(
    "https://api.sprinter.tech/lifi-intents/transaction",
    {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(quote),
    }
  );
  const { transactionRequest } = await response.json();

  // send it from the user's wallet
  const hash = await walletClient.sendTransaction({
    to: transactionRequest.to,
    data: transactionRequest.data,
    value: BigInt(transactionRequest.value),
    chainId: transactionRequest.chainId,
  });
  ```

  ```go Go theme={null}
  package main

  import (
  	"bytes"
  	"fmt"
  	"io"
  	"net/http"
  )

  func main() {
  	// quoteJSON is quotes[0] from the RFQ response, passed through unchanged
  	resp, _ := http.Post(
  		"https://api.sprinter.tech/lifi-intents/transaction",
  		"application/json",
  		bytes.NewReader(quoteJSON),
  	)
  	defer resp.Body.Close()
  	body, _ := io.ReadAll(resp.Body)
  	fmt.Println(string(body))
  }
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "validUntil": 1754481615,
    "eta": 45,
    "quoteId": "3f8a1c72-95e4-4d6b-b0a1-2c7e9f4d8a13",
    "provider": "sprinter",
    "preview": {
      "inputs": [
        {
          "user": "0x00010000022105141f98431c8ad98523631ae4a59f267346ea31f984",
          "asset": "0x0001000002210514833589fcd6edb6e08f4c7c32d4f71b54bda02913",
          "amount": "100000000"
        }
      ],
      "outputs": [
        {
          "receiver": "0x0001000002a4b1141f98431c8ad98523631ae4a59f267346ea31f984",
          "asset": "0x0001000002a4b114af88d065e77c8cc2239327c5edb3a432268e5831",
          "amount": "99850000"
        }
      ]
    },
    "metadata": {
      "exclusiveFor": "0x4c4A2f8c81640e47606d3fd77B353E87Ba015584"
    },
    "failureHandling": "refund-automatic",
    "transactionRequest": {
      "from": "0x1F98431c8aD98523631AE4a59f267346ea31F984",
      "to": "0x6E9a1b3F0c5D2a8B4e7C1f9A3d6B0e5C8f2A4d71",
      "chainId": 8453,
      "data": "0xff2b0c2b0000000000000000000000000000000000000000000000000000000000000020",
      "value": "0x0"
    }
  }
  ```
</ResponseExample>

## After the fill

Sprinter fills on the destination chain within the exclusivity window and is repaid when the escrow settles. If nobody fills before `fillDeadline`, the order is reclaimable on the escrow contract — `failureHandling` is `refund-automatic`, so nothing is stranded.


## OpenAPI

````yaml post /lifi-intents/transaction
openapi: 3.0.0
info:
  contact: {}
  title: ''
  version: 0.0.1
servers:
  - url: https://api.sprinter.tech
    description: Production server
security: []
paths:
  /lifi-intents/transaction:
    post:
      tags:
        - Liquidity
      summary: Build the escrow open transaction for a lifi-intents quote
      description: >-
        Turns a quote into an unsigned `open` call on the LI.FI intents input
        settler escrow. When the quote carries a `quoteId` from the RFQ
        endpoint, the liquidity reservation is re-keyed to the resulting
        on-chain order id.
      requestBody:
        description: A quote from the RFQ response
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/lifiintents.Quote'
      responses:
        '200':
          description: The same quote with transactionRequest populated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/lifiintents.Quote'
        '400':
          description: Bad request due to invalid input
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/responses.ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/responses.ErrorResponse'
components:
  schemas:
    lifiintents.Quote:
      type: object
      required:
        - preview
      properties:
        preview:
          $ref: '#/components/schemas/lifiintents.Preview'
        quoteId:
          type: string
          description: >-
            Identifier for the liquidity reservation backing this quote. Pass
            the quote back to /lifi-intents/transaction to keep it.
        validUntil:
          type: integer
          description: Unix timestamp after which the quote and its reservation expire.
        eta:
          type: integer
          description: Estimated fill duration in seconds.
        provider:
          type: string
          description: Always `sprinter`.
        failureHandling:
          type: string
          description: >-
            Always `refund-automatic` — an unfilled order is reclaimable on the
            escrow.
        partialFill:
          type: boolean
          description: >-
            Whether the order may be partially filled. Sprinter quotes are
            all-or-nothing.
        metadata:
          $ref: '#/components/schemas/lifiintents.Metadata'
        order:
          $ref: '#/components/schemas/lifiintents.Order'
        transactionRequest:
          $ref: '#/components/schemas/lifiintents.TransactionRequest'
    responses.ErrorResponse:
      type: object
      required:
        - error
      properties:
        debug:
          type: string
        error:
          type: string
    lifiintents.Preview:
      type: object
      required:
        - inputs
        - outputs
      properties:
        inputs:
          type: array
          minItems: 1
          description: >-
            Tokens escrowed on the origin chain. Every input must sit on the
            same origin chain.
          items:
            $ref: '#/components/schemas/lifiintents.Input'
        outputs:
          type: array
          minItems: 1
          description: Tokens delivered to the receiver.
          items:
            $ref: '#/components/schemas/lifiintents.Output'
    lifiintents.Metadata:
      type: object
      properties:
        exclusiveFor:
          type: string
          description: >-
            Address granted exclusivity over the fill. Defaults to Sprinter's
            filler address.
    lifiintents.Order:
      type: object
      description: >-
        Optional overrides for the escrow open call. Any field left unset is
        derived by the transaction endpoint.
      properties:
        nonce:
          type: string
        expires:
          type: integer
          description: Unix timestamp after which the order can no longer settle.
        fillDeadline:
          type: integer
          description: Unix timestamp after which the order can no longer be filled.
        inputOracle:
          type: string
    lifiintents.TransactionRequest:
      type: object
      description: >-
        Unsigned transaction calling open() on the input settler escrow. Send it
        from the user's wallet.
      required:
        - chainId
        - data
        - from
        - to
        - value
      properties:
        from:
          type: string
        to:
          type: string
          description: The LI.FI input settler escrow contract.
        chainId:
          type: integer
        data:
          type: string
        value:
          type: string
          description: Hex-encoded native value; `0x0` unless an input is the native token.
        gasPrice:
          type: string
        gasLimit:
          type: string
    lifiintents.Input:
      type: object
      required:
        - amount
        - asset
        - user
      properties:
        user:
          type: string
          description: Payer, as an ERC-7930 interoperable address.
        asset:
          type: string
          description: Input token, as an ERC-7930 interoperable address.
        amount:
          type: string
          description: Amount in the smallest denomination.
    lifiintents.Output:
      type: object
      required:
        - amount
        - asset
        - receiver
      properties:
        receiver:
          type: string
          description: Recipient, as an ERC-7930 interoperable address.
        asset:
          type: string
          description: Output token, as an ERC-7930 interoperable address.
        amount:
          type: string
          description: Amount in the smallest denomination.

````