> For the complete documentation index, see [llms.txt](https://docs.kiiglobal.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.kiiglobal.io/docs/kiichain-pay/api-reference/market.md).

# Market

## GetDexQuote returns a cross-chain route quote from the configured DEX provider

> Quote-only. Does not execute the swap. The response carries the ordered transactions the\
> caller has to submit to execute it, approvals included

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"description":"Queries (read operations)","name":"MarketQueryService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"paths":{"/market/v1/dex/quote":{"post":{"description":"Quote-only. Does not execute the swap. The response carries the ordered transactions the\ncaller has to submit to execute it, approvals included","operationId":"MarketQueryService_GetDexQuote","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/dexGetDexQuoteRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/dexGetDexQuoteResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"GetDexQuote returns a cross-chain route quote from the configured DEX provider","tags":["MarketQueryService"]}}},"components":{"schemas":{"dexGetDexQuoteRequest":{"properties":{"allowMultiTx":{"title":"allow_multi_tx allows routes that require more than one transaction","type":"boolean"},"assetIn":{"$ref":"#/components/schemas/dexDexAssetAmount"},"assetOut":{"$ref":"#/components/schemas/dexDexAsset"},"senderAddress":{"description":"sender_address is the wallet address of the user initiating the swap.","type":"string"}},"required":["assetIn","assetOut"],"title":"GetDexQuoteRequest is the request body for the GetDexQuote method","type":"object"},"dexDexAssetAmount":{"properties":{"amount":{"title":"amount is the quantity in the asset's base denomination (integer, no decimals)","type":"string"},"chainId":{"title":"chain_id is the chain the asset lives on","type":"string"},"denom":{"title":"denom is the asset denomination","type":"string"}},"required":["denom","chainId","amount"],"title":"DexAssetAmount is a cross-chain asset paired with an amount","type":"object"},"dexDexAsset":{"properties":{"chainId":{"title":"chain_id is the chain the asset lives on","type":"string"},"denom":{"title":"denom is the asset denomination (e.g. ERC-20 contract address or native token sentinel)","type":"string"}},"required":["denom","chainId"],"title":"DexAsset identifies a cross-chain asset by its denomination and chain","type":"object"},"dexGetDexQuoteResponse":{"properties":{"affiliateAddress":{"description":"affiliate_address is the address that receives the affiliate fee for this route.","type":"string"},"affiliateFeeBps":{"description":"affiliate_fee_bps is the affiliate fee in basis points applied to this route (e.g. 100 = 1.00%).","format":"int32","type":"integer"},"assetIn":{"$ref":"#/components/schemas/dexDexAssetAmount"},"assetOut":{"$ref":"#/components/schemas/dexDexAssetAmount"},"minAmountOut":{"description":"min_amount_out is the smallest output the route was built for, in the destination asset's\nbase units.","type":"string"},"provider":{"description":"provider identifies which DEX routing provider fulfilled this quote (\"skip\" or \"lifi\").","type":"string"},"swapPriceImpactPercent":{"title":"swap_price_impact_percent is the price impact of any swaps in the route","type":"string"},"transactions":{"description":"transactions is the ordered list the caller submits to execute the route, approvals included.\nEach transaction carries its own type (\"approval\", \"dexswap\"), so the client renders and\nsubmits them in order without inspecting the calldata.\nEmpty when sender_address was not supplied, which makes the response a pricing-only quote.","items":{"$ref":"#/components/schemas/blockchainV1Transaction"},"type":"array"},"usdAmountIn":{"title":"usd_amount_in is the USD value of the input amount","type":"string"},"usdAmountOut":{"title":"usd_amount_out is the USD value of the output amount","type":"string"}},"title":"GetDexQuoteResponse is the response for the GetDexQuote method","type":"object"},"blockchainV1Transaction":{"properties":{"evm":{"$ref":"#/components/schemas/v1EVMTransaction"}},"title":"Transaction wraps the transactions to build an ordered list","type":"object"},"v1EVMTransaction":{"properties":{"chainId":{"title":"chain_id is the ID of the network","type":"string"},"data":{"title":"data is the hex raw call data to be sent on the transaction","type":"string"},"from":{"title":"from is the address from which the transaction should be sent","type":"string"},"metadata":{"additionalProperties":{"type":"string"},"title":"metadata is the map of additional information to be sent with the transaction","type":"object"},"to":{"title":"to is the address to which the transaction should be sent","type":"string"},"type":{"title":"type is the type of the tx -- kiirouter, approval, etc","type":"string"},"value":{"title":"value is the amount of native token to be sent with the transaction","type":"string"}},"required":["type","chainId","from","to","value","data"],"title":"EVMTransaction represents an EVM transaction to be sent to the blockchain","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}}}
```

## GetFiatAssets returns a list of fiat assets

> Static reference list of fiat currencies (ISO codes) supported across\
> on-ramp/off-ramp products

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"description":"Queries (read operations)","name":"MarketQueryService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["market.fiat_assets.read"]},{"BearerAuth":["market.fiat_assets.read"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"fiat_assetsGetFiatAssetsResponse":{"properties":{"fiatAssets":{"items":{"$ref":"#/components/schemas/v1FiatAsset"},"title":"fiat_assets represents the list of fiat assets","type":"array"}},"required":["fiatAssets"],"title":"GetFiatAssetsResponse is the body response structure from the GetFiatAssets endpoint","type":"object"},"v1FiatAsset":{"properties":{"code":{"title":"code represents the fiat asset identifier using ISO 4217","type":"string"},"minorUnits":{"format":"int32","title":"minor_units is the number of decimal places this fiat currency's minor unit uses (e.g. 2 for\nBRL/MXN centavos) - the source of truth for converting between fiat minor units and face value","type":"integer"},"name":{"title":"name represents the fiat asset name","type":"string"},"symbol":{"title":"symbol represents the fiat asset symbol","type":"string"}},"required":["code","name","symbol","minorUnits"],"title":"FiatAsset contains the fiat asset data","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/market/v1/fiat-assets":{"get":{"description":"Static reference list of fiat currencies (ISO codes) supported across\non-ramp/off-ramp products","operationId":"MarketQueryService_GetFiatAssets","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/fiat_assetsGetFiatAssetsResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"GetFiatAssets returns a list of fiat assets","tags":["MarketQueryService"]}}}}
```

## GetFiatAsset returns a fiat asset by id

> code is the 3-letter ISO fiat currency code (e.g. "USD", "BRL")

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"description":"Queries (read operations)","name":"MarketQueryService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["market.fiat_assets.read"]},{"BearerAuth":["market.fiat_assets.read"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"fiat_assetsGetFiatAssetResponse":{"properties":{"fiatAsset":{"$ref":"#/components/schemas/v1FiatAsset"}},"required":["fiatAsset"],"title":"GetFiatAssetResponse is the body response structure from the GetFiatAsset endpoint","type":"object"},"v1FiatAsset":{"properties":{"code":{"title":"code represents the fiat asset identifier using ISO 4217","type":"string"},"minorUnits":{"format":"int32","title":"minor_units is the number of decimal places this fiat currency's minor unit uses (e.g. 2 for\nBRL/MXN centavos) - the source of truth for converting between fiat minor units and face value","type":"integer"},"name":{"title":"name represents the fiat asset name","type":"string"},"symbol":{"title":"symbol represents the fiat asset symbol","type":"string"}},"required":["code","name","symbol","minorUnits"],"title":"FiatAsset contains the fiat asset data","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/market/v1/fiat-assets/{code}":{"get":{"description":"code is the 3-letter ISO fiat currency code (e.g. \"USD\", \"BRL\")","operationId":"MarketQueryService_GetFiatAsset","parameters":[{"description":"code represents the fiat asset identifier","in":"path","name":"code","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/fiat_assetsGetFiatAssetResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"GetFiatAsset returns a fiat asset by id","tags":["MarketQueryService"]}}}}
```

## ListInstruments lists all the instruments for the users

> Scoped to the instruments account\_id has access to, not a global list

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"description":"Queries (read operations)","name":"MarketQueryService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["market.instruments.read"]},{"BearerAuth":["market.instruments.read"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"instrumentsListInstrumentsResponse":{"properties":{"instruments":{"items":{"$ref":"#/components/schemas/instrumentsInstrument"},"title":"instruments is the list of instruments","type":"array"}},"required":["instruments"],"title":"ListInstrumentsResponse is the response message for the ListInstruments method","type":"object"},"instrumentsInstrument":{"properties":{"createdAt":{"format":"date-time","title":"created_at is the timestamp when the relation products providers was created","type":"string"},"description":{"title":"description is the description of the instrument","type":"string"},"enabled":{"title":"enabled is the flag that shows if the instrument is enabled or disabled","type":"boolean"},"id":{"title":"id is the instrument identificator","type":"string"},"name":{"title":"name is the name of the instrument","type":"string"},"productBase":{"$ref":"#/components/schemas/productsProduct"},"productQuote":{"$ref":"#/components/schemas/productsProduct"},"provider":{"$ref":"#/components/schemas/providersProvider"},"spread":{"$ref":"#/components/schemas/instrumentsSpread"},"updatedAt":{"format":"date-time","title":"updated_at is the timestamp when the relation products providers was updated","type":"string"}},"required":["id","name","description","productBase","productQuote","provider","enabled","spread","createdAt","updatedAt"],"title":"Instrument defines the Instrument type","type":"object"},"productsProduct":{"properties":{"applyAmlCheck":{"title":"apply_aml_check indicates whether an AML check via Elliptic should be run before the ticket is accepted","type":"boolean"},"chainToken":{"$ref":"#/components/schemas/v1ChainToken"},"enabled":{"title":"enabled indicates whether the product is enabled","type":"boolean"},"feeSpec":{"$ref":"#/components/schemas/productsFeeSpec"},"fiatAsset":{"$ref":"#/components/schemas/v1FiatAsset"},"id":{"title":"id is the ID of the product","type":"string"},"name":{"title":"name is the name of the product","type":"string"},"type":{"title":"type contains the type of the product (crypto | fiat)","type":"string"}},"required":["id","name","enabled","feeSpec","applyAmlCheck","type"],"title":"Product represents a product in the market","type":"object"},"v1ChainToken":{"properties":{"chain":{"$ref":"#/components/schemas/v1Chain"},"chainTokenEnabled":{"title":"chain_token_enabled indicates whether the token is enabled for this specific chain","type":"boolean"},"contractAddress":{"title":"contract_address is the smart contract address of the token on the chain (null for native tokens)","type":"string"},"enabledDex":{"title":"enabled_dex indicates whether the token is enabled for DEX operations on this chain","type":"boolean"},"fireblocksDenom":{"title":"fireblocks_denom is the asset denomination Fireblocks uses for this chain-token (e.g.\n\"USDT_POLYGON\"), used to interact with Fireblocks custody instead of resolving it live from\nFireblocks' own API - null if this asset isn't Fireblocks-custodied","type":"string"},"id":{"format":"int32","title":"id is the surrogate identifier of the chain-token relation","type":"integer"},"native":{"title":"native indicates whether the token is native to the chain","type":"boolean"},"token":{"$ref":"#/components/schemas/v1Token"}},"required":["id","chain","token","native","chainTokenEnabled","enabledDex"],"title":"ChainToken represents a token enabled on a specific chain","type":"object"},"v1Chain":{"properties":{"chainId":{"title":"chain_id is the blockchain network identifier (e.g., \"1\" for Ethereum, \"137\" for Polygon)","type":"string"},"confirmationDepth":{"format":"int32","title":"confirmation_depth is the number of block confirmations required before processing","type":"integer"},"contracts":{"additionalProperties":{"$ref":"#/components/schemas/v1ContractEntry"},"title":"contracts maps contract name to its on-chain address and ABI version","type":"object"},"enabled":{"title":"enabled indicates whether the chain is enabled on the platform","type":"boolean"},"feeAddress":{"title":"fee_address is the address that receives the affiliate fee on this chain","type":"string"},"feeBps":{"format":"int32","title":"fee_bps is the affiliate fee in basis points charged on routes through this chain (e.g. 30 = 0.30%)","type":"integer"},"id":{"format":"int32","title":"id is the surrogate identifier of the chain","type":"integer"},"logo":{"title":"logo is the URL to the logo of the chain","type":"string"},"name":{"title":"name is the human-readable name of the chain","type":"string"},"testnet":{"title":"testnet indicates whether the chain is a testnet or mainnet","type":"boolean"},"type":{"title":"type is the type of the chain (e.g., \"evm\", \"cosmos\", \"solana\", \"bitcoin\", \"tron\")","type":"string"}},"required":["id","chainId","type","name","logo","testnet","enabled","confirmationDepth","contracts"],"title":"Chain represents a chain supported by the platform","type":"object"},"v1ContractEntry":{"properties":{"address":{"title":"address is the on-chain contract address","type":"string"},"version":{"title":"version is the optional version identifier","type":"string"}},"required":["address"],"title":"ContractEntry represents a single on-chain contract: its address and optional ABI version","type":"object"},"v1Token":{"properties":{"decimals":{"format":"int32","title":"decimals is the number of decimal places the token uses","type":"integer"},"enabled":{"title":"enabled indicates whether the token is enabled on the platform","type":"boolean"},"id":{"format":"int32","title":"id is the surrogate identifier of the token","type":"integer"},"logo":{"title":"logo is the URL to the token's logo image","type":"string"},"name":{"title":"name is the full name of the token","type":"string"},"stable":{"title":"stable indicates whether the token is a stablecoin","type":"boolean"},"symbol":{"title":"symbol is the ticker symbol of the token","type":"string"}},"required":["id","name","symbol","decimals","logo","enabled","stable"],"title":"Token represents a coin/token supported by the platform","type":"object"},"productsFeeSpec":{"properties":{"bpsValue":{"title":"bps_value is the basis points (0–10000); required for bps and max fee types","type":"string"},"flatValue":{"title":"flat_value is the fixed fee amount; required for flat and max fee types","type":"string"},"type":{"title":"type is the type of fee specification (flat, bps or max)","type":"string"}},"required":["type"],"title":"FeeSpec represents the fee specification for a product","type":"object"},"v1FiatAsset":{"properties":{"code":{"title":"code represents the fiat asset identifier using ISO 4217","type":"string"},"minorUnits":{"format":"int32","title":"minor_units is the number of decimal places this fiat currency's minor unit uses (e.g. 2 for\nBRL/MXN centavos) - the source of truth for converting between fiat minor units and face value","type":"integer"},"name":{"title":"name represents the fiat asset name","type":"string"},"symbol":{"title":"symbol represents the fiat asset symbol","type":"string"}},"required":["code","name","symbol","minorUnits"],"title":"FiatAsset contains the fiat asset data","type":"object"},"providersProvider":{"properties":{"additionalTemplate":{"$ref":"#/components/schemas/typesV1Schema"},"autoConfirm":{"title":"auto_confirm indicates whether the provider's off-ramp tickets are automatically confirmed","type":"boolean"},"enabled":{"title":"enabled indicates whether the provider is enabled","type":"boolean"},"id":{"title":"id is the ID of the provider","type":"string"},"identifier":{"title":"identifier is the identifier of the provider","type":"string"},"isUserAllowed":{"title":"is_user_allowed indicates whether the user is allowed to use the provider","type":"boolean"},"kycStatus":{"description":"kyc_status is the current KYC verification status for the requesting user on this provider.","type":"string"},"name":{"title":"name is the name of the provider","type":"string"}},"required":["id","identifier","name","enabled","isUserAllowed","kycStatus","autoConfirm"],"title":"Provider defines the Provider","type":"object"},"typesV1Schema":{"properties":{"fields":{"items":{"$ref":"#/components/schemas/v1FieldSchema"},"title":"fields are the fields that the schema contains","type":"array"},"title":{"title":"title is the name of the schema","type":"string"}},"required":["title","fields"],"title":"Schema defines the Schema type used to returns schemas on Rails and providers","type":"object"},"v1FieldSchema":{"properties":{"name":{"title":"name is the name of the field required by the backend","type":"string"},"optional":{"title":"optional contains the flag that determines if the field is optional or not","type":"boolean"},"options":{"items":{"type":"string"},"title":"options contains the available options if type is an enum","type":"array"},"pattern":{"title":"pattern contains the regex expresion to evaluate the field","type":"string"},"type":{"title":"type contains the type of the field","type":"string"}},"required":["name","type","optional"],"title":"FieldSchema describe the field on the schema and its properties","type":"object"},"instrumentsSpread":{"properties":{"bps":{"$ref":"#/components/schemas/instrumentsBpsSpread"}},"title":"Spread represents the Spread for an instrument","type":"object"},"instrumentsBpsSpread":{"properties":{"askBps":{"format":"int64","title":"ask_bps is the ask bps spread","type":"string"},"bidBps":{"format":"int64","title":"bid_bps is the bid bps spread","type":"string"}},"required":["bidBps","askBps"],"title":"BpsSpread represents a bps spread for an instrument","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/market/v1/instruments":{"get":{"description":"Scoped to the instruments account_id has access to, not a global list","operationId":"MarketQueryService_ListInstruments","parameters":[{"description":"account_id is the account identifier used to validate if the user has access to the provider","in":"query","name":"accountId","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/instrumentsListInstrumentsResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"ListInstruments lists all the instruments for the users","tags":["MarketQueryService"]}}}}
```

## GetInstrument retrieves a single instrument by its id

> account\_id is checked to confirm the caller has access to this\
> instrument before returning it

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"description":"Queries (read operations)","name":"MarketQueryService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["market.instruments.read"]},{"BearerAuth":["market.instruments.read"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"instrumentsGetInstrumentResponse":{"properties":{"instrument":{"$ref":"#/components/schemas/instrumentsInstrument"}},"required":["instrument"],"title":"GetInstrumentResponse is the response message for the GetInstrument method","type":"object"},"instrumentsInstrument":{"properties":{"createdAt":{"format":"date-time","title":"created_at is the timestamp when the relation products providers was created","type":"string"},"description":{"title":"description is the description of the instrument","type":"string"},"enabled":{"title":"enabled is the flag that shows if the instrument is enabled or disabled","type":"boolean"},"id":{"title":"id is the instrument identificator","type":"string"},"name":{"title":"name is the name of the instrument","type":"string"},"productBase":{"$ref":"#/components/schemas/productsProduct"},"productQuote":{"$ref":"#/components/schemas/productsProduct"},"provider":{"$ref":"#/components/schemas/providersProvider"},"spread":{"$ref":"#/components/schemas/instrumentsSpread"},"updatedAt":{"format":"date-time","title":"updated_at is the timestamp when the relation products providers was updated","type":"string"}},"required":["id","name","description","productBase","productQuote","provider","enabled","spread","createdAt","updatedAt"],"title":"Instrument defines the Instrument type","type":"object"},"productsProduct":{"properties":{"applyAmlCheck":{"title":"apply_aml_check indicates whether an AML check via Elliptic should be run before the ticket is accepted","type":"boolean"},"chainToken":{"$ref":"#/components/schemas/v1ChainToken"},"enabled":{"title":"enabled indicates whether the product is enabled","type":"boolean"},"feeSpec":{"$ref":"#/components/schemas/productsFeeSpec"},"fiatAsset":{"$ref":"#/components/schemas/v1FiatAsset"},"id":{"title":"id is the ID of the product","type":"string"},"name":{"title":"name is the name of the product","type":"string"},"type":{"title":"type contains the type of the product (crypto | fiat)","type":"string"}},"required":["id","name","enabled","feeSpec","applyAmlCheck","type"],"title":"Product represents a product in the market","type":"object"},"v1ChainToken":{"properties":{"chain":{"$ref":"#/components/schemas/v1Chain"},"chainTokenEnabled":{"title":"chain_token_enabled indicates whether the token is enabled for this specific chain","type":"boolean"},"contractAddress":{"title":"contract_address is the smart contract address of the token on the chain (null for native tokens)","type":"string"},"enabledDex":{"title":"enabled_dex indicates whether the token is enabled for DEX operations on this chain","type":"boolean"},"fireblocksDenom":{"title":"fireblocks_denom is the asset denomination Fireblocks uses for this chain-token (e.g.\n\"USDT_POLYGON\"), used to interact with Fireblocks custody instead of resolving it live from\nFireblocks' own API - null if this asset isn't Fireblocks-custodied","type":"string"},"id":{"format":"int32","title":"id is the surrogate identifier of the chain-token relation","type":"integer"},"native":{"title":"native indicates whether the token is native to the chain","type":"boolean"},"token":{"$ref":"#/components/schemas/v1Token"}},"required":["id","chain","token","native","chainTokenEnabled","enabledDex"],"title":"ChainToken represents a token enabled on a specific chain","type":"object"},"v1Chain":{"properties":{"chainId":{"title":"chain_id is the blockchain network identifier (e.g., \"1\" for Ethereum, \"137\" for Polygon)","type":"string"},"confirmationDepth":{"format":"int32","title":"confirmation_depth is the number of block confirmations required before processing","type":"integer"},"contracts":{"additionalProperties":{"$ref":"#/components/schemas/v1ContractEntry"},"title":"contracts maps contract name to its on-chain address and ABI version","type":"object"},"enabled":{"title":"enabled indicates whether the chain is enabled on the platform","type":"boolean"},"feeAddress":{"title":"fee_address is the address that receives the affiliate fee on this chain","type":"string"},"feeBps":{"format":"int32","title":"fee_bps is the affiliate fee in basis points charged on routes through this chain (e.g. 30 = 0.30%)","type":"integer"},"id":{"format":"int32","title":"id is the surrogate identifier of the chain","type":"integer"},"logo":{"title":"logo is the URL to the logo of the chain","type":"string"},"name":{"title":"name is the human-readable name of the chain","type":"string"},"testnet":{"title":"testnet indicates whether the chain is a testnet or mainnet","type":"boolean"},"type":{"title":"type is the type of the chain (e.g., \"evm\", \"cosmos\", \"solana\", \"bitcoin\", \"tron\")","type":"string"}},"required":["id","chainId","type","name","logo","testnet","enabled","confirmationDepth","contracts"],"title":"Chain represents a chain supported by the platform","type":"object"},"v1ContractEntry":{"properties":{"address":{"title":"address is the on-chain contract address","type":"string"},"version":{"title":"version is the optional version identifier","type":"string"}},"required":["address"],"title":"ContractEntry represents a single on-chain contract: its address and optional ABI version","type":"object"},"v1Token":{"properties":{"decimals":{"format":"int32","title":"decimals is the number of decimal places the token uses","type":"integer"},"enabled":{"title":"enabled indicates whether the token is enabled on the platform","type":"boolean"},"id":{"format":"int32","title":"id is the surrogate identifier of the token","type":"integer"},"logo":{"title":"logo is the URL to the token's logo image","type":"string"},"name":{"title":"name is the full name of the token","type":"string"},"stable":{"title":"stable indicates whether the token is a stablecoin","type":"boolean"},"symbol":{"title":"symbol is the ticker symbol of the token","type":"string"}},"required":["id","name","symbol","decimals","logo","enabled","stable"],"title":"Token represents a coin/token supported by the platform","type":"object"},"productsFeeSpec":{"properties":{"bpsValue":{"title":"bps_value is the basis points (0–10000); required for bps and max fee types","type":"string"},"flatValue":{"title":"flat_value is the fixed fee amount; required for flat and max fee types","type":"string"},"type":{"title":"type is the type of fee specification (flat, bps or max)","type":"string"}},"required":["type"],"title":"FeeSpec represents the fee specification for a product","type":"object"},"v1FiatAsset":{"properties":{"code":{"title":"code represents the fiat asset identifier using ISO 4217","type":"string"},"minorUnits":{"format":"int32","title":"minor_units is the number of decimal places this fiat currency's minor unit uses (e.g. 2 for\nBRL/MXN centavos) - the source of truth for converting between fiat minor units and face value","type":"integer"},"name":{"title":"name represents the fiat asset name","type":"string"},"symbol":{"title":"symbol represents the fiat asset symbol","type":"string"}},"required":["code","name","symbol","minorUnits"],"title":"FiatAsset contains the fiat asset data","type":"object"},"providersProvider":{"properties":{"additionalTemplate":{"$ref":"#/components/schemas/typesV1Schema"},"autoConfirm":{"title":"auto_confirm indicates whether the provider's off-ramp tickets are automatically confirmed","type":"boolean"},"enabled":{"title":"enabled indicates whether the provider is enabled","type":"boolean"},"id":{"title":"id is the ID of the provider","type":"string"},"identifier":{"title":"identifier is the identifier of the provider","type":"string"},"isUserAllowed":{"title":"is_user_allowed indicates whether the user is allowed to use the provider","type":"boolean"},"kycStatus":{"description":"kyc_status is the current KYC verification status for the requesting user on this provider.","type":"string"},"name":{"title":"name is the name of the provider","type":"string"}},"required":["id","identifier","name","enabled","isUserAllowed","kycStatus","autoConfirm"],"title":"Provider defines the Provider","type":"object"},"typesV1Schema":{"properties":{"fields":{"items":{"$ref":"#/components/schemas/v1FieldSchema"},"title":"fields are the fields that the schema contains","type":"array"},"title":{"title":"title is the name of the schema","type":"string"}},"required":["title","fields"],"title":"Schema defines the Schema type used to returns schemas on Rails and providers","type":"object"},"v1FieldSchema":{"properties":{"name":{"title":"name is the name of the field required by the backend","type":"string"},"optional":{"title":"optional contains the flag that determines if the field is optional or not","type":"boolean"},"options":{"items":{"type":"string"},"title":"options contains the available options if type is an enum","type":"array"},"pattern":{"title":"pattern contains the regex expresion to evaluate the field","type":"string"},"type":{"title":"type contains the type of the field","type":"string"}},"required":["name","type","optional"],"title":"FieldSchema describe the field on the schema and its properties","type":"object"},"instrumentsSpread":{"properties":{"bps":{"$ref":"#/components/schemas/instrumentsBpsSpread"}},"title":"Spread represents the Spread for an instrument","type":"object"},"instrumentsBpsSpread":{"properties":{"askBps":{"format":"int64","title":"ask_bps is the ask bps spread","type":"string"},"bidBps":{"format":"int64","title":"bid_bps is the bid bps spread","type":"string"}},"required":["bidBps","askBps"],"title":"BpsSpread represents a bps spread for an instrument","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/market/v1/instruments/{id}":{"get":{"description":"account_id is checked to confirm the caller has access to this\ninstrument before returning it","operationId":"MarketQueryService_GetInstrument","parameters":[{"description":"id is the id of the instrument","in":"path","name":"id","required":true,"schema":{"type":"string"}},{"description":"account_id is the account identifier used to validate if the user has access to the instrument","in":"query","name":"accountId","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/instrumentsGetInstrumentResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"GetInstrument retrieves a single instrument by its id","tags":["MarketQueryService"]}}}}
```

## GetInstrumentLimits retrieves the limits from the provided instrument

> Returns the min/max tradeable amount for the given side (buy or sell)

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"description":"Queries (read operations)","name":"MarketQueryService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["market.instruments.read"]},{"BearerAuth":["market.instruments.read"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"instrumentsGetInstrumentLimitsResponse":{"properties":{"limits":{"$ref":"#/components/schemas/v1InstrumentLimits"}},"required":["limits"],"title":"GetInstrumentLimitsResponse is the response message for the GetInstrumentLimits method","type":"object"},"v1InstrumentLimits":{"properties":{"maxBaseAmount":{"title":"max_base_amount contains the maximum amount of the input asset to perform the action","type":"string"},"maxQuoteAmount":{"title":"max_quote_amount contains the maximum amount of the output asset to perform the action","type":"string"},"minBaseAmount":{"title":"min_base_amount contains the minimum amount of the input asset to perform the action","type":"string"},"minQuoteAmount":{"title":"min_quote_amount contains the minimum amount of the output asset to perform the action","type":"string"}},"required":["minBaseAmount","maxBaseAmount","minQuoteAmount","maxQuoteAmount"],"title":"InstrumentLimits contains the limits for an instrument","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/market/v1/instruments/{id}/limits":{"get":{"description":"Returns the min/max tradeable amount for the given side (buy or sell)","operationId":"MarketQueryService_GetInstrumentLimits","parameters":[{"description":"id is the id of the instrument","in":"path","name":"id","required":true,"schema":{"type":"string"}},{"description":"side is the side of the quote (buy or sell)","in":"query","name":"side","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/instrumentsGetInstrumentLimitsResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"GetInstrumentLimits retrieves the limits from the provided instrument","tags":["MarketQueryService"]}}}}
```

## GetInstrumentQuote retrieves the quote from the provided instrument

> Applies the instrument's configured spread on top of the underlying\
> provider price for the given side (buy or sell) and amount

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"description":"Queries (read operations)","name":"MarketQueryService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["market.instruments.read"]},{"BearerAuth":["market.instruments.read"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"instrumentsGetInstrumentQuoteResponse":{"properties":{"quote":{"$ref":"#/components/schemas/v1Quote"}},"required":["quote"],"title":"GetInstrumentQuoteResponse is the response message for the GetInstrumentQuote method","type":"object"},"v1Quote":{"properties":{"quotePayload":{"$ref":"#/components/schemas/v1QuotePayload"},"signature":{"title":"signature contains the signature of the quote","type":"string"}},"required":["quotePayload","signature"],"title":"Quote contains the quote information","type":"object"},"v1QuotePayload":{"properties":{"accountId":{"title":"account_id is the account identifier","type":"string"},"assetIn":{"$ref":"#/components/schemas/v1AssetRef"},"assetOut":{"$ref":"#/components/schemas/v1AssetRef"},"exp":{"format":"int64","title":"exp contains the expiration timestamp in Unix","type":"string"},"expirationDate":{"format":"date-time","title":"total_fee contains the fees substracted from the amounts\nexpiration_date contains the date when the quote will expire in RFC 3339 format","type":"string"},"externalId":{"title":"external_id is the identifier of the quote if the provider does not return\nthe quote values. Instead of that return an ID that have to be fetched by API","type":"string"},"id":{"title":"id is the quote identifier","type":"string"},"meta":{"additionalProperties":{"type":"string"},"title":"meta contains additional metadata attached to the quote","type":"object"},"penaltyFee":{"$ref":"#/components/schemas/v1AssetRef"},"price":{"title":"Price contains the final price shown to the user","type":"string"},"productFee":{"$ref":"#/components/schemas/v1AssetRef"},"providerFee":{"$ref":"#/components/schemas/v1AssetRef"},"targetId":{"title":"target_id is the target identifier when type is offramp/onramp the\ntarget_id is the UUID of the product_provider. Otherwise when\ntype is swap the target_id is the instrument UUID","type":"string"},"targetType":{"title":"target_type is the quote type (offramp | onramp | swap | trade)","type":"string"}},"required":["id","accountId","targetId","targetType","assetIn","assetOut","providerFee","productFee","price","expirationDate","exp","meta"],"title":"QuotePayload describe the quote payload","type":"object"},"v1AssetRef":{"properties":{"amount":{"title":"amount contains the amount of the asset","type":"string"},"code":{"title":"code contains the identifier of the asset","type":"string"},"productId":{"title":"product_id is the identifier of the product this asset resolved to, when known. Disambiguates\nbetween multiple products sharing the same code on one trade instrument (e.g. the same token\non different chains) - unset on quotes signed before this field existed","type":"string"},"type":{"title":"type contains the type of the asset (fiat | crypto)","type":"string"}},"required":["code","type","amount"],"title":"AssetRef contains the asset information","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/market/v1/instruments/{id}/quote":{"get":{"description":"Applies the instrument's configured spread on top of the underlying\nprovider price for the given side (buy or sell) and amount","operationId":"MarketQueryService_GetInstrumentQuote","parameters":[{"description":"id is the id of the instrument","in":"path","name":"id","required":true,"schema":{"type":"string"}},{"description":"amount contains the amount to transfer (must be atoms)","in":"query","name":"amount","required":true,"schema":{"type":"string"}},{"description":"account_id is the ID of the account used to sign the quote","in":"query","name":"accountId","required":true,"schema":{"type":"string"}},{"description":"side is the side of the quote (buy or sell)","in":"query","name":"side","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/instrumentsGetInstrumentQuoteResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"GetInstrumentQuote retrieves the quote from the provided instrument","tags":["MarketQueryService"]}}}}
```

## ListProducts lists all products with optional filtering

> Returns every product regardless of enabled status. Filter client-side\
> if only enabled ones are needed

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"description":"Queries (read operations)","name":"MarketQueryService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["market.products.read"]},{"BearerAuth":["market.products.read"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"productsListProductsResponse":{"properties":{"products":{"items":{"$ref":"#/components/schemas/productsProduct"},"title":"products is a list of retrieved products","type":"array"}},"required":["products"],"title":"ListProductsResponse is the response message for the ListProducts method","type":"object"},"productsProduct":{"properties":{"applyAmlCheck":{"title":"apply_aml_check indicates whether an AML check via Elliptic should be run before the ticket is accepted","type":"boolean"},"chainToken":{"$ref":"#/components/schemas/v1ChainToken"},"enabled":{"title":"enabled indicates whether the product is enabled","type":"boolean"},"feeSpec":{"$ref":"#/components/schemas/productsFeeSpec"},"fiatAsset":{"$ref":"#/components/schemas/v1FiatAsset"},"id":{"title":"id is the ID of the product","type":"string"},"name":{"title":"name is the name of the product","type":"string"},"type":{"title":"type contains the type of the product (crypto | fiat)","type":"string"}},"required":["id","name","enabled","feeSpec","applyAmlCheck","type"],"title":"Product represents a product in the market","type":"object"},"v1ChainToken":{"properties":{"chain":{"$ref":"#/components/schemas/v1Chain"},"chainTokenEnabled":{"title":"chain_token_enabled indicates whether the token is enabled for this specific chain","type":"boolean"},"contractAddress":{"title":"contract_address is the smart contract address of the token on the chain (null for native tokens)","type":"string"},"enabledDex":{"title":"enabled_dex indicates whether the token is enabled for DEX operations on this chain","type":"boolean"},"fireblocksDenom":{"title":"fireblocks_denom is the asset denomination Fireblocks uses for this chain-token (e.g.\n\"USDT_POLYGON\"), used to interact with Fireblocks custody instead of resolving it live from\nFireblocks' own API - null if this asset isn't Fireblocks-custodied","type":"string"},"id":{"format":"int32","title":"id is the surrogate identifier of the chain-token relation","type":"integer"},"native":{"title":"native indicates whether the token is native to the chain","type":"boolean"},"token":{"$ref":"#/components/schemas/v1Token"}},"required":["id","chain","token","native","chainTokenEnabled","enabledDex"],"title":"ChainToken represents a token enabled on a specific chain","type":"object"},"v1Chain":{"properties":{"chainId":{"title":"chain_id is the blockchain network identifier (e.g., \"1\" for Ethereum, \"137\" for Polygon)","type":"string"},"confirmationDepth":{"format":"int32","title":"confirmation_depth is the number of block confirmations required before processing","type":"integer"},"contracts":{"additionalProperties":{"$ref":"#/components/schemas/v1ContractEntry"},"title":"contracts maps contract name to its on-chain address and ABI version","type":"object"},"enabled":{"title":"enabled indicates whether the chain is enabled on the platform","type":"boolean"},"feeAddress":{"title":"fee_address is the address that receives the affiliate fee on this chain","type":"string"},"feeBps":{"format":"int32","title":"fee_bps is the affiliate fee in basis points charged on routes through this chain (e.g. 30 = 0.30%)","type":"integer"},"id":{"format":"int32","title":"id is the surrogate identifier of the chain","type":"integer"},"logo":{"title":"logo is the URL to the logo of the chain","type":"string"},"name":{"title":"name is the human-readable name of the chain","type":"string"},"testnet":{"title":"testnet indicates whether the chain is a testnet or mainnet","type":"boolean"},"type":{"title":"type is the type of the chain (e.g., \"evm\", \"cosmos\", \"solana\", \"bitcoin\", \"tron\")","type":"string"}},"required":["id","chainId","type","name","logo","testnet","enabled","confirmationDepth","contracts"],"title":"Chain represents a chain supported by the platform","type":"object"},"v1ContractEntry":{"properties":{"address":{"title":"address is the on-chain contract address","type":"string"},"version":{"title":"version is the optional version identifier","type":"string"}},"required":["address"],"title":"ContractEntry represents a single on-chain contract: its address and optional ABI version","type":"object"},"v1Token":{"properties":{"decimals":{"format":"int32","title":"decimals is the number of decimal places the token uses","type":"integer"},"enabled":{"title":"enabled indicates whether the token is enabled on the platform","type":"boolean"},"id":{"format":"int32","title":"id is the surrogate identifier of the token","type":"integer"},"logo":{"title":"logo is the URL to the token's logo image","type":"string"},"name":{"title":"name is the full name of the token","type":"string"},"stable":{"title":"stable indicates whether the token is a stablecoin","type":"boolean"},"symbol":{"title":"symbol is the ticker symbol of the token","type":"string"}},"required":["id","name","symbol","decimals","logo","enabled","stable"],"title":"Token represents a coin/token supported by the platform","type":"object"},"productsFeeSpec":{"properties":{"bpsValue":{"title":"bps_value is the basis points (0–10000); required for bps and max fee types","type":"string"},"flatValue":{"title":"flat_value is the fixed fee amount; required for flat and max fee types","type":"string"},"type":{"title":"type is the type of fee specification (flat, bps or max)","type":"string"}},"required":["type"],"title":"FeeSpec represents the fee specification for a product","type":"object"},"v1FiatAsset":{"properties":{"code":{"title":"code represents the fiat asset identifier using ISO 4217","type":"string"},"minorUnits":{"format":"int32","title":"minor_units is the number of decimal places this fiat currency's minor unit uses (e.g. 2 for\nBRL/MXN centavos) - the source of truth for converting between fiat minor units and face value","type":"integer"},"name":{"title":"name represents the fiat asset name","type":"string"},"symbol":{"title":"symbol represents the fiat asset symbol","type":"string"}},"required":["code","name","symbol","minorUnits"],"title":"FiatAsset contains the fiat asset data","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/market/v1/products":{"get":{"description":"Returns every product regardless of enabled status. Filter client-side\nif only enabled ones are needed","operationId":"MarketQueryService_ListProducts","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/productsListProductsResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"ListProducts lists all products with optional filtering","tags":["MarketQueryService"]}}}}
```

## ListProductsProviders returns the store relations products providers

> account\_id scopes the list to relations that account is allowed to use

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"description":"Queries (read operations)","name":"MarketQueryService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["market.products_providers.read","market.products_providers.read:all"]},{"BearerAuth":["market.products_providers.read","market.products_providers.read:all"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"products_providersListProductsProvidersResponse":{"properties":{"productsProviders":{"items":{"$ref":"#/components/schemas/products_providersProductsProvider"},"title":"products_providers is the list of relations products providers","type":"array"}},"required":["productsProviders"],"title":"ListProductsProvidersResponse is the response message for the ListProductsProviders method","type":"object"},"products_providersProductsProvider":{"properties":{"createdAt":{"format":"date-time","title":"created_at is the timestamp when the relation products providers was created","type":"string"},"enabled":{"title":"enabled is the flag that shows if the relation products providers is enabled or disabled","type":"boolean"},"fiatAsset":{"$ref":"#/components/schemas/v1FiatAsset"},"id":{"title":"id is the id of the relation products providers","type":"string"},"product":{"$ref":"#/components/schemas/productsProduct"},"provider":{"$ref":"#/components/schemas/providersProvider"},"type":{"title":"type is the type of the provider","type":"string"},"updatedAt":{"format":"date-time","title":"updated_at is the timestamp when the relation products providers was updated","type":"string"}},"required":["id","product","provider","fiatAsset","type","enabled","createdAt","updatedAt"],"title":"ProductsProvider defines the ProductsProvider type","type":"object"},"v1FiatAsset":{"properties":{"code":{"title":"code represents the fiat asset identifier using ISO 4217","type":"string"},"minorUnits":{"format":"int32","title":"minor_units is the number of decimal places this fiat currency's minor unit uses (e.g. 2 for\nBRL/MXN centavos) - the source of truth for converting between fiat minor units and face value","type":"integer"},"name":{"title":"name represents the fiat asset name","type":"string"},"symbol":{"title":"symbol represents the fiat asset symbol","type":"string"}},"required":["code","name","symbol","minorUnits"],"title":"FiatAsset contains the fiat asset data","type":"object"},"productsProduct":{"properties":{"applyAmlCheck":{"title":"apply_aml_check indicates whether an AML check via Elliptic should be run before the ticket is accepted","type":"boolean"},"chainToken":{"$ref":"#/components/schemas/v1ChainToken"},"enabled":{"title":"enabled indicates whether the product is enabled","type":"boolean"},"feeSpec":{"$ref":"#/components/schemas/productsFeeSpec"},"fiatAsset":{"$ref":"#/components/schemas/v1FiatAsset"},"id":{"title":"id is the ID of the product","type":"string"},"name":{"title":"name is the name of the product","type":"string"},"type":{"title":"type contains the type of the product (crypto | fiat)","type":"string"}},"required":["id","name","enabled","feeSpec","applyAmlCheck","type"],"title":"Product represents a product in the market","type":"object"},"v1ChainToken":{"properties":{"chain":{"$ref":"#/components/schemas/v1Chain"},"chainTokenEnabled":{"title":"chain_token_enabled indicates whether the token is enabled for this specific chain","type":"boolean"},"contractAddress":{"title":"contract_address is the smart contract address of the token on the chain (null for native tokens)","type":"string"},"enabledDex":{"title":"enabled_dex indicates whether the token is enabled for DEX operations on this chain","type":"boolean"},"fireblocksDenom":{"title":"fireblocks_denom is the asset denomination Fireblocks uses for this chain-token (e.g.\n\"USDT_POLYGON\"), used to interact with Fireblocks custody instead of resolving it live from\nFireblocks' own API - null if this asset isn't Fireblocks-custodied","type":"string"},"id":{"format":"int32","title":"id is the surrogate identifier of the chain-token relation","type":"integer"},"native":{"title":"native indicates whether the token is native to the chain","type":"boolean"},"token":{"$ref":"#/components/schemas/v1Token"}},"required":["id","chain","token","native","chainTokenEnabled","enabledDex"],"title":"ChainToken represents a token enabled on a specific chain","type":"object"},"v1Chain":{"properties":{"chainId":{"title":"chain_id is the blockchain network identifier (e.g., \"1\" for Ethereum, \"137\" for Polygon)","type":"string"},"confirmationDepth":{"format":"int32","title":"confirmation_depth is the number of block confirmations required before processing","type":"integer"},"contracts":{"additionalProperties":{"$ref":"#/components/schemas/v1ContractEntry"},"title":"contracts maps contract name to its on-chain address and ABI version","type":"object"},"enabled":{"title":"enabled indicates whether the chain is enabled on the platform","type":"boolean"},"feeAddress":{"title":"fee_address is the address that receives the affiliate fee on this chain","type":"string"},"feeBps":{"format":"int32","title":"fee_bps is the affiliate fee in basis points charged on routes through this chain (e.g. 30 = 0.30%)","type":"integer"},"id":{"format":"int32","title":"id is the surrogate identifier of the chain","type":"integer"},"logo":{"title":"logo is the URL to the logo of the chain","type":"string"},"name":{"title":"name is the human-readable name of the chain","type":"string"},"testnet":{"title":"testnet indicates whether the chain is a testnet or mainnet","type":"boolean"},"type":{"title":"type is the type of the chain (e.g., \"evm\", \"cosmos\", \"solana\", \"bitcoin\", \"tron\")","type":"string"}},"required":["id","chainId","type","name","logo","testnet","enabled","confirmationDepth","contracts"],"title":"Chain represents a chain supported by the platform","type":"object"},"v1ContractEntry":{"properties":{"address":{"title":"address is the on-chain contract address","type":"string"},"version":{"title":"version is the optional version identifier","type":"string"}},"required":["address"],"title":"ContractEntry represents a single on-chain contract: its address and optional ABI version","type":"object"},"v1Token":{"properties":{"decimals":{"format":"int32","title":"decimals is the number of decimal places the token uses","type":"integer"},"enabled":{"title":"enabled indicates whether the token is enabled on the platform","type":"boolean"},"id":{"format":"int32","title":"id is the surrogate identifier of the token","type":"integer"},"logo":{"title":"logo is the URL to the token's logo image","type":"string"},"name":{"title":"name is the full name of the token","type":"string"},"stable":{"title":"stable indicates whether the token is a stablecoin","type":"boolean"},"symbol":{"title":"symbol is the ticker symbol of the token","type":"string"}},"required":["id","name","symbol","decimals","logo","enabled","stable"],"title":"Token represents a coin/token supported by the platform","type":"object"},"productsFeeSpec":{"properties":{"bpsValue":{"title":"bps_value is the basis points (0–10000); required for bps and max fee types","type":"string"},"flatValue":{"title":"flat_value is the fixed fee amount; required for flat and max fee types","type":"string"},"type":{"title":"type is the type of fee specification (flat, bps or max)","type":"string"}},"required":["type"],"title":"FeeSpec represents the fee specification for a product","type":"object"},"providersProvider":{"properties":{"additionalTemplate":{"$ref":"#/components/schemas/typesV1Schema"},"autoConfirm":{"title":"auto_confirm indicates whether the provider's off-ramp tickets are automatically confirmed","type":"boolean"},"enabled":{"title":"enabled indicates whether the provider is enabled","type":"boolean"},"id":{"title":"id is the ID of the provider","type":"string"},"identifier":{"title":"identifier is the identifier of the provider","type":"string"},"isUserAllowed":{"title":"is_user_allowed indicates whether the user is allowed to use the provider","type":"boolean"},"kycStatus":{"description":"kyc_status is the current KYC verification status for the requesting user on this provider.","type":"string"},"name":{"title":"name is the name of the provider","type":"string"}},"required":["id","identifier","name","enabled","isUserAllowed","kycStatus","autoConfirm"],"title":"Provider defines the Provider","type":"object"},"typesV1Schema":{"properties":{"fields":{"items":{"$ref":"#/components/schemas/v1FieldSchema"},"title":"fields are the fields that the schema contains","type":"array"},"title":{"title":"title is the name of the schema","type":"string"}},"required":["title","fields"],"title":"Schema defines the Schema type used to returns schemas on Rails and providers","type":"object"},"v1FieldSchema":{"properties":{"name":{"title":"name is the name of the field required by the backend","type":"string"},"optional":{"title":"optional contains the flag that determines if the field is optional or not","type":"boolean"},"options":{"items":{"type":"string"},"title":"options contains the available options if type is an enum","type":"array"},"pattern":{"title":"pattern contains the regex expresion to evaluate the field","type":"string"},"type":{"title":"type contains the type of the field","type":"string"}},"required":["name","type","optional"],"title":"FieldSchema describe the field on the schema and its properties","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/market/v1/products-providers":{"get":{"description":"account_id scopes the list to relations that account is allowed to use","operationId":"MarketQueryService_ListProductsProviders","parameters":[{"description":"account_id is the ID of the account to verify if it's allowed to use the provider","in":"query","name":"accountId","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/products_providersListProductsProvidersResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"ListProductsProviders returns the store relations products providers","tags":["MarketQueryService"]}}}}
```

## GetProductsProvider returns a single products provider relation by ID

> account\_id is checked to confirm the caller can use this relation

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"description":"Queries (read operations)","name":"MarketQueryService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["market.products_providers.read"]},{"BearerAuth":["market.products_providers.read"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"products_providersGetProductsProviderResponse":{"properties":{"productsProvider":{"$ref":"#/components/schemas/products_providersProductsProvider"}},"required":["productsProvider"],"title":"GetProductsProviderResponse is the response message for the GetProductsProvider method","type":"object"},"products_providersProductsProvider":{"properties":{"createdAt":{"format":"date-time","title":"created_at is the timestamp when the relation products providers was created","type":"string"},"enabled":{"title":"enabled is the flag that shows if the relation products providers is enabled or disabled","type":"boolean"},"fiatAsset":{"$ref":"#/components/schemas/v1FiatAsset"},"id":{"title":"id is the id of the relation products providers","type":"string"},"product":{"$ref":"#/components/schemas/productsProduct"},"provider":{"$ref":"#/components/schemas/providersProvider"},"type":{"title":"type is the type of the provider","type":"string"},"updatedAt":{"format":"date-time","title":"updated_at is the timestamp when the relation products providers was updated","type":"string"}},"required":["id","product","provider","fiatAsset","type","enabled","createdAt","updatedAt"],"title":"ProductsProvider defines the ProductsProvider type","type":"object"},"v1FiatAsset":{"properties":{"code":{"title":"code represents the fiat asset identifier using ISO 4217","type":"string"},"minorUnits":{"format":"int32","title":"minor_units is the number of decimal places this fiat currency's minor unit uses (e.g. 2 for\nBRL/MXN centavos) - the source of truth for converting between fiat minor units and face value","type":"integer"},"name":{"title":"name represents the fiat asset name","type":"string"},"symbol":{"title":"symbol represents the fiat asset symbol","type":"string"}},"required":["code","name","symbol","minorUnits"],"title":"FiatAsset contains the fiat asset data","type":"object"},"productsProduct":{"properties":{"applyAmlCheck":{"title":"apply_aml_check indicates whether an AML check via Elliptic should be run before the ticket is accepted","type":"boolean"},"chainToken":{"$ref":"#/components/schemas/v1ChainToken"},"enabled":{"title":"enabled indicates whether the product is enabled","type":"boolean"},"feeSpec":{"$ref":"#/components/schemas/productsFeeSpec"},"fiatAsset":{"$ref":"#/components/schemas/v1FiatAsset"},"id":{"title":"id is the ID of the product","type":"string"},"name":{"title":"name is the name of the product","type":"string"},"type":{"title":"type contains the type of the product (crypto | fiat)","type":"string"}},"required":["id","name","enabled","feeSpec","applyAmlCheck","type"],"title":"Product represents a product in the market","type":"object"},"v1ChainToken":{"properties":{"chain":{"$ref":"#/components/schemas/v1Chain"},"chainTokenEnabled":{"title":"chain_token_enabled indicates whether the token is enabled for this specific chain","type":"boolean"},"contractAddress":{"title":"contract_address is the smart contract address of the token on the chain (null for native tokens)","type":"string"},"enabledDex":{"title":"enabled_dex indicates whether the token is enabled for DEX operations on this chain","type":"boolean"},"fireblocksDenom":{"title":"fireblocks_denom is the asset denomination Fireblocks uses for this chain-token (e.g.\n\"USDT_POLYGON\"), used to interact with Fireblocks custody instead of resolving it live from\nFireblocks' own API - null if this asset isn't Fireblocks-custodied","type":"string"},"id":{"format":"int32","title":"id is the surrogate identifier of the chain-token relation","type":"integer"},"native":{"title":"native indicates whether the token is native to the chain","type":"boolean"},"token":{"$ref":"#/components/schemas/v1Token"}},"required":["id","chain","token","native","chainTokenEnabled","enabledDex"],"title":"ChainToken represents a token enabled on a specific chain","type":"object"},"v1Chain":{"properties":{"chainId":{"title":"chain_id is the blockchain network identifier (e.g., \"1\" for Ethereum, \"137\" for Polygon)","type":"string"},"confirmationDepth":{"format":"int32","title":"confirmation_depth is the number of block confirmations required before processing","type":"integer"},"contracts":{"additionalProperties":{"$ref":"#/components/schemas/v1ContractEntry"},"title":"contracts maps contract name to its on-chain address and ABI version","type":"object"},"enabled":{"title":"enabled indicates whether the chain is enabled on the platform","type":"boolean"},"feeAddress":{"title":"fee_address is the address that receives the affiliate fee on this chain","type":"string"},"feeBps":{"format":"int32","title":"fee_bps is the affiliate fee in basis points charged on routes through this chain (e.g. 30 = 0.30%)","type":"integer"},"id":{"format":"int32","title":"id is the surrogate identifier of the chain","type":"integer"},"logo":{"title":"logo is the URL to the logo of the chain","type":"string"},"name":{"title":"name is the human-readable name of the chain","type":"string"},"testnet":{"title":"testnet indicates whether the chain is a testnet or mainnet","type":"boolean"},"type":{"title":"type is the type of the chain (e.g., \"evm\", \"cosmos\", \"solana\", \"bitcoin\", \"tron\")","type":"string"}},"required":["id","chainId","type","name","logo","testnet","enabled","confirmationDepth","contracts"],"title":"Chain represents a chain supported by the platform","type":"object"},"v1ContractEntry":{"properties":{"address":{"title":"address is the on-chain contract address","type":"string"},"version":{"title":"version is the optional version identifier","type":"string"}},"required":["address"],"title":"ContractEntry represents a single on-chain contract: its address and optional ABI version","type":"object"},"v1Token":{"properties":{"decimals":{"format":"int32","title":"decimals is the number of decimal places the token uses","type":"integer"},"enabled":{"title":"enabled indicates whether the token is enabled on the platform","type":"boolean"},"id":{"format":"int32","title":"id is the surrogate identifier of the token","type":"integer"},"logo":{"title":"logo is the URL to the token's logo image","type":"string"},"name":{"title":"name is the full name of the token","type":"string"},"stable":{"title":"stable indicates whether the token is a stablecoin","type":"boolean"},"symbol":{"title":"symbol is the ticker symbol of the token","type":"string"}},"required":["id","name","symbol","decimals","logo","enabled","stable"],"title":"Token represents a coin/token supported by the platform","type":"object"},"productsFeeSpec":{"properties":{"bpsValue":{"title":"bps_value is the basis points (0–10000); required for bps and max fee types","type":"string"},"flatValue":{"title":"flat_value is the fixed fee amount; required for flat and max fee types","type":"string"},"type":{"title":"type is the type of fee specification (flat, bps or max)","type":"string"}},"required":["type"],"title":"FeeSpec represents the fee specification for a product","type":"object"},"providersProvider":{"properties":{"additionalTemplate":{"$ref":"#/components/schemas/typesV1Schema"},"autoConfirm":{"title":"auto_confirm indicates whether the provider's off-ramp tickets are automatically confirmed","type":"boolean"},"enabled":{"title":"enabled indicates whether the provider is enabled","type":"boolean"},"id":{"title":"id is the ID of the provider","type":"string"},"identifier":{"title":"identifier is the identifier of the provider","type":"string"},"isUserAllowed":{"title":"is_user_allowed indicates whether the user is allowed to use the provider","type":"boolean"},"kycStatus":{"description":"kyc_status is the current KYC verification status for the requesting user on this provider.","type":"string"},"name":{"title":"name is the name of the provider","type":"string"}},"required":["id","identifier","name","enabled","isUserAllowed","kycStatus","autoConfirm"],"title":"Provider defines the Provider","type":"object"},"typesV1Schema":{"properties":{"fields":{"items":{"$ref":"#/components/schemas/v1FieldSchema"},"title":"fields are the fields that the schema contains","type":"array"},"title":{"title":"title is the name of the schema","type":"string"}},"required":["title","fields"],"title":"Schema defines the Schema type used to returns schemas on Rails and providers","type":"object"},"v1FieldSchema":{"properties":{"name":{"title":"name is the name of the field required by the backend","type":"string"},"optional":{"title":"optional contains the flag that determines if the field is optional or not","type":"boolean"},"options":{"items":{"type":"string"},"title":"options contains the available options if type is an enum","type":"array"},"pattern":{"title":"pattern contains the regex expresion to evaluate the field","type":"string"},"type":{"title":"type contains the type of the field","type":"string"}},"required":["name","type","optional"],"title":"FieldSchema describe the field on the schema and its properties","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/market/v1/products-providers/{id}":{"get":{"description":"account_id is checked to confirm the caller can use this relation","operationId":"MarketQueryService_GetProductsProvider","parameters":[{"description":"id is the id of the relation products providers to retrieve","in":"path","name":"id","required":true,"schema":{"type":"string"}},{"description":"account_id is the ID of the account to verify if it's allowed to use the provider","in":"query","name":"accountId","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/products_providersGetProductsProviderResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"GetProductsProvider returns a single products provider relation by ID","tags":["MarketQueryService"]}}}}
```

## GetProductProviderLimits retrieves the limits for a provider based on the product, fiat and amount

> Returns the min/max tradeable amount for on-ramp/off-ramp through this\
> relation

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"description":"Queries (read operations)","name":"MarketQueryService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["market.products.read"]},{"BearerAuth":["market.products.read"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"products_providersGetProductProviderLimitsResponse":{"properties":{"limits":{"$ref":"#/components/schemas/v1Limits"}},"required":["limits"],"title":"GetProductProviderLimitsResponse is the response message for the GetProductProviderLimits method","type":"object"},"v1Limits":{"properties":{"maxFiatAmount":{"title":"max_fiat_amount contains the maximum amount of fiat asset to perform the action","type":"string"},"maxTokenAmount":{"title":"max_token_amount contains the maximum amount of token asset to perform the action","type":"string"},"minFiatAmount":{"title":"min_fiat_amount contains the minimum amount of fiat asset to perform the action","type":"string"},"minTokenAmount":{"title":"min_token_amount contains the minimum amount of token asset to perform the action","type":"string"}},"required":["minFiatAmount","maxFiatAmount","minTokenAmount","maxTokenAmount"],"title":"Limits contains the limits for a product_provider to perform an action\noff-ramp or on-ramp","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/market/v1/products-providers/{id}/limits":{"get":{"description":"Returns the min/max tradeable amount for on-ramp/off-ramp through this\nrelation","operationId":"MarketQueryService_GetProductProviderLimits","parameters":[{"description":"id is the id of the relation products providers","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/products_providersGetProductProviderLimitsResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"GetProductProviderLimits retrieves the limits for a provider based on the product, fiat and amount","tags":["MarketQueryService"]}}}}
```

## ProcessOnRamp initializes the on-ramp process with the given information

> Creates the on-ramp ticket and returns a provider-specific payload\
> Either a redirect URL (e.g. MoonPay widget) or PIX payment details\
> (e.g. Avenia PIX), depending on the provider

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"description":"Mutations (write operations)","name":"MarketMsgService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["market.products_providers_onramp.write"]},{"BearerAuth":["market.products_providers_onramp.write"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"MarketMsgServiceProcessOnRampBody":{"properties":{"accountId":{"title":"account_id is the ID of the account to verify if it's allowed to use the provider","type":"string"},"destinationId":{"title":"destination_id is the address that receives the funds, required for a crypto product and\nomitted for a fiat product (which settles inside the provider's own ledger)","type":"string"},"quote":{"$ref":"#/components/schemas/v1Quote"}},"required":["accountId","quote"],"title":"ProcessOnRampRequest is the request message for the ProcessOnRamp method","type":"object"},"v1Quote":{"properties":{"quotePayload":{"$ref":"#/components/schemas/v1QuotePayload"},"signature":{"title":"signature contains the signature of the quote","type":"string"}},"required":["quotePayload","signature"],"title":"Quote contains the quote information","type":"object"},"v1QuotePayload":{"properties":{"accountId":{"title":"account_id is the account identifier","type":"string"},"assetIn":{"$ref":"#/components/schemas/v1AssetRef"},"assetOut":{"$ref":"#/components/schemas/v1AssetRef"},"exp":{"format":"int64","title":"exp contains the expiration timestamp in Unix","type":"string"},"expirationDate":{"format":"date-time","title":"total_fee contains the fees substracted from the amounts\nexpiration_date contains the date when the quote will expire in RFC 3339 format","type":"string"},"externalId":{"title":"external_id is the identifier of the quote if the provider does not return\nthe quote values. Instead of that return an ID that have to be fetched by API","type":"string"},"id":{"title":"id is the quote identifier","type":"string"},"meta":{"additionalProperties":{"type":"string"},"title":"meta contains additional metadata attached to the quote","type":"object"},"penaltyFee":{"$ref":"#/components/schemas/v1AssetRef"},"price":{"title":"Price contains the final price shown to the user","type":"string"},"productFee":{"$ref":"#/components/schemas/v1AssetRef"},"providerFee":{"$ref":"#/components/schemas/v1AssetRef"},"targetId":{"title":"target_id is the target identifier when type is offramp/onramp the\ntarget_id is the UUID of the product_provider. Otherwise when\ntype is swap the target_id is the instrument UUID","type":"string"},"targetType":{"title":"target_type is the quote type (offramp | onramp | swap | trade)","type":"string"}},"required":["id","accountId","targetId","targetType","assetIn","assetOut","providerFee","productFee","price","expirationDate","exp","meta"],"title":"QuotePayload describe the quote payload","type":"object"},"v1AssetRef":{"properties":{"amount":{"title":"amount contains the amount of the asset","type":"string"},"code":{"title":"code contains the identifier of the asset","type":"string"},"productId":{"title":"product_id is the identifier of the product this asset resolved to, when known. Disambiguates\nbetween multiple products sharing the same code on one trade instrument (e.g. the same token\non different chains) - unset on quotes signed before this field existed","type":"string"},"type":{"title":"type contains the type of the asset (fiat | crypto)","type":"string"}},"required":["code","type","amount"],"title":"AssetRef contains the asset information","type":"object"},"products_providersProcessOnRampResponse":{"description":"ProcessOnRampResponse is the response message for the ProcessOnRamp method.\nExactly one of url_payload or deposit_payload is set, depending on the on-ramp type.","properties":{"depositPayload":{"$ref":"#/components/schemas/products_providersOnRampDepositPayload"},"ticketId":{"title":"ticket_id is the ticket ID associated with the on-ramp process","type":"string"},"urlPayload":{"$ref":"#/components/schemas/products_providersOnRampUrlPayload"}},"required":["ticketId"],"type":"object"},"products_providersOnRampDepositPayload":{"description":"OnRampDepositPayload contains the bank-deposit details returned by deposit-based\non-ramp providers. It is rail-agnostic: deposit_key holds the destination\nidentifier (a PIX key, a SPEI CLABE, or any future equivalent) and deposit_code\nholds an optional scannable/copy-paste code (e.g. the PIX BR Code).","properties":{"depositCode":{"title":"deposit_code is an optional copy-paste / QR code for the deposit (e.g. PIX BR Code)","type":"string"},"depositKey":{"title":"deposit_key is the destination identifier the user transfers funds to\n(PIX key, CLABE, etc.)","type":"string"}},"type":"object"},"products_providersOnRampUrlPayload":{"properties":{"expiresAt":{"format":"int64","title":"expires_at is the Unix timestamp when the URL expires","type":"string"},"url":{"title":"url is the redirect URL or widget URL","type":"string"}},"required":["url","expiresAt"],"title":"OnRampUrlPayload contains the redirect URL and expiry for URL-based on-ramp providers","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/market/v1/products-providers/{id}/onramp":{"post":{"description":"Creates the on-ramp ticket and returns a provider-specific payload\nEither a redirect URL (e.g. MoonPay widget) or PIX payment details\n(e.g. Avenia PIX), depending on the provider","operationId":"MarketMsgService_ProcessOnRamp","parameters":[{"description":"id is the id of the relation products providers","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarketMsgServiceProcessOnRampBody"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/products_providersProcessOnRampResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"ProcessOnRamp initializes the on-ramp process with the given information","tags":["MarketMsgService"]}}}}
```

## GetProductProviderQuote retrieves the quote for a product based on the provider, fiat and amount

> Quote-only. Use ProcessOnRamp separately to act on it. amount can be\
> crypto (atoms) or fiat (decimal) depending on the relation's direction

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"description":"Queries (read operations)","name":"MarketQueryService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["market.products.read"]},{"BearerAuth":["market.products.read"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"products_providersGetProductProviderQuoteResponse":{"properties":{"quote":{"$ref":"#/components/schemas/v1Quote"}},"required":["quote"],"title":"GetProductProviderQuoteResponse is the response message for the GetProductProviderQuote method","type":"object"},"v1Quote":{"properties":{"quotePayload":{"$ref":"#/components/schemas/v1QuotePayload"},"signature":{"title":"signature contains the signature of the quote","type":"string"}},"required":["quotePayload","signature"],"title":"Quote contains the quote information","type":"object"},"v1QuotePayload":{"properties":{"accountId":{"title":"account_id is the account identifier","type":"string"},"assetIn":{"$ref":"#/components/schemas/v1AssetRef"},"assetOut":{"$ref":"#/components/schemas/v1AssetRef"},"exp":{"format":"int64","title":"exp contains the expiration timestamp in Unix","type":"string"},"expirationDate":{"format":"date-time","title":"total_fee contains the fees substracted from the amounts\nexpiration_date contains the date when the quote will expire in RFC 3339 format","type":"string"},"externalId":{"title":"external_id is the identifier of the quote if the provider does not return\nthe quote values. Instead of that return an ID that have to be fetched by API","type":"string"},"id":{"title":"id is the quote identifier","type":"string"},"meta":{"additionalProperties":{"type":"string"},"title":"meta contains additional metadata attached to the quote","type":"object"},"penaltyFee":{"$ref":"#/components/schemas/v1AssetRef"},"price":{"title":"Price contains the final price shown to the user","type":"string"},"productFee":{"$ref":"#/components/schemas/v1AssetRef"},"providerFee":{"$ref":"#/components/schemas/v1AssetRef"},"targetId":{"title":"target_id is the target identifier when type is offramp/onramp the\ntarget_id is the UUID of the product_provider. Otherwise when\ntype is swap the target_id is the instrument UUID","type":"string"},"targetType":{"title":"target_type is the quote type (offramp | onramp | swap | trade)","type":"string"}},"required":["id","accountId","targetId","targetType","assetIn","assetOut","providerFee","productFee","price","expirationDate","exp","meta"],"title":"QuotePayload describe the quote payload","type":"object"},"v1AssetRef":{"properties":{"amount":{"title":"amount contains the amount of the asset","type":"string"},"code":{"title":"code contains the identifier of the asset","type":"string"},"productId":{"title":"product_id is the identifier of the product this asset resolved to, when known. Disambiguates\nbetween multiple products sharing the same code on one trade instrument (e.g. the same token\non different chains) - unset on quotes signed before this field existed","type":"string"},"type":{"title":"type contains the type of the asset (fiat | crypto)","type":"string"}},"required":["code","type","amount"],"title":"AssetRef contains the asset information","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/market/v1/products-providers/{id}/quote":{"get":{"description":"Quote-only. Use ProcessOnRamp separately to act on it. amount can be\ncrypto (atoms) or fiat (decimal) depending on the relation's direction","operationId":"MarketQueryService_GetProductProviderQuote","parameters":[{"description":"id is the id of the relation products providers","in":"path","name":"id","required":true,"schema":{"type":"string"}},{"description":"amount contains the amount to transfer (can be crypto in atoms or fiat in decimals)","in":"query","name":"amount","required":true,"schema":{"type":"string"}},{"description":"account_id is the ID of the account used to sign the quote","in":"query","name":"accountId","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/products_providersGetProductProviderQuoteResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"GetProductProviderQuote retrieves the quote for a product based on the provider, fiat and amount","tags":["MarketQueryService"]}}}}
```

## GetProduct retrieves a product by its ID

> Includes the product's chain/token, fee spec and AML check flag

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"description":"Queries (read operations)","name":"MarketQueryService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["market.products.read"]},{"BearerAuth":["market.products.read"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"productsGetProductResponse":{"properties":{"product":{"$ref":"#/components/schemas/productsProduct"}},"required":["product"],"title":"GetProductResponse is the response message for the GetProduct method","type":"object"},"productsProduct":{"properties":{"applyAmlCheck":{"title":"apply_aml_check indicates whether an AML check via Elliptic should be run before the ticket is accepted","type":"boolean"},"chainToken":{"$ref":"#/components/schemas/v1ChainToken"},"enabled":{"title":"enabled indicates whether the product is enabled","type":"boolean"},"feeSpec":{"$ref":"#/components/schemas/productsFeeSpec"},"fiatAsset":{"$ref":"#/components/schemas/v1FiatAsset"},"id":{"title":"id is the ID of the product","type":"string"},"name":{"title":"name is the name of the product","type":"string"},"type":{"title":"type contains the type of the product (crypto | fiat)","type":"string"}},"required":["id","name","enabled","feeSpec","applyAmlCheck","type"],"title":"Product represents a product in the market","type":"object"},"v1ChainToken":{"properties":{"chain":{"$ref":"#/components/schemas/v1Chain"},"chainTokenEnabled":{"title":"chain_token_enabled indicates whether the token is enabled for this specific chain","type":"boolean"},"contractAddress":{"title":"contract_address is the smart contract address of the token on the chain (null for native tokens)","type":"string"},"enabledDex":{"title":"enabled_dex indicates whether the token is enabled for DEX operations on this chain","type":"boolean"},"fireblocksDenom":{"title":"fireblocks_denom is the asset denomination Fireblocks uses for this chain-token (e.g.\n\"USDT_POLYGON\"), used to interact with Fireblocks custody instead of resolving it live from\nFireblocks' own API - null if this asset isn't Fireblocks-custodied","type":"string"},"id":{"format":"int32","title":"id is the surrogate identifier of the chain-token relation","type":"integer"},"native":{"title":"native indicates whether the token is native to the chain","type":"boolean"},"token":{"$ref":"#/components/schemas/v1Token"}},"required":["id","chain","token","native","chainTokenEnabled","enabledDex"],"title":"ChainToken represents a token enabled on a specific chain","type":"object"},"v1Chain":{"properties":{"chainId":{"title":"chain_id is the blockchain network identifier (e.g., \"1\" for Ethereum, \"137\" for Polygon)","type":"string"},"confirmationDepth":{"format":"int32","title":"confirmation_depth is the number of block confirmations required before processing","type":"integer"},"contracts":{"additionalProperties":{"$ref":"#/components/schemas/v1ContractEntry"},"title":"contracts maps contract name to its on-chain address and ABI version","type":"object"},"enabled":{"title":"enabled indicates whether the chain is enabled on the platform","type":"boolean"},"feeAddress":{"title":"fee_address is the address that receives the affiliate fee on this chain","type":"string"},"feeBps":{"format":"int32","title":"fee_bps is the affiliate fee in basis points charged on routes through this chain (e.g. 30 = 0.30%)","type":"integer"},"id":{"format":"int32","title":"id is the surrogate identifier of the chain","type":"integer"},"logo":{"title":"logo is the URL to the logo of the chain","type":"string"},"name":{"title":"name is the human-readable name of the chain","type":"string"},"testnet":{"title":"testnet indicates whether the chain is a testnet or mainnet","type":"boolean"},"type":{"title":"type is the type of the chain (e.g., \"evm\", \"cosmos\", \"solana\", \"bitcoin\", \"tron\")","type":"string"}},"required":["id","chainId","type","name","logo","testnet","enabled","confirmationDepth","contracts"],"title":"Chain represents a chain supported by the platform","type":"object"},"v1ContractEntry":{"properties":{"address":{"title":"address is the on-chain contract address","type":"string"},"version":{"title":"version is the optional version identifier","type":"string"}},"required":["address"],"title":"ContractEntry represents a single on-chain contract: its address and optional ABI version","type":"object"},"v1Token":{"properties":{"decimals":{"format":"int32","title":"decimals is the number of decimal places the token uses","type":"integer"},"enabled":{"title":"enabled indicates whether the token is enabled on the platform","type":"boolean"},"id":{"format":"int32","title":"id is the surrogate identifier of the token","type":"integer"},"logo":{"title":"logo is the URL to the token's logo image","type":"string"},"name":{"title":"name is the full name of the token","type":"string"},"stable":{"title":"stable indicates whether the token is a stablecoin","type":"boolean"},"symbol":{"title":"symbol is the ticker symbol of the token","type":"string"}},"required":["id","name","symbol","decimals","logo","enabled","stable"],"title":"Token represents a coin/token supported by the platform","type":"object"},"productsFeeSpec":{"properties":{"bpsValue":{"title":"bps_value is the basis points (0–10000); required for bps and max fee types","type":"string"},"flatValue":{"title":"flat_value is the fixed fee amount; required for flat and max fee types","type":"string"},"type":{"title":"type is the type of fee specification (flat, bps or max)","type":"string"}},"required":["type"],"title":"FeeSpec represents the fee specification for a product","type":"object"},"v1FiatAsset":{"properties":{"code":{"title":"code represents the fiat asset identifier using ISO 4217","type":"string"},"minorUnits":{"format":"int32","title":"minor_units is the number of decimal places this fiat currency's minor unit uses (e.g. 2 for\nBRL/MXN centavos) - the source of truth for converting between fiat minor units and face value","type":"integer"},"name":{"title":"name represents the fiat asset name","type":"string"},"symbol":{"title":"symbol represents the fiat asset symbol","type":"string"}},"required":["code","name","symbol","minorUnits"],"title":"FiatAsset contains the fiat asset data","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/market/v1/products/{productId}":{"get":{"description":"Includes the product's chain/token, fee spec and AML check flag","operationId":"MarketQueryService_GetProduct","parameters":[{"description":"product_id is the ID of the product to retrieve","in":"path","name":"productId","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/productsGetProductResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"GetProduct retrieves a product by its ID","tags":["MarketQueryService"]}}}}
```

## ListProviders returns all registered providers

> DB-registered providers only. Use ListRegistryProviders to see\
> providers implemented in code but not yet registered

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"description":"Queries (read operations)","name":"MarketQueryService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["market.providers.read"]},{"BearerAuth":["market.providers.read"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"providersListProvidersResponse":{"properties":{"providers":{"items":{"$ref":"#/components/schemas/providersProvider"},"title":"providers is a list of retrieved providers","type":"array"}},"required":["providers"],"title":"ListProvidersResponse is the response message for the ListProviders method","type":"object"},"providersProvider":{"properties":{"additionalTemplate":{"$ref":"#/components/schemas/typesV1Schema"},"autoConfirm":{"title":"auto_confirm indicates whether the provider's off-ramp tickets are automatically confirmed","type":"boolean"},"enabled":{"title":"enabled indicates whether the provider is enabled","type":"boolean"},"id":{"title":"id is the ID of the provider","type":"string"},"identifier":{"title":"identifier is the identifier of the provider","type":"string"},"isUserAllowed":{"title":"is_user_allowed indicates whether the user is allowed to use the provider","type":"boolean"},"kycStatus":{"description":"kyc_status is the current KYC verification status for the requesting user on this provider.","type":"string"},"name":{"title":"name is the name of the provider","type":"string"}},"required":["id","identifier","name","enabled","isUserAllowed","kycStatus","autoConfirm"],"title":"Provider defines the Provider","type":"object"},"typesV1Schema":{"properties":{"fields":{"items":{"$ref":"#/components/schemas/v1FieldSchema"},"title":"fields are the fields that the schema contains","type":"array"},"title":{"title":"title is the name of the schema","type":"string"}},"required":["title","fields"],"title":"Schema defines the Schema type used to returns schemas on Rails and providers","type":"object"},"v1FieldSchema":{"properties":{"name":{"title":"name is the name of the field required by the backend","type":"string"},"optional":{"title":"optional contains the flag that determines if the field is optional or not","type":"boolean"},"options":{"items":{"type":"string"},"title":"options contains the available options if type is an enum","type":"array"},"pattern":{"title":"pattern contains the regex expresion to evaluate the field","type":"string"},"type":{"title":"type contains the type of the field","type":"string"}},"required":["name","type","optional"],"title":"FieldSchema describe the field on the schema and its properties","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/market/v1/providers":{"get":{"description":"DB-registered providers only. Use ListRegistryProviders to see\nproviders implemented in code but not yet registered","operationId":"MarketQueryService_ListProviders","parameters":[{"description":"account_id is the ID of the account to verify if it's allowed to use the provider","in":"query","name":"accountId","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/providersListProvidersResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"ListProviders returns all registered providers","tags":["MarketQueryService"]}}}}
```

## GetProvider returns the provided information from the Id

> account\_id is used to resolve is\_user\_allowed and kyc\_status for that\
> specific account on this provider

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"description":"Queries (read operations)","name":"MarketQueryService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["market.providers.read"]},{"BearerAuth":["market.providers.read"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"providersGetProviderResponse":{"properties":{"provider":{"$ref":"#/components/schemas/providersProvider"}},"required":["provider"],"title":"GetProviderResponse is the response message for the GetProvider method","type":"object"},"providersProvider":{"properties":{"additionalTemplate":{"$ref":"#/components/schemas/typesV1Schema"},"autoConfirm":{"title":"auto_confirm indicates whether the provider's off-ramp tickets are automatically confirmed","type":"boolean"},"enabled":{"title":"enabled indicates whether the provider is enabled","type":"boolean"},"id":{"title":"id is the ID of the provider","type":"string"},"identifier":{"title":"identifier is the identifier of the provider","type":"string"},"isUserAllowed":{"title":"is_user_allowed indicates whether the user is allowed to use the provider","type":"boolean"},"kycStatus":{"description":"kyc_status is the current KYC verification status for the requesting user on this provider.","type":"string"},"name":{"title":"name is the name of the provider","type":"string"}},"required":["id","identifier","name","enabled","isUserAllowed","kycStatus","autoConfirm"],"title":"Provider defines the Provider","type":"object"},"typesV1Schema":{"properties":{"fields":{"items":{"$ref":"#/components/schemas/v1FieldSchema"},"title":"fields are the fields that the schema contains","type":"array"},"title":{"title":"title is the name of the schema","type":"string"}},"required":["title","fields"],"title":"Schema defines the Schema type used to returns schemas on Rails and providers","type":"object"},"v1FieldSchema":{"properties":{"name":{"title":"name is the name of the field required by the backend","type":"string"},"optional":{"title":"optional contains the flag that determines if the field is optional or not","type":"boolean"},"options":{"items":{"type":"string"},"title":"options contains the available options if type is an enum","type":"array"},"pattern":{"title":"pattern contains the regex expresion to evaluate the field","type":"string"},"type":{"title":"type contains the type of the field","type":"string"}},"required":["name","type","optional"],"title":"FieldSchema describe the field on the schema and its properties","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/market/v1/providers/{providerId}":{"get":{"description":"account_id is used to resolve is_user_allowed and kyc_status for that\nspecific account on this provider","operationId":"MarketQueryService_GetProvider","parameters":[{"description":"provider_id is the ID of the provider to retrieve","in":"path","name":"providerId","required":true,"schema":{"type":"string"}},{"description":"account_id is the ID of the account associated to the provider","in":"query","name":"accountId","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/providersGetProviderResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"GetProvider returns the provided information from the Id","tags":["MarketQueryService"]}}}}
```

## GetProviderKyc returns the KYC data for the user on the given provider

> Always fetches a fresh status from the provider and persists a history\
> record. It doesn't just read the last known status from the DB

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"description":"Mutations (write operations)","name":"MarketMsgService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["market.providers.read"]},{"BearerAuth":["market.providers.read"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"MarketMsgServiceGetProviderKycBody":{"title":"GetProviderKycRequest is the request message for the GetProviderKyc method","type":"object"},"providersGetProviderKycResponse":{"properties":{"basicCompanyDataUrl":{"description":"basic_company_data_url is the second URL for KYB (company) accounts only.\nPresent when the sub-account is a company; absent for individual KYC.","type":"string"},"history":{"items":{"$ref":"#/components/schemas/providersProviderKycEvent"},"title":"history contains the chronological list of KYC status changes for this account","type":"array"},"metadata":{"title":"metadata contains provider-specific KYC metadata","type":"object"},"nextUrl":{"description":"next_url is the redirect URL to continue the KYC process (when applicable).\nFor KYB (company) accounts this is the authorized representative URL.","type":"string"},"providerAccountId":{"title":"provider_account_id is the provider-side account identifier linked to this user","type":"string"},"reason":{"title":"reason contains the rejection reason when status is REJECTED","type":"string"},"status":{"description":"status is the current KYC status for the account on this provider.\nPossible values: \"pending\", \"processing\", \"verified\", \"rejected\".","type":"string"}},"required":["status","history"],"title":"GetProviderKycResponse is the response message for the GetProviderKyc method","type":"object"},"providersProviderKycEvent":{"properties":{"createdAt":{"format":"date-time","title":"created_at is when this event was recorded","type":"string"},"reason":{"title":"reason contains the rejection reason when status is REJECTED","type":"string"},"status":{"description":"status is the KYC status at the time this event was recorded.\nPossible values: \"pending\", \"processing\", \"verified\", \"rejected\".","type":"string"}},"required":["status","createdAt"],"title":"ProviderKycEvent represents a single KYC status change recorded in history","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/market/v1/providers/{providerId}/kyc/{accountId}":{"post":{"description":"Always fetches a fresh status from the provider and persists a history\nrecord. It doesn't just read the last known status from the DB","operationId":"MarketMsgService_GetProviderKyc","parameters":[{"description":"provider_id is the DB ID of the provider","in":"path","name":"providerId","required":true,"schema":{"type":"string"}},{"description":"account_id is the ID of the account to retrieve KYC data for","in":"path","name":"accountId","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarketMsgServiceGetProviderKycBody"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/providersGetProviderKycResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"GetProviderKyc returns the KYC data for the user on the given provider","tags":["MarketMsgService"]}}}}
```

## StartProviderKyc initiates the KYC process for the user on the given provider

> Creates the provider sub-account and returns the KYC redirect URL. Must\
> be called explicitly by the user. GetProviderKyc no longer auto-triggers\
> this

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"description":"Mutations (write operations)","name":"MarketMsgService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["market.providers.read"]},{"BearerAuth":["market.providers.read"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"MarketMsgServiceStartProviderKycBody":{"title":"StartProviderKycRequest is the request message for the StartProviderKyc method","type":"object"},"providersStartProviderKycResponse":{"properties":{"basicCompanyDataUrl":{"description":"basic_company_data_url is the second URL for KYB (company) accounts only.\nPresent when the sub-account is a company; absent for individual KYC.","type":"string"},"nextUrl":{"description":"next_url is the redirect URL the user must follow to complete the KYC process.\nFor KYB (company) accounts this is the authorized representative URL.","type":"string"},"status":{"description":"status is the current KYC status after initiating the flow.\nPossible values: \"pending\", \"processing\", \"verified\", \"rejected\".","type":"string"}},"required":["status"],"title":"StartProviderKycResponse is the response message for the StartProviderKyc method","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/market/v1/providers/{providerId}/kyc/{accountId}/start":{"post":{"description":"Creates the provider sub-account and returns the KYC redirect URL. Must\nbe called explicitly by the user. GetProviderKyc no longer auto-triggers\nthis","operationId":"MarketMsgService_StartProviderKyc","parameters":[{"description":"provider_id is the DB ID of the provider","in":"path","name":"providerId","required":true,"schema":{"type":"string"}},{"description":"account_id is the ID of the account to initiate KYC for","in":"path","name":"accountId","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarketMsgServiceStartProviderKycBody"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/providersStartProviderKycResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"StartProviderKyc initiates the KYC process for the user on the given provider","tags":["MarketMsgService"]}}}}
```

## ListTradeInstruments lists the trade instruments available to the account

> Each instrument carries its hydrated products so the caller can render the\
> pair picker that GetTradeInstrumentQuote expects

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"description":"Queries (read operations)","name":"TradeInstrumentsQueryService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["market.trade_instrument.read"]},{"BearerAuth":["market.trade_instrument.read"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"trade_instrumentsListTradeInstrumentsResponse":{"properties":{"tradeInstruments":{"items":{"$ref":"#/components/schemas/trade_instrumentsTradeInstrument"},"title":"trade_instruments contains the instruments with their products hydrated","type":"array"}},"title":"ListTradeInstrumentsResponse contains the trade instruments available to the account","type":"object"},"trade_instrumentsTradeInstrument":{"properties":{"createdAt":{"format":"date-time","title":"created_at contains the creation date of the instrument","type":"string"},"description":{"title":"description contains the description of the trade instrument","type":"string"},"enabled":{"title":"enabled reports whether the instrument can be quoted","type":"boolean"},"id":{"title":"id contains the identifier of the trade instrument","type":"string"},"name":{"title":"name contains the name of the trade instrument","type":"string"},"products":{"items":{"$ref":"#/components/schemas/trade_instrumentsTradeInstrumentProduct"},"title":"products contains the base and quote products of the instrument","type":"array"},"provider":{"$ref":"#/components/schemas/providersProvider"},"spread":{"$ref":"#/components/schemas/instrumentsSpread"},"updatedAt":{"format":"date-time","title":"updated_at contains the last update date of the instrument","type":"string"}},"title":"TradeInstrument is a tradable group of products quoted by a single provider","type":"object"},"trade_instrumentsTradeInstrumentProduct":{"properties":{"product":{"$ref":"#/components/schemas/productsProduct"},"role":{"title":"role is base or quote","type":"string"}},"title":"TradeInstrumentProduct is a product attached to an instrument, hydrated","type":"object"},"productsProduct":{"properties":{"applyAmlCheck":{"title":"apply_aml_check indicates whether an AML check via Elliptic should be run before the ticket is accepted","type":"boolean"},"chainToken":{"$ref":"#/components/schemas/v1ChainToken"},"enabled":{"title":"enabled indicates whether the product is enabled","type":"boolean"},"feeSpec":{"$ref":"#/components/schemas/productsFeeSpec"},"fiatAsset":{"$ref":"#/components/schemas/v1FiatAsset"},"id":{"title":"id is the ID of the product","type":"string"},"name":{"title":"name is the name of the product","type":"string"},"type":{"title":"type contains the type of the product (crypto | fiat)","type":"string"}},"required":["id","name","enabled","feeSpec","applyAmlCheck","type"],"title":"Product represents a product in the market","type":"object"},"v1ChainToken":{"properties":{"chain":{"$ref":"#/components/schemas/v1Chain"},"chainTokenEnabled":{"title":"chain_token_enabled indicates whether the token is enabled for this specific chain","type":"boolean"},"contractAddress":{"title":"contract_address is the smart contract address of the token on the chain (null for native tokens)","type":"string"},"enabledDex":{"title":"enabled_dex indicates whether the token is enabled for DEX operations on this chain","type":"boolean"},"fireblocksDenom":{"title":"fireblocks_denom is the asset denomination Fireblocks uses for this chain-token (e.g.\n\"USDT_POLYGON\"), used to interact with Fireblocks custody instead of resolving it live from\nFireblocks' own API - null if this asset isn't Fireblocks-custodied","type":"string"},"id":{"format":"int32","title":"id is the surrogate identifier of the chain-token relation","type":"integer"},"native":{"title":"native indicates whether the token is native to the chain","type":"boolean"},"token":{"$ref":"#/components/schemas/v1Token"}},"required":["id","chain","token","native","chainTokenEnabled","enabledDex"],"title":"ChainToken represents a token enabled on a specific chain","type":"object"},"v1Chain":{"properties":{"chainId":{"title":"chain_id is the blockchain network identifier (e.g., \"1\" for Ethereum, \"137\" for Polygon)","type":"string"},"confirmationDepth":{"format":"int32","title":"confirmation_depth is the number of block confirmations required before processing","type":"integer"},"contracts":{"additionalProperties":{"$ref":"#/components/schemas/v1ContractEntry"},"title":"contracts maps contract name to its on-chain address and ABI version","type":"object"},"enabled":{"title":"enabled indicates whether the chain is enabled on the platform","type":"boolean"},"feeAddress":{"title":"fee_address is the address that receives the affiliate fee on this chain","type":"string"},"feeBps":{"format":"int32","title":"fee_bps is the affiliate fee in basis points charged on routes through this chain (e.g. 30 = 0.30%)","type":"integer"},"id":{"format":"int32","title":"id is the surrogate identifier of the chain","type":"integer"},"logo":{"title":"logo is the URL to the logo of the chain","type":"string"},"name":{"title":"name is the human-readable name of the chain","type":"string"},"testnet":{"title":"testnet indicates whether the chain is a testnet or mainnet","type":"boolean"},"type":{"title":"type is the type of the chain (e.g., \"evm\", \"cosmos\", \"solana\", \"bitcoin\", \"tron\")","type":"string"}},"required":["id","chainId","type","name","logo","testnet","enabled","confirmationDepth","contracts"],"title":"Chain represents a chain supported by the platform","type":"object"},"v1ContractEntry":{"properties":{"address":{"title":"address is the on-chain contract address","type":"string"},"version":{"title":"version is the optional version identifier","type":"string"}},"required":["address"],"title":"ContractEntry represents a single on-chain contract: its address and optional ABI version","type":"object"},"v1Token":{"properties":{"decimals":{"format":"int32","title":"decimals is the number of decimal places the token uses","type":"integer"},"enabled":{"title":"enabled indicates whether the token is enabled on the platform","type":"boolean"},"id":{"format":"int32","title":"id is the surrogate identifier of the token","type":"integer"},"logo":{"title":"logo is the URL to the token's logo image","type":"string"},"name":{"title":"name is the full name of the token","type":"string"},"stable":{"title":"stable indicates whether the token is a stablecoin","type":"boolean"},"symbol":{"title":"symbol is the ticker symbol of the token","type":"string"}},"required":["id","name","symbol","decimals","logo","enabled","stable"],"title":"Token represents a coin/token supported by the platform","type":"object"},"productsFeeSpec":{"properties":{"bpsValue":{"title":"bps_value is the basis points (0–10000); required for bps and max fee types","type":"string"},"flatValue":{"title":"flat_value is the fixed fee amount; required for flat and max fee types","type":"string"},"type":{"title":"type is the type of fee specification (flat, bps or max)","type":"string"}},"required":["type"],"title":"FeeSpec represents the fee specification for a product","type":"object"},"v1FiatAsset":{"properties":{"code":{"title":"code represents the fiat asset identifier using ISO 4217","type":"string"},"minorUnits":{"format":"int32","title":"minor_units is the number of decimal places this fiat currency's minor unit uses (e.g. 2 for\nBRL/MXN centavos) - the source of truth for converting between fiat minor units and face value","type":"integer"},"name":{"title":"name represents the fiat asset name","type":"string"},"symbol":{"title":"symbol represents the fiat asset symbol","type":"string"}},"required":["code","name","symbol","minorUnits"],"title":"FiatAsset contains the fiat asset data","type":"object"},"providersProvider":{"properties":{"additionalTemplate":{"$ref":"#/components/schemas/typesV1Schema"},"autoConfirm":{"title":"auto_confirm indicates whether the provider's off-ramp tickets are automatically confirmed","type":"boolean"},"enabled":{"title":"enabled indicates whether the provider is enabled","type":"boolean"},"id":{"title":"id is the ID of the provider","type":"string"},"identifier":{"title":"identifier is the identifier of the provider","type":"string"},"isUserAllowed":{"title":"is_user_allowed indicates whether the user is allowed to use the provider","type":"boolean"},"kycStatus":{"description":"kyc_status is the current KYC verification status for the requesting user on this provider.","type":"string"},"name":{"title":"name is the name of the provider","type":"string"}},"required":["id","identifier","name","enabled","isUserAllowed","kycStatus","autoConfirm"],"title":"Provider defines the Provider","type":"object"},"typesV1Schema":{"properties":{"fields":{"items":{"$ref":"#/components/schemas/v1FieldSchema"},"title":"fields are the fields that the schema contains","type":"array"},"title":{"title":"title is the name of the schema","type":"string"}},"required":["title","fields"],"title":"Schema defines the Schema type used to returns schemas on Rails and providers","type":"object"},"v1FieldSchema":{"properties":{"name":{"title":"name is the name of the field required by the backend","type":"string"},"optional":{"title":"optional contains the flag that determines if the field is optional or not","type":"boolean"},"options":{"items":{"type":"string"},"title":"options contains the available options if type is an enum","type":"array"},"pattern":{"title":"pattern contains the regex expresion to evaluate the field","type":"string"},"type":{"title":"type contains the type of the field","type":"string"}},"required":["name","type","optional"],"title":"FieldSchema describe the field on the schema and its properties","type":"object"},"instrumentsSpread":{"properties":{"bps":{"$ref":"#/components/schemas/instrumentsBpsSpread"}},"title":"Spread represents the Spread for an instrument","type":"object"},"instrumentsBpsSpread":{"properties":{"askBps":{"format":"int64","title":"ask_bps is the ask bps spread","type":"string"},"bidBps":{"format":"int64","title":"bid_bps is the bid bps spread","type":"string"}},"required":["bidBps","askBps"],"title":"BpsSpread represents a bps spread for an instrument","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/market/v1/trade-instruments":{"get":{"description":"Each instrument carries its hydrated products so the caller can render the\npair picker that GetTradeInstrumentQuote expects","operationId":"TradeInstrumentsQueryService_ListTradeInstruments","parameters":[{"description":"account_id is the identifier of the account listing the instruments","in":"query","name":"accountId","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/trade_instrumentsListTradeInstrumentsResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"ListTradeInstruments lists the trade instruments available to the account","tags":["TradeInstrumentsQueryService"]}}}}
```

## GetTradeInstrumentQuote returns a quote for a pair inside a trade instrument

> Both legs are named explicitly. Exactly one of them must be the instrument's\
> quote product, which is what determines the side of the trade

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"description":"Queries (read operations)","name":"TradeInstrumentsQueryService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["market.trade_instrument.read"]},{"BearerAuth":["market.trade_instrument.read"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"trade_instrumentsGetTradeInstrumentQuoteResponse":{"properties":{"quote":{"$ref":"#/components/schemas/v1Quote"}},"title":"GetTradeInstrumentQuoteResponse contains the signed quote for the pair","type":"object"},"v1Quote":{"properties":{"quotePayload":{"$ref":"#/components/schemas/v1QuotePayload"},"signature":{"title":"signature contains the signature of the quote","type":"string"}},"required":["quotePayload","signature"],"title":"Quote contains the quote information","type":"object"},"v1QuotePayload":{"properties":{"accountId":{"title":"account_id is the account identifier","type":"string"},"assetIn":{"$ref":"#/components/schemas/v1AssetRef"},"assetOut":{"$ref":"#/components/schemas/v1AssetRef"},"exp":{"format":"int64","title":"exp contains the expiration timestamp in Unix","type":"string"},"expirationDate":{"format":"date-time","title":"total_fee contains the fees substracted from the amounts\nexpiration_date contains the date when the quote will expire in RFC 3339 format","type":"string"},"externalId":{"title":"external_id is the identifier of the quote if the provider does not return\nthe quote values. Instead of that return an ID that have to be fetched by API","type":"string"},"id":{"title":"id is the quote identifier","type":"string"},"meta":{"additionalProperties":{"type":"string"},"title":"meta contains additional metadata attached to the quote","type":"object"},"penaltyFee":{"$ref":"#/components/schemas/v1AssetRef"},"price":{"title":"Price contains the final price shown to the user","type":"string"},"productFee":{"$ref":"#/components/schemas/v1AssetRef"},"providerFee":{"$ref":"#/components/schemas/v1AssetRef"},"targetId":{"title":"target_id is the target identifier when type is offramp/onramp the\ntarget_id is the UUID of the product_provider. Otherwise when\ntype is swap the target_id is the instrument UUID","type":"string"},"targetType":{"title":"target_type is the quote type (offramp | onramp | swap | trade)","type":"string"}},"required":["id","accountId","targetId","targetType","assetIn","assetOut","providerFee","productFee","price","expirationDate","exp","meta"],"title":"QuotePayload describe the quote payload","type":"object"},"v1AssetRef":{"properties":{"amount":{"title":"amount contains the amount of the asset","type":"string"},"code":{"title":"code contains the identifier of the asset","type":"string"},"productId":{"title":"product_id is the identifier of the product this asset resolved to, when known. Disambiguates\nbetween multiple products sharing the same code on one trade instrument (e.g. the same token\non different chains) - unset on quotes signed before this field existed","type":"string"},"type":{"title":"type contains the type of the asset (fiat | crypto)","type":"string"}},"required":["code","type","amount"],"title":"AssetRef contains the asset information","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/market/v1/trade-instruments/{id}/quote":{"get":{"description":"Both legs are named explicitly. Exactly one of them must be the instrument's\nquote product, which is what determines the side of the trade","operationId":"TradeInstrumentsQueryService_GetTradeInstrumentQuote","parameters":[{"description":"id contains the identifier of the trade instrument","in":"path","name":"id","required":true,"schema":{"type":"string"}},{"description":"account_id is the identifier of the account requesting the quote","in":"query","name":"accountId","required":true,"schema":{"type":"string"}},{"description":"product_in_id is the product the user gives up","in":"query","name":"productInId","required":true,"schema":{"type":"string"}},{"description":"product_out_id is the product the user receives","in":"query","name":"productOutId","required":true,"schema":{"type":"string"}},{"description":"amount contains the amount of product_in in atoms","in":"query","name":"amount","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/trade_instrumentsGetTradeInstrumentQuoteResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"GetTradeInstrumentQuote returns a quote for a pair inside a trade instrument","tags":["TradeInstrumentsQueryService"]}}}}
```

## CreateYieldDeposit creates a deposit intent for a yield vault

> Returns the ERC-20 transfer the frontend signs and broadcasts from the user's\
> connected wallet, which then reports the hash back through ReportYieldDepositTx\
> The transaction's from is left empty, only the frontend knows the signing wallet

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"description":"Mutations (write operations)","name":"MarketMsgService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["market.yields.write"]},{"BearerAuth":["market.yields.write"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"yieldsCreateYieldDepositRequest":{"properties":{"accountId":{"title":"account_id is the depositing account","type":"string"},"amount":{"title":"amount is the exact deposit amount in token units","type":"string"},"chain":{"title":"chain is the provider network key the transfer happens on, e.g. ethereum, base,\narbitrum, polygon, ethereum_sepolia","type":"string"},"userAddress":{"description":"Required whenever the chain charges a deposit fee: the fee is collected through\nKiiRouter, which binds the request to one signer and refuses any other sender. A\nchain with no fee configured builds a plain transfer and ignores this field","title":"user_address is the wallet the transfer is signed from","type":"string"},"vaultId":{"title":"vault_id is the vault to deposit into","type":"string"}},"required":["accountId","vaultId","amount","chain"],"title":"CreateYieldDepositRequest is the request message for the CreateYieldDeposit method","type":"object"},"yieldsCreateYieldDepositResponse":{"properties":{"amount":{"title":"amount is the exact amount the frontend must send","type":"string"},"chain":{"title":"chain is the provider network key of the transfer, e.g. ethereum, base, arbitrum,\npolygon, ethereum_sepolia","type":"string"},"depositAddress":{"title":"deposit_address is where the transfer must be sent","type":"string"},"depositId":{"title":"deposit_id is our deposit intent id","type":"string"},"fee":{"$ref":"#/components/schemas/yieldsYieldFee"},"netAmount":{"title":"net_amount is what reaches the vault: amount minus the fee. It is the amount the\nposition and the deposit history are recorded against","type":"string"},"status":{"title":"status is the deposit status: pending, sent, processing, completed, failed, expired","type":"string"},"tokenContract":{"title":"token_contract is the ERC-20 contract the transfer is called on","type":"string"},"transactions":{"items":{"$ref":"#/components/schemas/blockchainV1Transaction"},"title":"transactions is the transfer the frontend signs and broadcasts, from is left empty","type":"array"},"walletStatus":{"title":"wallet_status is the provisioning state of the account's yield wallet: creating, idle,\nfailed. Only idle carries a deposit, every other value leaves every other field on this\nmessage empty (fee included, which arrives null) and means the caller should retry once\nthe wallet settles","type":"string"}},"required":["depositId","status","depositAddress","tokenContract","chain","amount","transactions","walletStatus","fee","netAmount"],"title":"CreateYieldDepositResponse is the response message for the CreateYieldDeposit method","type":"object"},"yieldsYieldFee":{"properties":{"amount":{"title":"amount is the charged fee in token units, \"0\" when the chain charges nothing","type":"string"},"asset":{"title":"asset is the token the fee is taken in, always the vault deposit token","type":"string"},"type":{"title":"type is how the fee was computed: flat, bps or max, empty when the chain charges nothing","type":"string"}},"required":["type","amount","asset"],"title":"YieldFee is what Kii charges on a yields operation, deducted from the amount the user\ncommits. type is flat, bps or max, amount is in token units and asset is the token symbol","type":"object"},"blockchainV1Transaction":{"properties":{"evm":{"$ref":"#/components/schemas/v1EVMTransaction"}},"title":"Transaction wraps the transactions to build an ordered list","type":"object"},"v1EVMTransaction":{"properties":{"chainId":{"title":"chain_id is the ID of the network","type":"string"},"data":{"title":"data is the hex raw call data to be sent on the transaction","type":"string"},"from":{"title":"from is the address from which the transaction should be sent","type":"string"},"metadata":{"additionalProperties":{"type":"string"},"title":"metadata is the map of additional information to be sent with the transaction","type":"object"},"to":{"title":"to is the address to which the transaction should be sent","type":"string"},"type":{"title":"type is the type of the tx -- kiirouter, approval, etc","type":"string"},"value":{"title":"value is the amount of native token to be sent with the transaction","type":"string"}},"required":["type","chainId","from","to","value","data"],"title":"EVMTransaction represents an EVM transaction to be sent to the blockchain","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/market/v1/yields/deposits":{"post":{"description":"Returns the ERC-20 transfer the frontend signs and broadcasts from the user's\nconnected wallet, which then reports the hash back through ReportYieldDepositTx\nThe transaction's from is left empty, only the frontend knows the signing wallet","operationId":"MarketMsgService_CreateYieldDeposit","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/yieldsCreateYieldDepositRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/yieldsCreateYieldDepositResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"CreateYieldDeposit creates a deposit intent for a yield vault","tags":["MarketMsgService"]}}}}
```

## ListYieldDeposits lists the account's deposit history

> Includes in-flight intents, used by the frontend to poll deposit status

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"description":"Queries (read operations)","name":"MarketQueryService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["market.yields.read"]},{"BearerAuth":["market.yields.read"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"yieldsListYieldDepositsResponse":{"properties":{"deposits":{"items":{"$ref":"#/components/schemas/yieldsYieldDeposit"},"title":"deposits are the account's deposit records, newest first","type":"array"}},"title":"ListYieldDepositsResponse is the response message for the ListYieldDeposits method","type":"object"},"yieldsYieldDeposit":{"properties":{"amount":{"title":"amount is the deposit amount in token units","type":"string"},"chain":{"title":"chain is the provider network key of the transfer, e.g. ethereum, base, arbitrum,\npolygon, ethereum_sepolia","type":"string"},"createdAt":{"title":"created_at is the intent creation time in RFC 3339","type":"string"},"id":{"title":"id is our deposit intent id","type":"string"},"source":{"title":"source is user or unsolicited","type":"string"},"status":{"title":"status is pending, sent, processing, completed, failed or expired","type":"string"},"token":{"title":"token is the deposited token symbol","type":"string"},"txHash":{"title":"tx_hash is the on-chain transfer hash once known","type":"string"},"vaultId":{"title":"vault_id is the vault deposited into","type":"string"}},"required":["id","vaultId","source","chain","token","amount","status","createdAt"],"title":"YieldDeposit is a deposit intent record","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/market/v1/yields/deposits/{accountId}":{"get":{"description":"Includes in-flight intents, used by the frontend to poll deposit status","operationId":"MarketQueryService_ListYieldDeposits","parameters":[{"description":"account_id is the account to list deposits for","in":"path","name":"accountId","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/yieldsListYieldDepositsResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"ListYieldDeposits lists the account's deposit history","tags":["MarketQueryService"]}}}}
```

## ReportYieldDepositTx attaches the frontend-signed transaction hash to a deposit

> Called after the user's connected wallet broadcasts the transfer, moving the\
> deposit intent from pending to sent

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"description":"Mutations (write operations)","name":"MarketMsgService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["market.yields.write"]},{"BearerAuth":["market.yields.write"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"MarketMsgServiceReportYieldDepositTxBody":{"properties":{"accountId":{"title":"account_id is the owning account","type":"string"},"txHash":{"title":"tx_hash is the broadcast transaction hash","type":"string"}},"required":["accountId","txHash"],"title":"ReportYieldDepositTxRequest is the request message for the ReportYieldDepositTx method","type":"object"},"yieldsReportYieldDepositTxResponse":{"title":"ReportYieldDepositTxResponse is the response message for the ReportYieldDepositTx method","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/market/v1/yields/deposits/{depositId}/tx":{"post":{"description":"Called after the user's connected wallet broadcasts the transfer, moving the\ndeposit intent from pending to sent","operationId":"MarketMsgService_ReportYieldDepositTx","parameters":[{"description":"deposit_id is the deposit intent the transaction belongs to","in":"path","name":"depositId","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarketMsgServiceReportYieldDepositTxBody"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/yieldsReportYieldDepositTxResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"ReportYieldDepositTx attaches the frontend-signed transaction hash to a deposit","tags":["MarketMsgService"]}}}}
```

## GetYieldPortfolio returns the account's position in each vault

> Balances, earned yield and withdrawable amounts are read through from the\
> yields provider per active wallet

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"description":"Queries (read operations)","name":"MarketQueryService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["market.yields.read"]},{"BearerAuth":["market.yields.read"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"yieldsGetYieldPortfolioResponse":{"properties":{"entries":{"items":{"$ref":"#/components/schemas/yieldsYieldPortfolioEntry"},"title":"entries are the account's vault positions","type":"array"}},"title":"GetYieldPortfolioResponse is the response message for the GetYieldPortfolio method","type":"object"},"yieldsYieldPortfolioEntry":{"properties":{"cashUsd":{"title":"cash_usd is idle undeployed cash, non-zero when a deposit was below the\nprovider deployment minimum","type":"string"},"earnedUsd":{"title":"earned_usd is the yield earned in USD","type":"string"},"reservedUsd":{"title":"reserved_usd is the part of the balance the provider is holding and will not pay out\nyet, typically funds moving through a rebalance or an in-flight withdrawal. A\nwithdrawal larger than total_usd minus reserved_usd is rejected","type":"string"},"totalUsd":{"title":"total_usd is the current position value in USD","type":"string"},"vault":{"$ref":"#/components/schemas/yieldsYieldVault"},"withdrawableUsd":{"title":"withdrawable_usd is the amount currently withdrawable in USD","type":"string"}},"required":["vault","totalUsd","earnedUsd","withdrawableUsd"],"title":"YieldPortfolioEntry is the account's position in one vault","type":"object"},"yieldsYieldVault":{"properties":{"addresses":{"items":{"$ref":"#/components/schemas/yieldsYieldVaultAddress"},"title":"addresses are the vault's published on-chain addresses","type":"array"},"allocations":{"items":{"$ref":"#/components/schemas/yieldsYieldVaultAllocation"},"title":"allocations break down what the vault currently holds","type":"array"},"apyBps":{"format":"int64","title":"apy_bps is the current APY in basis points","type":"string"},"chain":{"title":"chain is the provider network key the vault runs on, e.g. ethereum, base, arbitrum,\npolygon, ethereum_sepolia","type":"string"},"depositToken":{"title":"deposit_token is the token the vault accepts (e.g. USDC)","type":"string"},"description":{"title":"description is the long-form vault explanation","type":"string"},"id":{"title":"id is our vault id","type":"string"},"links":{"items":{"$ref":"#/components/schemas/yieldsYieldVaultLink"},"title":"links are external references for the vault","type":"array"},"maxAllocationUsd":{"title":"max_allocation_usd is the cap on what the vault will accept, in USD","type":"string"},"name":{"title":"name is the vault display name","type":"string"},"navUpdateMode":{"title":"nav_update_mode is how the vault values its position: continuous or discrete","type":"string"},"protocol":{"title":"protocol is the underlying protocol the vault routes into, e.g. centrifuge, maple","type":"string"},"status":{"title":"status is which operations the vault currently accepts: active (both), buy_only\n(deposits only), sell_only (withdrawals only), frozen (neither), inactive (delisted by\nthe provider, withdrawals still allowed). Delisted vaults are not returned by\nListYieldVaults but can still appear on a portfolio entry","type":"string"},"tvlUsd":{"title":"tvl_usd is the vault TVL in USD","type":"string"},"utilizationPct":{"title":"utilization_pct is how much of the vault's capacity is deployed, as a percentage","type":"string"},"withdrawPolicy":{"title":"withdraw_policy is the provider processing policy JSON driving delay warnings","type":"string"}},"required":["id","name","chain","depositToken","apyBps","status"],"title":"YieldVault is a catalog entry for a vault users can deposit into","type":"object"},"yieldsYieldVaultAddress":{"properties":{"label":{"title":"label is the address role, e.g. Vault or Asset token","type":"string"},"value":{"title":"value is the address itself, or the token symbol for a non-address entry","type":"string"}},"required":["label","value"],"title":"YieldVaultAddress is a labeled on-chain address the provider publishes for a vault","type":"object"},"yieldsYieldVaultAllocation":{"properties":{"address":{"title":"address is the leg's on-chain address when it has one","type":"string"},"description":{"title":"description is the long-form explanation of the leg","type":"string"},"label":{"title":"label describes the holding","type":"string"},"pct":{"title":"pct is the leg's percentage share of the vault","type":"string"},"type":{"title":"type is the provider's asset class for the leg, e.g. rwa, credit","type":"string"},"valueUsd":{"title":"value_usd is the leg value in USD","type":"string"}},"required":["label"],"title":"YieldVaultAllocation is one leg of what a vault holds","type":"object"},"yieldsYieldVaultLink":{"properties":{"label":{"title":"label is the link display text","type":"string"},"url":{"title":"url is the link target","type":"string"}},"required":["label","url"],"title":"YieldVaultLink is a labeled external link for a vault, e.g. the protocol's own page","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/market/v1/yields/portfolio/{accountId}":{"get":{"description":"Balances, earned yield and withdrawable amounts are read through from the\nyields provider per active wallet","operationId":"MarketQueryService_GetYieldPortfolio","parameters":[{"description":"account_id is the account to fetch the portfolio for","in":"path","name":"accountId","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/yieldsGetYieldPortfolioResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"GetYieldPortfolio returns the account's position in each vault","tags":["MarketQueryService"]}}}}
```

## ListYieldVaults lists the active yield vault catalog

> Returns the vault catalog with APY, TVL and withdrawal policy metadata, enriched\
> with the provider's presentation data (description, protocol, allocations, links)\
> needed to render a vault page. The provider catalog is cached, so a call costs a\
> provider fetch at most once every 15 minutes

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"description":"Queries (read operations)","name":"MarketQueryService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["market.yields.read"]},{"BearerAuth":["market.yields.read"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"yieldsListYieldVaultsResponse":{"properties":{"vaults":{"items":{"$ref":"#/components/schemas/yieldsYieldVault"},"title":"vaults are the active catalog entries","type":"array"}},"title":"ListYieldVaultsResponse is the response message for the ListYieldVaults method","type":"object"},"yieldsYieldVault":{"properties":{"addresses":{"items":{"$ref":"#/components/schemas/yieldsYieldVaultAddress"},"title":"addresses are the vault's published on-chain addresses","type":"array"},"allocations":{"items":{"$ref":"#/components/schemas/yieldsYieldVaultAllocation"},"title":"allocations break down what the vault currently holds","type":"array"},"apyBps":{"format":"int64","title":"apy_bps is the current APY in basis points","type":"string"},"chain":{"title":"chain is the provider network key the vault runs on, e.g. ethereum, base, arbitrum,\npolygon, ethereum_sepolia","type":"string"},"depositToken":{"title":"deposit_token is the token the vault accepts (e.g. USDC)","type":"string"},"description":{"title":"description is the long-form vault explanation","type":"string"},"id":{"title":"id is our vault id","type":"string"},"links":{"items":{"$ref":"#/components/schemas/yieldsYieldVaultLink"},"title":"links are external references for the vault","type":"array"},"maxAllocationUsd":{"title":"max_allocation_usd is the cap on what the vault will accept, in USD","type":"string"},"name":{"title":"name is the vault display name","type":"string"},"navUpdateMode":{"title":"nav_update_mode is how the vault values its position: continuous or discrete","type":"string"},"protocol":{"title":"protocol is the underlying protocol the vault routes into, e.g. centrifuge, maple","type":"string"},"status":{"title":"status is which operations the vault currently accepts: active (both), buy_only\n(deposits only), sell_only (withdrawals only), frozen (neither), inactive (delisted by\nthe provider, withdrawals still allowed). Delisted vaults are not returned by\nListYieldVaults but can still appear on a portfolio entry","type":"string"},"tvlUsd":{"title":"tvl_usd is the vault TVL in USD","type":"string"},"utilizationPct":{"title":"utilization_pct is how much of the vault's capacity is deployed, as a percentage","type":"string"},"withdrawPolicy":{"title":"withdraw_policy is the provider processing policy JSON driving delay warnings","type":"string"}},"required":["id","name","chain","depositToken","apyBps","status"],"title":"YieldVault is a catalog entry for a vault users can deposit into","type":"object"},"yieldsYieldVaultAddress":{"properties":{"label":{"title":"label is the address role, e.g. Vault or Asset token","type":"string"},"value":{"title":"value is the address itself, or the token symbol for a non-address entry","type":"string"}},"required":["label","value"],"title":"YieldVaultAddress is a labeled on-chain address the provider publishes for a vault","type":"object"},"yieldsYieldVaultAllocation":{"properties":{"address":{"title":"address is the leg's on-chain address when it has one","type":"string"},"description":{"title":"description is the long-form explanation of the leg","type":"string"},"label":{"title":"label describes the holding","type":"string"},"pct":{"title":"pct is the leg's percentage share of the vault","type":"string"},"type":{"title":"type is the provider's asset class for the leg, e.g. rwa, credit","type":"string"},"valueUsd":{"title":"value_usd is the leg value in USD","type":"string"}},"required":["label"],"title":"YieldVaultAllocation is one leg of what a vault holds","type":"object"},"yieldsYieldVaultLink":{"properties":{"label":{"title":"label is the link display text","type":"string"},"url":{"title":"url is the link target","type":"string"}},"required":["label","url"],"title":"YieldVaultLink is a labeled external link for a vault, e.g. the protocol's own page","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/market/v1/yields/vaults":{"get":{"description":"Returns the vault catalog with APY, TVL and withdrawal policy metadata, enriched\nwith the provider's presentation data (description, protocol, allocations, links)\nneeded to render a vault page. The provider catalog is cached, so a call costs a\nprovider fetch at most once every 15 minutes","operationId":"MarketQueryService_ListYieldVaults","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/yieldsListYieldVaultsResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"ListYieldVaults lists the active yield vault catalog","tags":["MarketQueryService"]}}}}
```

## PreviewYieldDeposit previews the fee split of a deposit before creating it

> Returns what Kii charges on the chain and what would reach the vault, without\
> touching the account's yield wallet or recording an intent. Nothing is created,\
> so it is safe to call while the user is still typing an amount

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"description":"Queries (read operations)","name":"MarketQueryService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["market.yields.read"]},{"BearerAuth":["market.yields.read"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"yieldsPreviewYieldDepositResponse":{"properties":{"amount":{"title":"amount is the requested amount, what the user's wallet would be debited","type":"string"},"chain":{"title":"chain is the provider network key the preview was computed for","type":"string"},"fee":{"$ref":"#/components/schemas/yieldsYieldFee"},"netAmount":{"title":"net_amount is what would reach the vault: amount minus the fee","type":"string"},"token":{"title":"token is the vault deposit token symbol","type":"string"},"tokenContract":{"title":"token_contract is the ERC-20 contract the transfer would be called on, for the\nfrontend to check the user's balance before committing","type":"string"}},"required":["chain","token","tokenContract","amount","netAmount","fee"],"title":"PreviewYieldDepositResponse is the response message for the PreviewYieldDeposit method","type":"object"},"yieldsYieldFee":{"properties":{"amount":{"title":"amount is the charged fee in token units, \"0\" when the chain charges nothing","type":"string"},"asset":{"title":"asset is the token the fee is taken in, always the vault deposit token","type":"string"},"type":{"title":"type is how the fee was computed: flat, bps or max, empty when the chain charges nothing","type":"string"}},"required":["type","amount","asset"],"title":"YieldFee is what Kii charges on a yields operation, deducted from the amount the user\ncommits. type is flat, bps or max, amount is in token units and asset is the token symbol","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/market/v1/yields/vaults/{vaultId}/deposit-preview":{"get":{"description":"Returns what Kii charges on the chain and what would reach the vault, without\ntouching the account's yield wallet or recording an intent. Nothing is created,\nso it is safe to call while the user is still typing an amount","operationId":"MarketQueryService_PreviewYieldDeposit","parameters":[{"description":"vault_id is the vault the deposit would go to","in":"path","name":"vaultId","required":true,"schema":{"type":"string"}},{"description":"chain is the provider network key the transfer would happen on, e.g. ethereum, base,\narbitrum, polygon, ethereum_sepolia","in":"query","name":"chain","required":true,"schema":{"type":"string"}},{"description":"amount is the deposit amount in token units, the same value CreateYieldDeposit takes","in":"query","name":"amount","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/yieldsPreviewYieldDepositResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"PreviewYieldDeposit previews the fee split of a deposit before creating it","tags":["MarketQueryService"]}}}}
```

## PreviewYieldWithdrawal previews a withdrawal before creating it

> Returns the destination-specific withdrawable amount and the estimated\
> processing delay used for the frontend warning

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"description":"Queries (read operations)","name":"MarketQueryService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["market.yields.read"]},{"BearerAuth":["market.yields.read"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"yieldsPreviewYieldWithdrawalResponse":{"properties":{"estimatedDelay":{"title":"estimated_delay is the ISO-8601 processing delay estimate","type":"string"},"feeUsd":{"title":"fee_usd is the provider fee estimate","type":"string"},"withdrawableUsd":{"title":"withdrawable_usd is the destination-specific withdrawable amount, and the ceiling any\nwithdrawal to this destination must stay under","type":"string"}},"required":["withdrawableUsd","estimatedDelay","feeUsd"],"title":"PreviewYieldWithdrawalResponse is the response message for the PreviewYieldWithdrawal method","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/market/v1/yields/vaults/{vaultId}/withdrawal-preview":{"get":{"description":"Returns the destination-specific withdrawable amount and the estimated\nprocessing delay used for the frontend warning","operationId":"MarketQueryService_PreviewYieldWithdrawal","parameters":[{"description":"vault_id is the vault to withdraw from","in":"path","name":"vaultId","required":true,"schema":{"type":"string"}},{"description":"account_id is the withdrawing account","in":"query","name":"accountId","required":true,"schema":{"type":"string"}},{"description":"amount_usd is the amount to withdraw in USD units\n\nOmit it to ask what the maximum withdrawable amount is for this destination instead of\ntesting a specific amount. That is the number to drive a Max button, the wallet balance\nis not: it counts funds the provider currently reserves","in":"query","name":"amountUsd","required":false,"schema":{"type":"string"}},{"description":"destination_chain is the provider network key of the payout, e.g. ethereum, base,\narbitrum, polygon, ethereum_sepolia","in":"query","name":"destinationChain","required":true,"schema":{"type":"string"}},{"description":"destination_address is the payout address","in":"query","name":"destinationAddress","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/yieldsPreviewYieldWithdrawalResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"PreviewYieldWithdrawal previews a withdrawal before creating it","tags":["MarketQueryService"]}}}}
```

## CreateYieldWithdrawal initiates a withdrawal from a yield vault

> Withdrawals are asynchronous and can take from minutes to banking days\
> depending on the vault, use PreviewYieldWithdrawal for the delay estimate

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"description":"Mutations (write operations)","name":"MarketMsgService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["market.yields.write"]},{"BearerAuth":["market.yields.write"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"yieldsCreateYieldWithdrawalRequest":{"properties":{"accountId":{"title":"account_id is the withdrawing account","type":"string"},"amountUsd":{"title":"amount_usd is the amount to withdraw in USD units","type":"string"},"destinationAddress":{"title":"destination_address is the payout address","type":"string"},"destinationChain":{"title":"destination_chain is the provider network key of the payout, e.g. ethereum, base,\narbitrum, polygon, ethereum_sepolia","type":"string"},"vaultId":{"title":"vault_id is the vault to withdraw from","type":"string"}},"required":["accountId","vaultId","amountUsd","destinationChain","destinationAddress"],"title":"CreateYieldWithdrawalRequest is the request message for the CreateYieldWithdrawal method","type":"object"},"yieldsCreateYieldWithdrawalResponse":{"properties":{"status":{"title":"status is the withdrawal status: processing, awaiting_approval, completed,\npartially_completed, failed, cancelled","type":"string"},"withdrawalId":{"title":"withdrawal_id is our withdrawal record id","type":"string"}},"required":["withdrawalId","status"],"title":"CreateYieldWithdrawalResponse is the response message for the CreateYieldWithdrawal method","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/market/v1/yields/withdrawals":{"post":{"description":"Withdrawals are asynchronous and can take from minutes to banking days\ndepending on the vault, use PreviewYieldWithdrawal for the delay estimate","operationId":"MarketMsgService_CreateYieldWithdrawal","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/yieldsCreateYieldWithdrawalRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/yieldsCreateYieldWithdrawalResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"CreateYieldWithdrawal initiates a withdrawal from a yield vault","tags":["MarketMsgService"]}}}}
```

