# API Endpoints

For a high-level overview on how to integrate these API endpoints see [Integration Guide](/yodl-documentation/integration-guide.md).

### Lookup Payment

## Lookup Payment

<mark style="color:blue;">`GET`</mark> `https://yodl.me/api/v1/tx/:chainId/:txHash`

This endpoint looks up the given transaction in our database and returns an array of payments in an easy to read JSON format. The `yodlFee` value is a decimal value in terms of the token amount.

If price feeds are provided, `conversion` will be in the form of `chainlink:XXXYYY` where XXX is the invoice currency, and YYY is the token currency. The price feeds will be in the order they were used to convert from invoice currency to the token currency. The price feed name will be in the format `$baseCurrency$quoteCurrency` and their rates will all be in terms of the quote currency (usually USD).

#### Path Parameters

| Name                                       | Type   | Description |
| ------------------------------------------ | ------ | ----------- |
| :chainId<mark style="color:red;">\*</mark> | String |             |
| :txHash<mark style="color:red;">\*</mark>  | String |             |

#### Headers

| Name                                            | Type   | Description |
| ----------------------------------------------- | ------ | ----------- |
| Authorization<mark style="color:red;">\*</mark> | String | API Key     |

{% tabs %}
{% tab title="200: OK Successful response" %}

```json
{
  "chainId": 1,
  "txHash": "0x00000000000000000000000000000000000000000000000000000000000000",
  "payments": [
    {
      // order ids, invoice number or other
      "memo": "test",
      "receiver": "0x0000000000000000000000000000000000000000",
      "tokenSymbol": "USDC", // symbol of the token being received
      "tokenAmount": { // amount of the token being received
        "formatted": "1.00",
        "value": "1000000"
      },
      "tokenAmountNet": { // amount the receiver gets (amount - fees)
        "formatted": "0.9975",
        "value": "997500"
      },
      "totalFees": {
        "formatted": "0.0025",
        "value": "2500"
      },
      "fees": [
        {
          // fee charged by YODL
          "type": "YodlFee",
          "formatted": "0.002",
          "value": "2000"
        },
        {
          // extra fee charged by third-party
          "type": "ExtraFee",
          "formatted": "0.0005",
          "value": "500"
        }
      ],
      // what was charged/invoice to the payer
      "invoiceAmount": "1",
      "invoiceCurrency": "USD",
      "conversion": "",
      "priceFeeds": [],
      // whether a sufficient number of blocks have passed for the tx to be considered final
      // see Finality section
      "final": true
    }
  ]
}
```

{% endtab %}

{% tab title="200: OK Successful payment with one price feeds" %}

```json
{
  "chainId": 1,
  "txHash": "0x00000000000000000000000000000000000000000000000000000000000000",
  "payments": [
    {
      // order ids, invoice number or other
      "memo": "test",
      "receiver": "0x0000000000000000000000000000000000000000",
      "tokenSymbol": "USDC", // symbol of the token being received
      "tokenAmount": { // amount of the token being received
        "formatted": "1.05565",
        "value": "1055650"
      },
      "tokenAmountNet": { // amount the receiver gets (amount - fees)
        "formatted": "1.053539",
        "value": "1053539"
      },
      "totalFees": {
        "formatted": "0.002111",
        "value": "2111"
      },
      "fees": [
        {
          // fee charged by YODL
          "type": "YodlFee",
          "formatted": "0.002111",
          "value": "2111"
        }
      ],
      // what was charged/invoice to the payer
      "invoiceAmount": "1",
      "invoiceCurrency": "EUR",	
      "conversion": "chainlink:EURUSD",
      "priceFeeds": [
        {
          "name": "EURUSD",
          "contract": "0xab70BCB260073d036d1660201e9d5405F5829b7a",
          "rate": "1.05565"
        }
      ],
      // whether a sufficient number of blocks have passed for the tx to be considered final
      // see Finality section
      "final": true
    }
  ]
}
```

{% endtab %}

{% tab title="200: OK Successful payment with two price feeds" %}

