> For the complete documentation index, see [llms.txt](https://docs.blinklabs.xyz/blink/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.blinklabs.xyz/blink/ethereum/gas-sponsored-swaps/api-reference.md).

# API Reference

### Checking for Transaction Sponsorship <a href="#checking-for-transaction-sponsorship" id="checking-for-transaction-sponsorship"></a>

To check whether a swap is sponsorable, first send your unsigned transaction to your RPC endpoint at `https://eth.blinklabs.xyz/v1/<API_KEY>` with the following POST request

#### pm\_isSponsorable

{% code overflow="wrap" %}

```json
{
    "jsonrpc": "2.0",
    "method": "pm_isSponsorable",
    "params": [
        {
          "to": "<TX_TO_ADDRESS>",
          "from": "<TX_FROM_ADDRESS>",
          "value": "<TX_VALUE_HEX>",
          "data": "TX_DATA_HEX>",
          "gas": "<TX_GAS_LIMIT_HEX>"
        }
    ],
    "id": 1
}
```

{% endcode %}

Example request:

{% code overflow="wrap" %}

```json
{
    "jsonrpc": "2.0",
    "method": "pm_isSponsorable",
    "params": [
        {
          "to": "0xb30eC35F98ff1237EDe720D32aC2da7e52A5f56b",
          "from": "0x1234567890b4fa4756b8db7a52e4150e6c18fc2c",
          "value": "0x2386f26fc10000",
          "data": "0x095ea7b3000000000000000000000000111111125421cA6dc452d289314280a0f8842A650000000000000000000000000000000000000000000000000000000000000000",
          "gas": "0x11170"
        }
    ],
    "id": 0
}
```

{% endcode %}

Example response:

{% code overflow="wrap" %}

```json
{
    "id": 0,
    "result": {
        "sponsorable": true,
        "sponsorName": "Blink",
        "sponsorIcon": "https://framerusercontent.com/images/o61GQaQ3nRGkpdVnUD5P3HhDxx0.png",
        "sponsorWebsite": "https://blinklabs.xyz/"
    },
    "jsonrpc": "2.0"
}
```

{% endcode %}

If the response returns `true`, your transaction is sponsorable.

If the transaction is not sponsorable, the response returns `false` with a `reason` explaining why:

{% code overflow="wrap" %}

```json
{
    "id": 0,
    "result": {
        "sponsorable": false,
        "sponsorName": "Blink",
        "sponsorIcon": "https://framerusercontent.com/images/o61GQaQ3nRGkpdVnUD5P3HhDxx0.png",
        "sponsorWebsite": "https://blinklabs.xyz/",
        "reason": "max swaps per day exceeded"
    },
    "jsonrpc": "2.0"
}
```

{% endcode %}

The `reason` is a human-readable explanation, not a fixed set of values. Log or display it rather than matching on its text.

#### eth\_sendRawTransaction

After calling pm\_isSponsorable, send the signed transaction using the RPC method eth\_sendRawTransaction.

The only difference compared to a normal API is that you must add the query string parameter, sponsorship=true. The full URL would be:

`https://eth.blinklabs.xyz/v1/<API_KEY>?sponsorship=true`

```
{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "eth_sendRawTransaction",
    "params": [
        "0x...",
     ],
}
```

Example response;

```
{
    "id": 1,
    "jsonrpc": "2.0",
    "result": "0x..."
}
```

Provided that the same transaction data passed to pm\_isSponsorable is used in eth\_sendRawTransaction, the transaction will be sponsored.

### Sponsoring an Approval and Swap Together <a href="#sponsoring-an-approval-and-swap-together" id="sponsoring-an-approval-and-swap-together"></a>

When a swap needs an ERC20 approval first, send the approval and the swap together as a JSON-RPC batch. Checking the swap on its own before the approval has landed fails, because the simulation has no allowance to spend. In a batch, both transactions are simulated together, so the swap sees the approval.

A sponsorship batch must be exactly two requests of the same method, from the same sender, in this order:

1. The ERC20 `approve`
2. The swap

#### pm\_isSponsorable (batch)

Send both unsigned transactions in one batch to `https://eth.blinklabs.xyz/v1/<API_KEY>`. Set each `gas` to the gas limit you will sign that transaction with. An approval's gas limit must not exceed 100,000.

{% code overflow="wrap" %}

```json
[
    {
        "jsonrpc": "2.0",
        "method": "pm_isSponsorable",
        "params": [
            {
              "to": "<TOKEN_ADDRESS>",
              "from": "<TX_FROM_ADDRESS>",
              "value": "0x0",
              "data": "<APPROVE_DATA_HEX>",
              "gas": "<APPROVE_GAS_LIMIT_HEX>"
            }
        ],
        "id": 1
    },
    {
        "jsonrpc": "2.0",
        "method": "pm_isSponsorable",
        "params": [
            {
              "to": "<SWAP_TO_ADDRESS>",
              "from": "<TX_FROM_ADDRESS>",
              "value": "<SWAP_VALUE_HEX>",
              "data": "<SWAP_DATA_HEX>",
              "gas": "<SWAP_GAS_LIMIT_HEX>"
            }
        ],
        "id": 2
    }
]
```

{% endcode %}

Both elements of the response carry the same verdict. The pair is sponsored together or not at all.

{% code overflow="wrap" %}

```json
[
    {
        "id": 1,
        "result": {
            "sponsorable": true,
            "sponsorName": "Blink",
            "sponsorIcon": "https://framerusercontent.com/images/o61GQaQ3nRGkpdVnUD5P3HhDxx0.png",
            "sponsorWebsite": "https://blinklabs.xyz/"
        },
        "jsonrpc": "2.0"
    },
    {
        "id": 2,
        "result": {
            "sponsorable": true,
            "sponsorName": "Blink",
            "sponsorIcon": "https://framerusercontent.com/images/o61GQaQ3nRGkpdVnUD5P3HhDxx0.png",
            "sponsorWebsite": "https://blinklabs.xyz/"
        },
        "jsonrpc": "2.0"
    }
]
```

{% endcode %}

When the pair is not sponsorable, both results return `"sponsorable": false` with a `reason`. A reason that starts with `transaction 0:` or `transaction 1:` names the leg that failed, for example `"transaction 1: max swaps per day exceeded"`.

#### eth\_sendRawTransaction (batch)

Send both signed transactions in one batch to `https://eth.blinklabs.xyz/v1/<API_KEY>?sponsorship=true`, in the same order. The approval must use the sender's next nonce and the swap the nonce after it.

```
[
    {
        "id": 1,
        "jsonrpc": "2.0",
        "method": "eth_sendRawTransaction",
        "params": ["<SIGNED_APPROVE_HEX>"]
    },
    {
        "id": 2,
        "jsonrpc": "2.0",
        "method": "eth_sendRawTransaction",
        "params": ["<SIGNED_SWAP_HEX>"]
    }
]
```

Each element of the response returns its transaction hash. The two transactions are submitted together in one bundle, so the approval never lands without its swap.

```
[
    {
        "id": 1,
        "jsonrpc": "2.0",
        "result": "0x..."
    },
    {
        "id": 2,
        "jsonrpc": "2.0",
        "result": "0x..."
    }
]
```

#### Batch rules

* The pair counts as one swap toward the per-user daily swap limit. The approval is not checked against the daily approval limit.
* To check or send a single transaction, use a plain request rather than a one-element batch.
* Do not mix `pm_isSponsorable` and `eth_sendRawTransaction`, or other methods, in a sponsorship batch.
* Any other batch of two or more `pm_isSponsorable` requests, or of two or more sponsored `eth_sendRawTransaction` requests, returns this error on every element:

{% code overflow="wrap" %}

```json
{
    "id": 1,
    "jsonrpc": "2.0",
    "error": {
        "code": -32600,
        "message": "This batch combination is not supported by our gas sponsorship setup yet. Batches must be exactly two transactions from one sender: an ERC20 approve followed by the swap. Please reach out if you need another combination."
    }
}
```

{% endcode %}

This applies to three or more requests, and to a swap sent before its approval. A pair from two different senders returns an error naming the mismatched sender instead.

**Notes:**

* We can setup arbitrary sponsorable criteria (e.g. whitelisted contract addresses, max sponsored transactions per user, etc...).
* We only sponsor if the transaction does not have enough funds.
* It's important that the gasLimit is not set too high compared to the gasUsed. We simulate the transaction and will return false in pm\_isSponsorable if the simulated transaction's gasLimit > 1.1 \* gasUsed.