## ListYieldWithdrawals lists the account's withdrawal history

> Includes in-flight withdrawals, used by the frontend to poll withdrawal status

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"description":"Queries (read operations)","name":"MarketQueryService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["market.yields.read"]},{"BearerAuth":["market.yields.read"]}],"components":{"securitySchemes":{"ApiKeyAuth":{"description":"Send 'Authorization: APIKey <api-key>' to authenticate with a API key.","in":"header","name":"Authorization","type":"apiKey"},"BearerAuth":{"flows":{"password":{"scopes":{},"tokenUrl":"https://backend.pay.kiichain.io/users/v1/auth/login"}},"type":"oauth2"}},"schemas":{"yieldsListYieldWithdrawalsResponse":{"properties":{"withdrawals":{"items":{"$ref":"#/components/schemas/yieldsYieldWithdrawal"},"title":"withdrawals are the account's withdrawal records, newest first","type":"array"}},"title":"ListYieldWithdrawalsResponse is the response message for the ListYieldWithdrawals method","type":"object"},"yieldsYieldWithdrawal":{"properties":{"amountUsd":{"title":"amount_usd is the requested amount in USD units","type":"string"},"createdAt":{"title":"created_at is the record creation time in RFC 3339","type":"string"},"destinationAddress":{"title":"destination_address is the payout address","type":"string"},"destinationChain":{"title":"destination_chain is the provider network key of the payout, e.g. ethereum, base,\narbitrum, polygon, ethereum_sepolia","type":"string"},"id":{"title":"id is our withdrawal record id","type":"string"},"legs":{"title":"legs is the provider per-leg payout detail JSON","type":"string"},"status":{"title":"status is processing, awaiting_approval, completed, partially_completed,\nfailed or cancelled","type":"string"},"vaultId":{"title":"vault_id is the vault withdrawn from","type":"string"}},"required":["id","vaultId","amountUsd","destinationAddress","destinationChain","status","createdAt"],"title":"YieldWithdrawal is a withdrawal record","type":"object"},"AppErrorStatus":{"description":"The error envelope this API returns for every non-2xx response. `details` always contains exactly one AppError.","properties":{"code":{"description":"gRPC status code","format":"int32","type":"integer"},"details":{"description":"Always contains exactly one AppError","items":{"$ref":"#/components/schemas/AppError"},"type":"array"},"message":{"description":"Human-readable error message","type":"string"}},"type":"object"},"AppError":{"description":"Structured error detail responded by any non-2xx response.","properties":{"@type":{"description":"Protobuf Any type URL, always \"type.googleapis.com/pay.common.error.v1.AppError\" for this API","type":"string"},"internalCode":{"description":"Internal error code, unique within the module","format":"int32","type":"integer"},"message":{"description":"Human-readable error message","type":"string"},"meta":{"additionalProperties":{"type":"string"},"description":"Additional structured context for the error, if any","type":"object"},"module":{"description":"Module name where the error occurred (e.g. \"accounts\", \"market\")","type":"string"}},"type":"object"}},"responses":{"AppError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppErrorStatus"}}},"description":"An unexpected error response. `details[0]` is always an AppError, see #/components/schemas/AppError"}}},"paths":{"/market/v1/yields/withdrawals/{accountId}":{"get":{"description":"Includes in-flight withdrawals, used by the frontend to poll withdrawal status","operationId":"MarketQueryService_ListYieldWithdrawals","parameters":[{"description":"account_id is the account to list withdrawals for","in":"path","name":"accountId","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/yieldsListYieldWithdrawalsResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"ListYieldWithdrawals lists the account's withdrawal history","tags":["MarketQueryService"]}}}}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

```
GET https://docs.kiiglobal.io/docs/kiichain-pay/api-reference/market.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