```json
{
  "chainId": 1,
  "txHash": "0x00000000000000000000000000000000000000000000000000000000000000",
  "payments": [
    {
      // order ids, invoice number or other
      "memo": "test",
      "receiver": "0x0000000000000000000000000000000000000000",
      "tokenSymbol": "EURe", // symbol of the token being received
      "tokenAmount": { // amount of the token being received
        "formatted": "1.045246858849634651",
        "value": "1045246858849634651"
      },
      "tokenAmountNet": { // amount the receiver gets (amount - fees)
        "formatted": "1.045246858849634651",
        "value": "1045246858849634651"
      },
      "totalFees": {
        "formatted": "0",
        "value": "0"
      },
      "fees": [],
      // what was charged/invoice to the payer
      "invoiceAmount": "1",
      "invoiceCurrency": "CHF",	
      "conversion": "chainlink:CHFEUR",
      "priceFeeds": [
        {
          "name": "CHFUSD",
          "contract": "0xFb00261Af80ADb1629D3869E377ae1EEC7bE659F",
          "rate": "1.10933617"
        },
        {
          "name": "EURUSD",
          "contract": "0xab70BCB260073d036d1660201e9d5405F5829b7a",
          "rate": "1.061315"
        }
      ],
      // whether a sufficient number of blocks have passed for the tx to be considered final
      // see Finality section
      "final": true
    }
  ]
}
```

{% endtab %}

{% tab title="400: Bad Request One or more of the URL parameters are invalid" %}

```json
{
  "error": "Invalid query parameters",
  "details": [
    {
      "code": "custom",
      "message": "Address must start with '0x' and have 60 characters",
      "path": [
        "txHash"
      ]
    }
  ]
}
```

{% endtab %}

{% tab title="401: Unauthorized Valid 'Authorization' header is not present" %}

{% endtab %}

{% tab title="404: Not Found Transaction is not in our system" %}

{% endtab %}
{% endtabs %}

### Lookup & Verify Payment

## Lookup and verify a payment against given parameters

<mark style="color:green;">`POST`</mark> `https://yodl.me/api/v1/verify`

This endpoint behaves similarly to the Lookup endpoint with the notable addition of performing server-side payment verification checks. Instead of passing through transaction details in the URL, a JSON payload must be sent.

This endpoint will verify that a malicious user has not interferred and manipulated the payment.&#x20;

#### Headers

| Name                                            | Type   | Description      |
| ----------------------------------------------- | ------ | ---------------- |
| Authorization<mark style="color:red;">\*</mark> | String | API Key          |
| Content-Type<mark style="color:red;">\*</mark>  | String | application/json |

#### Request Body

| Name                                              | Type          | Description                                         |
| ------------------------------------------------- | ------------- | --------------------------------------------------- |
| chainId<mark style="color:red;">\*</mark>         | number        | id of the chain on which the transaction took place |
| txHash<mark style="color:red;">\*</mark>          | string        | transaction hash                                    |
| invoiceAmount<mark style="color:red;">\*</mark>   | number/string | amount of the invoice with decimals eg. 1.23        |
| invoiceCurrency<mark style="color:red;">\*</mark> | string        | uppercase currency for the invoice eg. USD          |
| address<mark style="color:red;">\*</mark>         | string        | receiver address or yodl.me handle                  |

{% tabs %}
{% tab title="200: OK Successful response" %}

```json
{
  "chainId": 1,
  "txHash": "0x00000000000000000000000000000000000000000000000000000000000000",
  "payments": [
    {
      // order ids, invoice number or other
      "memo": "",
      "receiver": "0x0000000000000000000000000000000000000000",
      "tokenSymbol": "USDC", // symbol of the token being received
      "tokenAmount": { // amount of the token being received
        "formatted": "0.737055",
        "value": "737055"
      },
      "tokenAmountNet": { // amount the receiver gets (amount - fees)
        "formatted": "0.737055",
        "value": "737055"
      },
      "totalFees": {
        "formatted": "0",
        "value": "0"
      },
      "fees": [],
      // what was charged/invoice to the payer
      "invoiceAmount": "1",
      "invoiceCurrency": "CAD",	
      "conversion": "chainlink:CADUSD",
      "priceFeeds": [
        {
          "name": "CADUSD",
          "contract": "0xf6DA27749484843c4F02f5Ad1378ceE723dD61d4",
          "rate": "0.7370555"
        }
      ],
      // whether a sufficient number of blocks have passed for the tx to be considered final
      // see Finality section
      "final": true
      "verified": true,
      "verificationErrors": []
    }
  ]
}
```

{% endtab %}

{% tab title="400: Bad Request One or more of the URL parameters are invalid" %}

