{
  "openapi": "3.1.0",
  "info": {
    "title": "AirnodeHub Resolve API",
    "version": "1.0.0",
    "description": "Resolve a natural-language intent to Airnode operations. Candidates include the live endpoint, parameter contract, the same call in the provider's own form, expected signer, provenance and maximum payment requirement. Unresolved inputs identify requirements the resolver deliberately did not guess."
  },
  "servers": [
    {
      "url": "https://airnodehub.api3.org"
    }
  ],
  "paths": {
    "/resolve": {
      "post": {
        "operationId": "resolveIntent",
        "summary": "Find Airnode operations for an intent",
        "description": "Returns candidates but does not call them. unresolvedInputs names missing, unverified or unsupported requirements, including parts of a multi-part intent omitted from candidates. With no candidates, reason \"unsupported\" means nothing listed serves the intent and reason \"noIntent\" means the message named no fact to fetch; 503 means the resolver could not answer and the intent is worth sending again.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ResolveRequest"
              },
              "example": {
                "intent": "current USD price of ETH"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Matching operations and the evidence needed to evaluate them.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Resolution"
                }
              }
            }
          },
          "400": {
            "description": "The request could not be completed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "additionalProperties": false
                }
              }
            }
          },
          "405": {
            "description": "The request could not be completed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "additionalProperties": false
                }
              }
            }
          },
          "429": {
            "description": "The request could not be completed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "additionalProperties": false
                }
              }
            }
          },
          "503": {
            "description": "The request could not be completed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ResolveRequest": {
        "type": "object",
        "required": [
          "intent"
        ],
        "properties": {
          "intent": {
            "type": "string",
            "minLength": 1
          }
        }
      },
      "Resolution": {
        "type": "object",
        "required": [
          "intent",
          "candidates",
          "unresolvedInputs"
        ],
        "properties": {
          "intent": {
            "type": "string"
          },
          "candidates": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Candidate"
            }
          },
          "unresolvedInputs": {
            "type": "array",
            "description": "Requirements not represented by a candidate because an input is missing, a mapping is unverified, no listed operation supports it, or the intent named no fact to fetch.",
            "items": {
              "$ref": "#/components/schemas/UnresolvedInput"
            }
          }
        },
        "additionalProperties": false
      },
      "UnresolvedInput": {
        "type": "object",
        "required": [
          "requirement",
          "needed",
          "reason"
        ],
        "properties": {
          "requirement": {
            "type": "string",
            "description": "The requested fact that remains unresolved."
          },
          "needed": {
            "type": "string",
            "description": "The exact input, mapping or capability needed next."
          },
          "reason": {
            "type": "string",
            "enum": [
              "missing",
              "unverified",
              "unsupported",
              "noIntent"
            ]
          }
        },
        "additionalProperties": false
      },
      "Candidate": {
        "type": "object",
        "required": [
          "listing",
          "airnode",
          "operation",
          "address",
          "attestation",
          "parameters",
          "example",
          "passthrough",
          "returns",
          "payment",
          "why"
        ],
        "properties": {
          "listing": {
            "type": "string",
            "description": "Stable listing slug."
          },
          "airnode": {
            "type": "string",
            "format": "uri",
            "description": "Call this Airnode directly, not the Hub."
          },
          "operation": {
            "type": "string"
          },
          "address": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]{40}$",
            "description": "Expected attestation signer."
          },
          "attestation": {
            "type": "string",
            "enum": [
              "first-party",
              "third-party"
            ]
          },
          "parameters": {
            "type": "object",
            "additionalProperties": {
              "$ref": "#/components/schemas/Parameter"
            }
          },
          "example": {
            "type": "object",
            "additionalProperties": true
          },
          "passthrough": {
            "$ref": "#/components/schemas/PassthroughRequest"
          },
          "returns": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "payment": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Payment"
              },
              {
                "type": "null"
              }
            ]
          },
          "why": {
            "type": "string"
          }
        },
        "additionalProperties": false
      },
      "PassthroughRequest": {
        "type": "object",
        "required": [
          "method",
          "url"
        ],
        "description": "The example as the provider documents the call, sent to the Airnode's passthrough. The provider's response comes back as it is, with the attestation in the X-Airnode-Address, X-Airnode-Request-Hash, X-Airnode-Timestamp and X-Airnode-Signature headers.",
        "properties": {
          "method": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "body": {
            "type": "string",
            "description": "The JSON body to send, when the call takes one."
          }
        },
        "additionalProperties": false
      },
      "Parameter": {
        "type": "object",
        "required": [
          "type",
          "required"
        ],
        "properties": {
          "type": {
            "type": "string"
          },
          "required": {
            "type": "boolean"
          }
        },
        "additionalProperties": false
      },
      "Payment": {
        "type": "object",
        "required": [
          "accepts"
        ],
        "properties": {
          "accepts": {
            "type": "array",
            "description": "One entry per network and token the call can be paid in.",
            "items": {
              "$ref": "#/components/schemas/PaymentEntry"
            }
          }
        },
        "additionalProperties": false
      },
      "PaymentEntry": {
        "type": "object",
        "required": [
          "scheme",
          "network",
          "asset",
          "amount"
        ],
        "properties": {
          "scheme": {
            "type": "string",
            "enum": [
              "exact"
            ]
          },
          "network": {
            "type": "string"
          },
          "asset": {
            "type": "string"
          },
          "amount": {
            "type": "string",
            "pattern": "^[0-9]+$",
            "description": "The x402 v2 amount, in the asset atomic unit. This is information, not payment authority."
          }
        },
        "additionalProperties": false
      }
    }
  }
}