```json
{
    "error": "Invalid query parameters",
    "details": [
        {
            "code": "custom",
            "message": "Address must start with '0x' and have 60 characters",
            "path": [
                "txHash"
            ]
        }
    ]
}
```

{% endtab %}

{% tab title="404: Not Found Transaction is not found in our system" %}

{% endtab %}

{% tab title="409: Conflict Payment(s) did not match the given payload" %}
Verification errors can one or more of:

`Payment does not match link configuration`

`Invalid payment address`

`Invalid payment currency`

`Invalid payment amount`

```json
{
  "chainId": 1,
  "txHash": "0x00000000000000000000000000000000000000000000000000000000000000",
  "payments": [
    {
      // order ids, invoice number or other
      "memo": "",
      "receiver": "0x0000000000000000000000000000000000000000",
      "tokenSymbol": "USDC", // symbol of the token being received
      "tokenAmount": { // amount of the token being received
        "formatted": "0.737055",
        "value": "737055"
      },
      "tokenAmountNet": { // amount the receiver gets (amount - fees)
        "formatted": "0.737055",
        "value": "737055"
      },
      "totalFees": {
        "formatted": "0",
        "value": "0"
      },
      "fees": [],
      // what was charged/invoice to the payer
      "invoiceAmount": "1",
      "invoiceCurrency": "CAD",	
      "conversion": "chainlink:CADUSD",
      "priceFeeds": [
        {
          "name": "CADUSD",
          "contract": "0xf6DA27749484843c4F02f5Ad1378ceE723dD61d4",
          "rate": "0.7370555"
        }
      ],
      "verified": false,
      "verificationErrors": [
        "Payment does not match link configuration"
      ]
    }
  ]
}
```

{% endtab %}
{% endtabs %}

#### Notes

It is technically possible that a (blockchain) transaction can contain mulitple YODL payments. Therefore the API endpoints return an array of payments.&#x20;

**Finality**

There are multiple definitions out there for finality, some more strict than others. In order to be practical, we will look at the likelihood of a reorg after a certain number of transactions have passed.

Currently, the confirmations we use are as follows:

| Chain Name   | Chain Id | Confirmations | Duration      |
| ------------ | -------- | ------------- | ------------- |
| Mainnet      | 1        | 3             | \~36 seconds  |
| Optimism     | 10       | 48            | \~96 seconds  |
| Gnosis       | 100      | 1             | \~5 seconds   |
| Polygon      | 137      | 50            | \~100 seconds |
| Arbitrum One | 42161    | 1600          | \~8 minutes   |

#### Types

These are likely to change and are provided as a snapshot to the current state of types.

```typescript
export enum OnCompleteActionType {
  NOTHING = "NOTHING",
  REDIRECT = "REDIRECT",
  CLOSE_WINDOW = "CLOSE_WINDOW",
}

export type OnCompleteAction =
  | { type: OnCompleteActionType.NOTHING }
  | {
      type: OnCompleteActionType.REDIRECT;
      payload: {
        url: string;
      };
    }
  | {
      type: OnCompleteActionType.CLOSE_WINDOW;
      payload: {
        delayMilliseconds: number;
      };
    };

export type CoinConfig = {
  chainId: number;
  defaultAddress?: string;
  tokens: {
    symbol: string;
    address?: string;
  }[];
};

export type LinkConfig = {
  coins: CoinConfig[];
  onCompleteAction?: OnCompleteAction;
};

export type PriceFeed = {
  name: string;
  contract: string;
  rate: string;
};

export type LookupTxDetails = {
  chainId: number;
  txHash: string;
  memo: string;
  receiver: string;
  tokenSymbol: string;
  tokenAmountGross: string;
  tokenAmountNet: string;
  tokenAmountGrossNative: string;
  tokenAmountNetNative: string;
  yodlFee: string;
  invoiceAmount: string;
  invoiceCurrency: string;
  conversion: string;
  priceFeeds: PriceFeed[];
};

export type AccountsResponse = {
	address: string;
	config: LinkConfig;
	handle: string;
};

export type LookupResponse = LookupTxDetails[];

export type VerifyDetails = LookupDetails & {
	verified: boolean;
	verificationErrors: string[]
};

export type VerifyResponse = VerifyDetails[];
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.yodl.me/yodl-documentation/api/api-endpoints.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
