> 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/tickets.md).

# Tickets

## GetTicketsByAccount returns tickets for a specific account with pagination and filtering

> Scoped to a single account\_id. Use GetTickets for the platform-wide\
> admin view across every account

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"description":"Queries (read operations)","name":"TicketsQueryService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["tickets.tickets.read"]},{"BearerAuth":["tickets.tickets.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":{"v1GetTicketsByAccountResponse":{"properties":{"pagination":{"$ref":"#/components/schemas/v1Pagination"},"tickets":{"items":{"$ref":"#/components/schemas/v1Ticket"},"title":"tickets contains the list of tickets for the requested account","type":"array"}},"required":["tickets","pagination"],"title":"GetTicketsByAccountResponse is the response structure for the GetTicketsByAccount endpoint","type":"object"},"v1Pagination":{"properties":{"currentPage":{"format":"int32","title":"current_page is the current page number","type":"integer"},"limit":{"format":"int32","title":"limit contains the limit used to calculate the page","type":"integer"},"totalItems":{"format":"int32","title":"total_items is the total number of items","type":"integer"},"totalPages":{"format":"int32","title":"total_pages is the total number of pages","type":"integer"}},"required":["currentPage","totalItems","totalPages","limit"],"title":"Pagination contains the keys to move between pages\nusing the cursor-based pagination","type":"object"},"v1Ticket":{"properties":{"accountId":{"title":"Account ID associated with the ticket","type":"string"},"amount":{"title":"Amount in asset units (in atoms) - integer only, no decimals","type":"string"},"amountUsd":{"title":"Amount in USD - decimal value (e.g. \"123.45\")","type":"string"},"createdAt":{"format":"date-time","title":"Created at timestamp","type":"string"},"deadline":{"format":"date-time","title":"Expire at timestamp","type":"string"},"dexValueLocation":{"$ref":"#/components/schemas/v1DexValueLocation"},"displayStatus":{"description":"Display status of the ticket for user-friendly display.\nPossible values: \"pending\", \"fulfilled\", \"canceled\", \"failed\", \"refunded\", \"processing\", \"expired\", \"stuck\".","type":"string"},"id":{"title":"Unique identifier for the ticket","type":"string"},"metadata":{"additionalProperties":{"type":"string"},"title":"Metadata information - user managed","type":"object"},"productFee":{"title":"Product fee amount in atoms - integer only, no decimals","type":"string"},"productProviderId":{"title":"product_provider_id is the product-provider this ticket targets (target_type = \"onramp\" or \"offramp\")","type":"string"},"providerId":{"title":"provider_id is the DEX aggregator provider this ticket targets (target_type = \"dex\")","type":"string"},"quote":{"$ref":"#/components/schemas/v1Quote"},"state":{"title":"State of the ticket","type":"string"},"swapInstrumentId":{"title":"swap_instrument_id is the swap instrument this ticket targets (target_type = \"swap\")","type":"string"},"targetType":{"title":"Legacy discriminator, kept only to identify a ticket's target type when all the\ntyped target fields below are null (target was deleted)","type":"string"},"template":{"title":"Template information as JSON","type":"object"},"tradeInstrumentId":{"title":"trade_instrument_id is the trade instrument this ticket targets (target_type = \"trade\")","type":"string"},"type":{"title":"Type of the ticket (off-ramp, cex-custodial, cex-non-custodial, on-ramp, etc.)","type":"string"},"updatedAt":{"format":"date-time","title":"Updated at timestamp","type":"string"},"userChainAddress":{"title":"UserChainAddress associated with the ticket","type":"string"},"withdrawDestinationId":{"title":"Withdrawal destination ID associated with the ticket","type":"string"}},"required":["id","type","targetType","accountId","userChainAddress","amount","amountUsd","state","displayStatus","productFee","createdAt","updatedAt"],"title":"Ticket represents a support or issue ticket","type":"object"},"v1DexValueLocation":{"properties":{"amount":{"title":"amount is the quantity in the asset's base denomination, empty when the route halted\nbefore anything reported what was delivered","type":"string"},"chainId":{"title":"chain_id is the chain the value sits on","type":"string"},"denom":{"title":"denom is the asset denomination, empty when the halt cannot tell which asset landed","type":"string"},"lastTxHash":{"title":"last_tx_hash is the hash of the last transaction seen for the route before it halted","type":"string"}},"required":["chainId","lastTxHash"],"title":"DexValueLocation is where a halted DEX route left the user's value","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":{"/tickets/v1/accounts/{accountId}":{"get":{"description":"Scoped to a single account_id. Use GetTickets for the platform-wide\nadmin view across every account","operationId":"TicketsQueryService_GetTicketsByAccount","parameters":[{"description":"account_id is the unique identifier of the account whose tickets are requested","in":"path","name":"accountId","required":true,"schema":{"type":"string"}},{"description":"page is an optional query parameter to set the page","in":"query","name":"page","required":false,"schema":{"format":"int32","type":"integer"}},{"description":"limit is an optional query parameter to set the max number of results","in":"query","name":"limit","required":false,"schema":{"format":"int32","type":"integer"}},{"description":"display_status is an optional filter to return only tickets with the given display status","in":"query","name":"displayStatus","required":false,"schema":{"type":"string"}},{"description":"state is an optional filter to return only tickets with the given state","in":"query","name":"state","required":false,"schema":{"type":"string"}},{"description":"type is an optional filter to return only tickets of the given type","in":"query","name":"type","required":false,"schema":{"type":"string"}},{"description":"sort_by is an optional field to sort the results","in":"query","name":"sortBy","required":false,"schema":{"type":"string"}},{"description":"sort_order is an optional field to set the sort direction","in":"query","name":"sortOrder","required":false,"schema":{"type":"string"}},{"description":"start_date optionally keeps only tickets created at or after this time","in":"query","name":"startDate","required":false,"schema":{"format":"date-time","type":"string"}},{"description":"end_date optionally keeps only tickets created before this time (exclusive)","in":"query","name":"endDate","required":false,"schema":{"format":"date-time","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/v1GetTicketsByAccountResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"GetTicketsByAccount returns tickets for a specific account with pagination and filtering","tags":["TicketsQueryService"]}}}}
```

## GetTicketsSummaryByAccount returns the ticket counts and USD totals of an account

> Totals are grouped by type and display status, so a client can build any\
> breakdown (money in, money out, swapped) from one call. USD values are the\
> ones stored when each ticket was created. Use GetTicketsSummary for the\
> platform-wide admin view

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"description":"Queries (read operations)","name":"TicketsQueryService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["tickets.tickets.read"]},{"BearerAuth":["tickets.tickets.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":{"v1GetTicketsSummaryByAccountResponse":{"properties":{"summary":{"$ref":"#/components/schemas/v1TicketsSummary"}},"required":["summary"],"title":"GetTicketsSummaryByAccountResponse is the response structure for the GetTicketsSummaryByAccount endpoint","type":"object"},"v1TicketsSummary":{"properties":{"amountUsd":{"title":"amount_usd is the sum of the matched tickets' USD amounts, as a decimal (e.g. \"123.45\")","type":"string"},"count":{"format":"int32","title":"count is the number of tickets matched","type":"integer"},"firstCreatedAt":{"format":"date-time","title":"first_created_at is when the oldest matched ticket was created, absent when nothing matched","type":"string"},"groups":{"items":{"$ref":"#/components/schemas/v1TicketsSummaryGroup"},"title":"groups breaks the totals down per type and display status. Combinations with no tickets are left out","type":"array"},"lastCreatedAt":{"format":"date-time","title":"last_created_at is when the newest matched ticket was created, absent when nothing matched","type":"string"}},"required":["count","amountUsd","groups"],"title":"TicketsSummary holds the ticket counts and USD totals of a set of tickets","type":"object"},"v1TicketsSummaryGroup":{"properties":{"amountUsd":{"title":"amount_usd is the sum of the group's USD amounts, as a decimal (e.g. \"123.45\")","type":"string"},"count":{"format":"int32","title":"count is the number of tickets in the group","type":"integer"},"displayStatus":{"title":"display_status is the display status of the group","type":"string"},"maxAmountUsd":{"title":"max_amount_usd is the largest USD amount in the group, as a decimal (e.g. \"123.45\")","type":"string"},"type":{"title":"type is the ticket type of the group","type":"string"}},"required":["type","displayStatus","count","amountUsd","maxAmountUsd"],"title":"TicketsSummaryGroup holds the totals of the tickets sharing one type and display status","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":{"/tickets/v1/accounts/{accountId}/summary":{"get":{"description":"Totals are grouped by type and display status, so a client can build any\nbreakdown (money in, money out, swapped) from one call. USD values are the\nones stored when each ticket was created. Use GetTicketsSummary for the\nplatform-wide admin view","operationId":"TicketsQueryService_GetTicketsSummaryByAccount","parameters":[{"description":"account_id is the unique identifier of the account whose tickets are summarized","in":"path","name":"accountId","required":true,"schema":{"type":"string"}},{"description":"start_date optionally keeps only tickets created at or after this time","in":"query","name":"startDate","required":false,"schema":{"format":"date-time","type":"string"}},{"description":"end_date optionally keeps only tickets created before this time (exclusive)","in":"query","name":"endDate","required":false,"schema":{"format":"date-time","type":"string"}},{"description":"types optionally keeps only tickets of these types.\nPossible values: \"onramp\", \"offramp\", \"swap\", \"trade\", \"dex\"","explode":true,"in":"query","name":"types","required":false,"schema":{"items":{"type":"string"},"type":"array"}},{"description":"display_statuses optionally keeps only tickets in these display statuses.\nPossible values: \"pending\", \"fulfilled\", \"canceled\", \"failed\", \"refunded\", \"processing\", \"expired\", \"stuck\"","explode":true,"in":"query","name":"displayStatuses","required":false,"schema":{"items":{"type":"string"},"type":"array"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/v1GetTicketsSummaryByAccountResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"GetTicketsSummaryByAccount returns the ticket counts and USD totals of an account","tags":["TicketsQueryService"]}}}}
```

## CreateDexTicket creates a ticket that tracks a cross-chain DEX route

> Re-runs the DEX router server-side and persists the fresh route, because route calldata\
> is only valid for seconds. The response carries every transaction of the route in\
> submission order, an approval together with the swap or bridge it unlocks, for the caller\
> to sign and report through SubmitDexStep. TicketGetPendingUserAction returns the ones not\
> submitted yet while the ticket waits on a step

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"description":"Msg service (write operations)","name":"TicketsMsgService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["tickets.tickets.write"]},{"BearerAuth":["tickets.tickets.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":{"v1CreateDexTicketRequest":{"properties":{"accountId":{"title":"Account ID associated with the ticket","type":"string"},"allowMultiHops":{"title":"allow_multi_hops allows a route that needs more than one leg. The first leg comes back here,\neach later one appears on GetPendingUserAction once the previous leg delivered, with the\nticket back in dex_waiting_step. Send the same value used on the pricing quote","type":"boolean"},"assetIn":{"$ref":"#/components/schemas/v1DexTicketAssetAmount"},"assetOut":{"$ref":"#/components/schemas/v1DexTicketAsset"},"metadata":{"additionalProperties":{"type":"string"},"title":"Metadata information - user managed","type":"object"},"minAmountOut":{"title":"min_amount_out is the floor the caller already accepted on the quote shown to them.\nCreation fails if the fresh server-side re-quote's expected output comes back below it.\nThe route's on-chain minimum can still land up to one slippage under it","type":"string"},"userChainAddress":{"title":"user_chain_address is the wallet address that signs every step of the route","type":"string"}},"required":["accountId","assetIn","assetOut","minAmountOut","userChainAddress"],"title":"CreateDexTicketRequest is the body request structure for the CreateDexTicket endpoint","type":"object"},"v1DexTicketAssetAmount":{"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":"DexTicketAssetAmount is a cross-chain asset paired with an amount","type":"object"},"v1DexTicketAsset":{"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":"DexTicketAsset identifies a cross-chain asset by its denomination and chain, with no amount","type":"object"},"v1CreateDexTicketResponse":{"properties":{"ticket":{"$ref":"#/components/schemas/v1Ticket"},"transactions":{"items":{"$ref":"#/components/schemas/blockchainV1Transaction"},"title":"transactions is the route's first leg in submission order, all signed and submitted by the\ncaller. A route that needs more than one leg hands the later ones out through\nGetPendingUserAction, once the previous leg delivered","type":"array"}},"required":["ticket","transactions"],"title":"CreateDexTicketResponse is the body response structure for the CreateDexTicket endpoint","type":"object"},"v1Ticket":{"properties":{"accountId":{"title":"Account ID associated with the ticket","type":"string"},"amount":{"title":"Amount in asset units (in atoms) - integer only, no decimals","type":"string"},"amountUsd":{"title":"Amount in USD - decimal value (e.g. \"123.45\")","type":"string"},"createdAt":{"format":"date-time","title":"Created at timestamp","type":"string"},"deadline":{"format":"date-time","title":"Expire at timestamp","type":"string"},"dexValueLocation":{"$ref":"#/components/schemas/v1DexValueLocation"},"displayStatus":{"description":"Display status of the ticket for user-friendly display.\nPossible values: \"pending\", \"fulfilled\", \"canceled\", \"failed\", \"refunded\", \"processing\", \"expired\", \"stuck\".","type":"string"},"id":{"title":"Unique identifier for the ticket","type":"string"},"metadata":{"additionalProperties":{"type":"string"},"title":"Metadata information - user managed","type":"object"},"productFee":{"title":"Product fee amount in atoms - integer only, no decimals","type":"string"},"productProviderId":{"title":"product_provider_id is the product-provider this ticket targets (target_type = \"onramp\" or \"offramp\")","type":"string"},"providerId":{"title":"provider_id is the DEX aggregator provider this ticket targets (target_type = \"dex\")","type":"string"},"quote":{"$ref":"#/components/schemas/v1Quote"},"state":{"title":"State of the ticket","type":"string"},"swapInstrumentId":{"title":"swap_instrument_id is the swap instrument this ticket targets (target_type = \"swap\")","type":"string"},"targetType":{"title":"Legacy discriminator, kept only to identify a ticket's target type when all the\ntyped target fields below are null (target was deleted)","type":"string"},"template":{"title":"Template information as JSON","type":"object"},"tradeInstrumentId":{"title":"trade_instrument_id is the trade instrument this ticket targets (target_type = \"trade\")","type":"string"},"type":{"title":"Type of the ticket (off-ramp, cex-custodial, cex-non-custodial, on-ramp, etc.)","type":"string"},"updatedAt":{"format":"date-time","title":"Updated at timestamp","type":"string"},"userChainAddress":{"title":"UserChainAddress associated with the ticket","type":"string"},"withdrawDestinationId":{"title":"Withdrawal destination ID associated with the ticket","type":"string"}},"required":["id","type","targetType","accountId","userChainAddress","amount","amountUsd","state","displayStatus","productFee","createdAt","updatedAt"],"title":"Ticket represents a support or issue ticket","type":"object"},"v1DexValueLocation":{"properties":{"amount":{"title":"amount is the quantity in the asset's base denomination, empty when the route halted\nbefore anything reported what was delivered","type":"string"},"chainId":{"title":"chain_id is the chain the value sits on","type":"string"},"denom":{"title":"denom is the asset denomination, empty when the halt cannot tell which asset landed","type":"string"},"lastTxHash":{"title":"last_tx_hash is the hash of the last transaction seen for the route before it halted","type":"string"}},"required":["chainId","lastTxHash"],"title":"DexValueLocation is where a halted DEX route left the user's value","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"},"blockchainV1Transaction":{"properties":{"evm":{"$ref":"#/components/schemas/v1EVMTransaction"},"typedData":{"$ref":"#/components/schemas/v1EVMTypedData"}},"title":"Transaction wraps the user actions to build an ordered list, either a transaction to send\nor a typed data to sign","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"},"v1EVMTypedData":{"description":"Sign typed_data as is with eth_signTypedData_v4 from the signer wallet, then send the\nsignature back with SubmitTicketSignature","properties":{"chainId":{"title":"chain_id is the ID of the network the typed data is bound to","type":"string"},"metadata":{"additionalProperties":{"type":"string"},"title":"metadata is the map of additional information sent with the typed data","type":"object"},"signer":{"title":"signer is the address that must sign the typed data","type":"string"},"type":{"title":"type is what is being signed, the accepted values are: permit","type":"string"},"typedData":{"title":"typed_data is the full EIP-712 JSON (types, domain, primaryType and message)","type":"string"}},"required":["type","chainId","signer","typedData"],"title":"EVMTypedData is an EIP-712 message the user signs instead of sending a transaction","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":{"/tickets/v1/dex":{"post":{"description":"Re-runs the DEX router server-side and persists the fresh route, because route calldata\nis only valid for seconds. The response carries every transaction of the route in\nsubmission order, an approval together with the swap or bridge it unlocks, for the caller\nto sign and report through SubmitDexStep. TicketGetPendingUserAction returns the ones not\nsubmitted yet while the ticket waits on a step","operationId":"TicketsMsgService_CreateDexTicket","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/v1CreateDexTicketRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/v1CreateDexTicketResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"CreateDexTicket creates a ticket that tracks a cross-chain DEX route","tags":["TicketsMsgService"]}}}}
```

## CreateOffRampTicket creates a new off-ramp ticket

> Kicks off the off-ramp flow for the given quote. Response includes the\
> transactions the user must sign to fund it

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"description":"Msg service (write operations)","name":"TicketsMsgService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["tickets.tickets.write"]},{"BearerAuth":["tickets.tickets.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":{"v1CreateOffRampTicketRequest":{"properties":{"accountId":{"title":"Account ID associated with the ticket","type":"string"},"metadata":{"additionalProperties":{"type":"string"},"title":"Metadata information - user managed","type":"object"},"productsProviderId":{"title":"Target ID associated with the ticket","type":"string"},"quote":{"$ref":"#/components/schemas/v1Quote"},"template":{"title":"Template information as JSON","type":"object"},"userChainAddress":{"title":"UserChainAddress associated with the ticket","type":"string"},"withdrawDestinationId":{"title":"Withdrawal destination ID associated with the ticket","type":"string"}},"required":["productsProviderId","accountId","userChainAddress","quote"],"title":"CreateOffRampTicketRequest is the body request structure for the CreateOffRampTicket endpoint","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"},"v1CreateOffRampTicketResponse":{"properties":{"ticket":{"$ref":"#/components/schemas/v1Ticket"},"transactions":{"items":{"$ref":"#/components/schemas/blockchainV1Transaction"},"title":"Transaction message containing the information needed to execute the transaction on the blockchain","type":"array"}},"required":["ticket","transactions"],"title":"CreateOffRampTicketResponse is the body response structure for the CreateOffRampTicket endpoint","type":"object"},"v1Ticket":{"properties":{"accountId":{"title":"Account ID associated with the ticket","type":"string"},"amount":{"title":"Amount in asset units (in atoms) - integer only, no decimals","type":"string"},"amountUsd":{"title":"Amount in USD - decimal value (e.g. \"123.45\")","type":"string"},"createdAt":{"format":"date-time","title":"Created at timestamp","type":"string"},"deadline":{"format":"date-time","title":"Expire at timestamp","type":"string"},"dexValueLocation":{"$ref":"#/components/schemas/v1DexValueLocation"},"displayStatus":{"description":"Display status of the ticket for user-friendly display.\nPossible values: \"pending\", \"fulfilled\", \"canceled\", \"failed\", \"refunded\", \"processing\", \"expired\", \"stuck\".","type":"string"},"id":{"title":"Unique identifier for the ticket","type":"string"},"metadata":{"additionalProperties":{"type":"string"},"title":"Metadata information - user managed","type":"object"},"productFee":{"title":"Product fee amount in atoms - integer only, no decimals","type":"string"},"productProviderId":{"title":"product_provider_id is the product-provider this ticket targets (target_type = \"onramp\" or \"offramp\")","type":"string"},"providerId":{"title":"provider_id is the DEX aggregator provider this ticket targets (target_type = \"dex\")","type":"string"},"quote":{"$ref":"#/components/schemas/v1Quote"},"state":{"title":"State of the ticket","type":"string"},"swapInstrumentId":{"title":"swap_instrument_id is the swap instrument this ticket targets (target_type = \"swap\")","type":"string"},"targetType":{"title":"Legacy discriminator, kept only to identify a ticket's target type when all the\ntyped target fields below are null (target was deleted)","type":"string"},"template":{"title":"Template information as JSON","type":"object"},"tradeInstrumentId":{"title":"trade_instrument_id is the trade instrument this ticket targets (target_type = \"trade\")","type":"string"},"type":{"title":"Type of the ticket (off-ramp, cex-custodial, cex-non-custodial, on-ramp, etc.)","type":"string"},"updatedAt":{"format":"date-time","title":"Updated at timestamp","type":"string"},"userChainAddress":{"title":"UserChainAddress associated with the ticket","type":"string"},"withdrawDestinationId":{"title":"Withdrawal destination ID associated with the ticket","type":"string"}},"required":["id","type","targetType","accountId","userChainAddress","amount","amountUsd","state","displayStatus","productFee","createdAt","updatedAt"],"title":"Ticket represents a support or issue ticket","type":"object"},"v1DexValueLocation":{"properties":{"amount":{"title":"amount is the quantity in the asset's base denomination, empty when the route halted\nbefore anything reported what was delivered","type":"string"},"chainId":{"title":"chain_id is the chain the value sits on","type":"string"},"denom":{"title":"denom is the asset denomination, empty when the halt cannot tell which asset landed","type":"string"},"lastTxHash":{"title":"last_tx_hash is the hash of the last transaction seen for the route before it halted","type":"string"}},"required":["chainId","lastTxHash"],"title":"DexValueLocation is where a halted DEX route left the user's value","type":"object"},"blockchainV1Transaction":{"properties":{"evm":{"$ref":"#/components/schemas/v1EVMTransaction"},"typedData":{"$ref":"#/components/schemas/v1EVMTypedData"}},"title":"Transaction wraps the user actions to build an ordered list, either a transaction to send\nor a typed data to sign","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"},"v1EVMTypedData":{"description":"Sign typed_data as is with eth_signTypedData_v4 from the signer wallet, then send the\nsignature back with SubmitTicketSignature","properties":{"chainId":{"title":"chain_id is the ID of the network the typed data is bound to","type":"string"},"metadata":{"additionalProperties":{"type":"string"},"title":"metadata is the map of additional information sent with the typed data","type":"object"},"signer":{"title":"signer is the address that must sign the typed data","type":"string"},"type":{"title":"type is what is being signed, the accepted values are: permit","type":"string"},"typedData":{"title":"typed_data is the full EIP-712 JSON (types, domain, primaryType and message)","type":"string"}},"required":["type","chainId","signer","typedData"],"title":"EVMTypedData is an EIP-712 message the user signs instead of sending a transaction","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":{"/tickets/v1/offramp":{"post":{"description":"Kicks off the off-ramp flow for the given quote. Response includes the\ntransactions the user must sign to fund it","operationId":"TicketsMsgService_CreateOffRampTicket","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/v1CreateOffRampTicketRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/v1CreateOffRampTicketResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"CreateOffRampTicket creates a new off-ramp ticket","tags":["TicketsMsgService"]}}}}
```

## CreateSwapTicket creates a new swap ticket with the given parameters

> Kicks off the swap flow for an instrument's quote. Response includes\
> the transactions the user must sign to fund it

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"description":"Msg service (write operations)","name":"TicketsMsgService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["tickets.tickets.write"]},{"BearerAuth":["tickets.tickets.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":{"v1CreateSwapTicketRequest":{"properties":{"accountId":{"title":"Account ID associated with the ticket","type":"string"},"instrumentId":{"title":"instrument_id contains the target ID associated with the ticket","type":"string"},"metadata":{"additionalProperties":{"type":"string"},"title":"Metadata information - user managed","type":"object"},"quote":{"$ref":"#/components/schemas/v1Quote"},"template":{"title":"Template information as JSON","type":"object"},"userChainAddress":{"title":"UserChainAddress associated with the ticket","type":"string"},"withdrawDestinationId":{"title":"Withdrawal destination ID associated with the ticket","type":"string"}},"required":["instrumentId","accountId","userChainAddress","quote"],"title":"CreateSwapTicketRequest is the body request structure for the CreateSwapTicket endpoint","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"},"v1CreateSwapTicketResponse":{"properties":{"ticket":{"$ref":"#/components/schemas/v1Ticket"},"transactions":{"items":{"$ref":"#/components/schemas/blockchainV1Transaction"},"title":"Transaction message containing the information needed to execute the transaction on the blockchain","type":"array"}},"required":["ticket","transactions"],"title":"CreateSwapTicketResponse is the body response structure for the CreateSwapTicket endpoint","type":"object"},"v1Ticket":{"properties":{"accountId":{"title":"Account ID associated with the ticket","type":"string"},"amount":{"title":"Amount in asset units (in atoms) - integer only, no decimals","type":"string"},"amountUsd":{"title":"Amount in USD - decimal value (e.g. \"123.45\")","type":"string"},"createdAt":{"format":"date-time","title":"Created at timestamp","type":"string"},"deadline":{"format":"date-time","title":"Expire at timestamp","type":"string"},"dexValueLocation":{"$ref":"#/components/schemas/v1DexValueLocation"},"displayStatus":{"description":"Display status of the ticket for user-friendly display.\nPossible values: \"pending\", \"fulfilled\", \"canceled\", \"failed\", \"refunded\", \"processing\", \"expired\", \"stuck\".","type":"string"},"id":{"title":"Unique identifier for the ticket","type":"string"},"metadata":{"additionalProperties":{"type":"string"},"title":"Metadata information - user managed","type":"object"},"productFee":{"title":"Product fee amount in atoms - integer only, no decimals","type":"string"},"productProviderId":{"title":"product_provider_id is the product-provider this ticket targets (target_type = \"onramp\" or \"offramp\")","type":"string"},"providerId":{"title":"provider_id is the DEX aggregator provider this ticket targets (target_type = \"dex\")","type":"string"},"quote":{"$ref":"#/components/schemas/v1Quote"},"state":{"title":"State of the ticket","type":"string"},"swapInstrumentId":{"title":"swap_instrument_id is the swap instrument this ticket targets (target_type = \"swap\")","type":"string"},"targetType":{"title":"Legacy discriminator, kept only to identify a ticket's target type when all the\ntyped target fields below are null (target was deleted)","type":"string"},"template":{"title":"Template information as JSON","type":"object"},"tradeInstrumentId":{"title":"trade_instrument_id is the trade instrument this ticket targets (target_type = \"trade\")","type":"string"},"type":{"title":"Type of the ticket (off-ramp, cex-custodial, cex-non-custodial, on-ramp, etc.)","type":"string"},"updatedAt":{"format":"date-time","title":"Updated at timestamp","type":"string"},"userChainAddress":{"title":"UserChainAddress associated with the ticket","type":"string"},"withdrawDestinationId":{"title":"Withdrawal destination ID associated with the ticket","type":"string"}},"required":["id","type","targetType","accountId","userChainAddress","amount","amountUsd","state","displayStatus","productFee","createdAt","updatedAt"],"title":"Ticket represents a support or issue ticket","type":"object"},"v1DexValueLocation":{"properties":{"amount":{"title":"amount is the quantity in the asset's base denomination, empty when the route halted\nbefore anything reported what was delivered","type":"string"},"chainId":{"title":"chain_id is the chain the value sits on","type":"string"},"denom":{"title":"denom is the asset denomination, empty when the halt cannot tell which asset landed","type":"string"},"lastTxHash":{"title":"last_tx_hash is the hash of the last transaction seen for the route before it halted","type":"string"}},"required":["chainId","lastTxHash"],"title":"DexValueLocation is where a halted DEX route left the user's value","type":"object"},"blockchainV1Transaction":{"properties":{"evm":{"$ref":"#/components/schemas/v1EVMTransaction"},"typedData":{"$ref":"#/components/schemas/v1EVMTypedData"}},"title":"Transaction wraps the user actions to build an ordered list, either a transaction to send\nor a typed data to sign","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"},"v1EVMTypedData":{"description":"Sign typed_data as is with eth_signTypedData_v4 from the signer wallet, then send the\nsignature back with SubmitTicketSignature","properties":{"chainId":{"title":"chain_id is the ID of the network the typed data is bound to","type":"string"},"metadata":{"additionalProperties":{"type":"string"},"title":"metadata is the map of additional information sent with the typed data","type":"object"},"signer":{"title":"signer is the address that must sign the typed data","type":"string"},"type":{"title":"type is what is being signed, the accepted values are: permit","type":"string"},"typedData":{"title":"typed_data is the full EIP-712 JSON (types, domain, primaryType and message)","type":"string"}},"required":["type","chainId","signer","typedData"],"title":"EVMTypedData is an EIP-712 message the user signs instead of sending a transaction","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":{"/tickets/v1/swap":{"post":{"description":"Kicks off the swap flow for an instrument's quote. Response includes\nthe transactions the user must sign to fund it","operationId":"TicketsMsgService_CreateSwapTicket","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/v1CreateSwapTicketRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/v1CreateSwapTicketResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"CreateSwapTicket creates a new swap ticket with the given parameters","tags":["TicketsMsgService"]}}}}
```

## CreateTradeTicket creates a new trade ticket for the trade page feature

> Kicks off the trade flow for a trade instrument's quote. Crypto-input trades\
> return the deposit details on the ticket metadata; fiat-input trades lock the ledger

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"description":"Msg service (write operations)","name":"TicketsMsgService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["tickets.tickets.write"]},{"BearerAuth":["tickets.tickets.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":{"v1CreateTradeTicketRequest":{"properties":{"accountId":{"title":"account_id is the account creating the trade","type":"string"},"instrumentId":{"title":"instrument_id is the trade instrument targeted by the ticket","type":"string"},"metadata":{"additionalProperties":{"type":"string"},"title":"metadata information - user managed","type":"object"},"quote":{"$ref":"#/components/schemas/v1Quote"},"template":{"title":"template information as JSON","type":"object"},"userChainAddress":{"title":"user_chain_address is the user's chain address, optional since fiat-input trades have none","type":"string"},"withdrawDestinationId":{"title":"withdraw_destination_id is the payout destination, required for crypto-output trades","type":"string"}},"required":["instrumentId","accountId","quote"],"title":"CreateTradeTicketRequest is the body request structure for the CreateTradeTicket endpoint","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"},"v1CreateTradeTicketResponse":{"properties":{"ticket":{"$ref":"#/components/schemas/v1Ticket"},"transactions":{"items":{"$ref":"#/components/schemas/blockchainV1Transaction"},"title":"transactions is present for parity with other create endpoints; trades never return one","type":"array"}},"required":["ticket"],"title":"CreateTradeTicketResponse is the body response structure for the CreateTradeTicket endpoint","type":"object"},"v1Ticket":{"properties":{"accountId":{"title":"Account ID associated with the ticket","type":"string"},"amount":{"title":"Amount in asset units (in atoms) - integer only, no decimals","type":"string"},"amountUsd":{"title":"Amount in USD - decimal value (e.g. \"123.45\")","type":"string"},"createdAt":{"format":"date-time","title":"Created at timestamp","type":"string"},"deadline":{"format":"date-time","title":"Expire at timestamp","type":"string"},"dexValueLocation":{"$ref":"#/components/schemas/v1DexValueLocation"},"displayStatus":{"description":"Display status of the ticket for user-friendly display.\nPossible values: \"pending\", \"fulfilled\", \"canceled\", \"failed\", \"refunded\", \"processing\", \"expired\", \"stuck\".","type":"string"},"id":{"title":"Unique identifier for the ticket","type":"string"},"metadata":{"additionalProperties":{"type":"string"},"title":"Metadata information - user managed","type":"object"},"productFee":{"title":"Product fee amount in atoms - integer only, no decimals","type":"string"},"productProviderId":{"title":"product_provider_id is the product-provider this ticket targets (target_type = \"onramp\" or \"offramp\")","type":"string"},"providerId":{"title":"provider_id is the DEX aggregator provider this ticket targets (target_type = \"dex\")","type":"string"},"quote":{"$ref":"#/components/schemas/v1Quote"},"state":{"title":"State of the ticket","type":"string"},"swapInstrumentId":{"title":"swap_instrument_id is the swap instrument this ticket targets (target_type = \"swap\")","type":"string"},"targetType":{"title":"Legacy discriminator, kept only to identify a ticket's target type when all the\ntyped target fields below are null (target was deleted)","type":"string"},"template":{"title":"Template information as JSON","type":"object"},"tradeInstrumentId":{"title":"trade_instrument_id is the trade instrument this ticket targets (target_type = \"trade\")","type":"string"},"type":{"title":"Type of the ticket (off-ramp, cex-custodial, cex-non-custodial, on-ramp, etc.)","type":"string"},"updatedAt":{"format":"date-time","title":"Updated at timestamp","type":"string"},"userChainAddress":{"title":"UserChainAddress associated with the ticket","type":"string"},"withdrawDestinationId":{"title":"Withdrawal destination ID associated with the ticket","type":"string"}},"required":["id","type","targetType","accountId","userChainAddress","amount","amountUsd","state","displayStatus","productFee","createdAt","updatedAt"],"title":"Ticket represents a support or issue ticket","type":"object"},"v1DexValueLocation":{"properties":{"amount":{"title":"amount is the quantity in the asset's base denomination, empty when the route halted\nbefore anything reported what was delivered","type":"string"},"chainId":{"title":"chain_id is the chain the value sits on","type":"string"},"denom":{"title":"denom is the asset denomination, empty when the halt cannot tell which asset landed","type":"string"},"lastTxHash":{"title":"last_tx_hash is the hash of the last transaction seen for the route before it halted","type":"string"}},"required":["chainId","lastTxHash"],"title":"DexValueLocation is where a halted DEX route left the user's value","type":"object"},"blockchainV1Transaction":{"properties":{"evm":{"$ref":"#/components/schemas/v1EVMTransaction"},"typedData":{"$ref":"#/components/schemas/v1EVMTypedData"}},"title":"Transaction wraps the user actions to build an ordered list, either a transaction to send\nor a typed data to sign","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"},"v1EVMTypedData":{"description":"Sign typed_data as is with eth_signTypedData_v4 from the signer wallet, then send the\nsignature back with SubmitTicketSignature","properties":{"chainId":{"title":"chain_id is the ID of the network the typed data is bound to","type":"string"},"metadata":{"additionalProperties":{"type":"string"},"title":"metadata is the map of additional information sent with the typed data","type":"object"},"signer":{"title":"signer is the address that must sign the typed data","type":"string"},"type":{"title":"type is what is being signed, the accepted values are: permit","type":"string"},"typedData":{"title":"typed_data is the full EIP-712 JSON (types, domain, primaryType and message)","type":"string"}},"required":["type","chainId","signer","typedData"],"title":"EVMTypedData is an EIP-712 message the user signs instead of sending a transaction","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":{"/tickets/v1/trade":{"post":{"description":"Kicks off the trade flow for a trade instrument's quote. Crypto-input trades\nreturn the deposit details on the ticket metadata; fiat-input trades lock the ledger","operationId":"TicketsMsgService_CreateTradeTicket","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/v1CreateTradeTicketRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/v1CreateTradeTicketResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"CreateTradeTicket creates a new trade ticket for the trade page feature","tags":["TicketsMsgService"]}}}}
```

## GetTicket returns a ticket by its ID

> Ticket data only. Use GetTicketDetails for the context, flows and\
> provider information as well

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"description":"Queries (read operations)","name":"TicketsQueryService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["tickets.tickets.read"]},{"BearerAuth":["tickets.tickets.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":{"v1GetTicketResponse":{"properties":{"ticket":{"$ref":"#/components/schemas/v1Ticket"}},"required":["ticket"],"title":"GetTicketResponse is the body response structure for the GetTicket endpoint","type":"object"},"v1Ticket":{"properties":{"accountId":{"title":"Account ID associated with the ticket","type":"string"},"amount":{"title":"Amount in asset units (in atoms) - integer only, no decimals","type":"string"},"amountUsd":{"title":"Amount in USD - decimal value (e.g. \"123.45\")","type":"string"},"createdAt":{"format":"date-time","title":"Created at timestamp","type":"string"},"deadline":{"format":"date-time","title":"Expire at timestamp","type":"string"},"dexValueLocation":{"$ref":"#/components/schemas/v1DexValueLocation"},"displayStatus":{"description":"Display status of the ticket for user-friendly display.\nPossible values: \"pending\", \"fulfilled\", \"canceled\", \"failed\", \"refunded\", \"processing\", \"expired\", \"stuck\".","type":"string"},"id":{"title":"Unique identifier for the ticket","type":"string"},"metadata":{"additionalProperties":{"type":"string"},"title":"Metadata information - user managed","type":"object"},"productFee":{"title":"Product fee amount in atoms - integer only, no decimals","type":"string"},"productProviderId":{"title":"product_provider_id is the product-provider this ticket targets (target_type = \"onramp\" or \"offramp\")","type":"string"},"providerId":{"title":"provider_id is the DEX aggregator provider this ticket targets (target_type = \"dex\")","type":"string"},"quote":{"$ref":"#/components/schemas/v1Quote"},"state":{"title":"State of the ticket","type":"string"},"swapInstrumentId":{"title":"swap_instrument_id is the swap instrument this ticket targets (target_type = \"swap\")","type":"string"},"targetType":{"title":"Legacy discriminator, kept only to identify a ticket's target type when all the\ntyped target fields below are null (target was deleted)","type":"string"},"template":{"title":"Template information as JSON","type":"object"},"tradeInstrumentId":{"title":"trade_instrument_id is the trade instrument this ticket targets (target_type = \"trade\")","type":"string"},"type":{"title":"Type of the ticket (off-ramp, cex-custodial, cex-non-custodial, on-ramp, etc.)","type":"string"},"updatedAt":{"format":"date-time","title":"Updated at timestamp","type":"string"},"userChainAddress":{"title":"UserChainAddress associated with the ticket","type":"string"},"withdrawDestinationId":{"title":"Withdrawal destination ID associated with the ticket","type":"string"}},"required":["id","type","targetType","accountId","userChainAddress","amount","amountUsd","state","displayStatus","productFee","createdAt","updatedAt"],"title":"Ticket represents a support or issue ticket","type":"object"},"v1DexValueLocation":{"properties":{"amount":{"title":"amount is the quantity in the asset's base denomination, empty when the route halted\nbefore anything reported what was delivered","type":"string"},"chainId":{"title":"chain_id is the chain the value sits on","type":"string"},"denom":{"title":"denom is the asset denomination, empty when the halt cannot tell which asset landed","type":"string"},"lastTxHash":{"title":"last_tx_hash is the hash of the last transaction seen for the route before it halted","type":"string"}},"required":["chainId","lastTxHash"],"title":"DexValueLocation is where a halted DEX route left the user's value","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":{"/tickets/v1/{ticketId}":{"get":{"description":"Ticket data only. Use GetTicketDetails for the context, flows and\nprovider information as well","operationId":"TicketsQueryService_GetTicket","parameters":[{"description":"Unique identifier for the ticket","in":"path","name":"ticketId","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/v1GetTicketResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"GetTicket returns a ticket by its ID","tags":["TicketsQueryService"]}}}}
```

## SubmitDexStep records the transaction hash for the step a DEX ticket is waiting on

> Submissions are only accepted while the ticket waits on a step, and the ticket must belong\
> to account\_id. The hash is verified against the expected step before it is accepted: it\
> has to exist on that step's chain, be sent by the ticket's wallet, and target the step's\
> contract. Resubmitting a hash already recorded on the route is a no-op, even after the\
> ticket moved on. Three FailedPrecondition errors are retryable with the same hash: the\
> transaction is not found on chain yet, its sender and target are not readable yet, or the\
> ticket is not waiting on a step, which a just-created ticket reports until its flow\
> reaches the step

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"description":"Msg service (write operations)","name":"TicketsMsgService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["tickets.tickets.write"]},{"BearerAuth":["tickets.tickets.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":{"TicketsMsgServiceSubmitDexStepBody":{"properties":{"accountId":{"title":"account_id is the account that owns the ticket","type":"string"},"txHash":{"title":"tx_hash is the hash of the transaction the caller submitted for the step the ticket is\ncurrently waiting on","type":"string"}},"required":["txHash","accountId"],"title":"SubmitDexStepRequest is the body request structure for the SubmitDexStep endpoint","type":"object"},"v1SubmitDexStepResponse":{"title":"SubmitDexStepResponse is the body response structure for the SubmitDexStep endpoint","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":{"/tickets/v1/{ticketId}/dex/step":{"post":{"description":"Submissions are only accepted while the ticket waits on a step, and the ticket must belong\nto account_id. The hash is verified against the expected step before it is accepted: it\nhas to exist on that step's chain, be sent by the ticket's wallet, and target the step's\ncontract. Resubmitting a hash already recorded on the route is a no-op, even after the\nticket moved on. Three FailedPrecondition errors are retryable with the same hash: the\ntransaction is not found on chain yet, its sender and target are not readable yet, or the\nticket is not waiting on a step, which a just-created ticket reports until its flow\nreaches the step","operationId":"TicketsMsgService_SubmitDexStep","parameters":[{"description":"ticket_id is the dex ticket the step belongs to","in":"path","name":"ticketId","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TicketsMsgServiceSubmitDexStepBody"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/v1SubmitDexStepResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"SubmitDexStep records the transaction hash for the step a DEX ticket is waiting on","tags":["TicketsMsgService"]}}}}
```

## TicketGetPendingUserAction returns the pending user actions for a ticket

> Returns either a transaction the user still needs to sign/submit or a\
> URL they need to visit, depending on the ticket's current state

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"description":"Queries (read operations)","name":"TicketsQueryService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["tickets.tickets.read"]},{"BearerAuth":["tickets.tickets.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":{"v1TicketGetPendingUserActionResponse":{"properties":{"transactionPayload":{"$ref":"#/components/schemas/v1TransactionPayload"},"type":{"title":"The type of the ticket.\nExamples: offramp, onramp, swap","type":"string"},"urlPayload":{"$ref":"#/components/schemas/v1UrlPayload"}},"title":"TicketGetPendingUserActionResponse is the response structure for the TicketGetPendingUserAction endpoint","type":"object"},"v1TransactionPayload":{"properties":{"transactions":{"items":{"$ref":"#/components/schemas/blockchainV1Transaction"},"type":"array"}},"title":"TransactionPayload contains the list of transactions to be executed for a user action","type":"object"},"blockchainV1Transaction":{"properties":{"evm":{"$ref":"#/components/schemas/v1EVMTransaction"},"typedData":{"$ref":"#/components/schemas/v1EVMTypedData"}},"title":"Transaction wraps the user actions to build an ordered list, either a transaction to send\nor a typed data to sign","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"},"v1EVMTypedData":{"description":"Sign typed_data as is with eth_signTypedData_v4 from the signer wallet, then send the\nsignature back with SubmitTicketSignature","properties":{"chainId":{"title":"chain_id is the ID of the network the typed data is bound to","type":"string"},"metadata":{"additionalProperties":{"type":"string"},"title":"metadata is the map of additional information sent with the typed data","type":"object"},"signer":{"title":"signer is the address that must sign the typed data","type":"string"},"type":{"title":"type is what is being signed, the accepted values are: permit","type":"string"},"typedData":{"title":"typed_data is the full EIP-712 JSON (types, domain, primaryType and message)","type":"string"}},"required":["type","chainId","signer","typedData"],"title":"EVMTypedData is an EIP-712 message the user signs instead of sending a transaction","type":"object"},"v1UrlPayload":{"properties":{"expiresAt":{"format":"int64","title":"expires_at represents the expiration time of the URL","type":"string"},"url":{"title":"url represents the URL to be opened for the user action","type":"string"}},"required":["expiresAt"],"title":"UrlPayload contains the URL to be opened for a user action","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":{"/tickets/v1/{ticketId}/pending_user_actions":{"get":{"description":"Returns either a transaction the user still needs to sign/submit or a\nURL they need to visit, depending on the ticket's current state","operationId":"TicketsQueryService_TicketGetPendingUserAction","parameters":[{"description":"Unique identifier for the ticket","in":"path","name":"ticketId","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/v1TicketGetPendingUserActionResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"TicketGetPendingUserAction returns the pending user actions for a ticket","tags":["TicketsQueryService"]}}}}
```

## SubmitTicketSignature sends the signature of a typed data action the ticket is waiting on

> Used when a ticket returns a typed\_data action instead of a transaction, for example the\
> permit of a swap. The signature must come from the signer of the action and the ticket must\
> belong to account\_id and still be waiting on the user. A wrong signature is rejected and the\
> ticket keeps waiting, so the user can sign again

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"description":"Msg service (write operations)","name":"TicketsMsgService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["tickets.tickets.write"]},{"BearerAuth":["tickets.tickets.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":{"TicketsMsgServiceSubmitTicketSignatureBody":{"properties":{"accountId":{"title":"account_id is the account that owns the ticket","type":"string"},"signature":{"title":"signature is the 65 byte EIP-712 signature as 0x prefixed hex","type":"string"},"type":{"title":"type is the type of the typed data action being signed, the accepted values are: permit","type":"string"}},"required":["accountId","type","signature"],"title":"SubmitTicketSignatureRequest is the body request structure for the SubmitTicketSignature endpoint","type":"object"},"v1SubmitTicketSignatureResponse":{"title":"SubmitTicketSignatureResponse is the body response structure for the SubmitTicketSignature endpoint","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":{"/tickets/v1/{ticketId}/signature":{"post":{"description":"Used when a ticket returns a typed_data action instead of a transaction, for example the\npermit of a swap. The signature must come from the signer of the action and the ticket must\nbelong to account_id and still be waiting on the user. A wrong signature is rejected and the\nticket keeps waiting, so the user can sign again","operationId":"TicketsMsgService_SubmitTicketSignature","parameters":[{"description":"ticket_id is the ticket waiting on the signature","in":"path","name":"ticketId","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TicketsMsgServiceSubmitTicketSignatureBody"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/v1SubmitTicketSignatureResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"SubmitTicketSignature sends the signature of a typed data action the ticket is waiting on","tags":["TicketsMsgService"]}}}}
```

## GetUserTransactions returns the list of available user transactions for a ticket based on its current state

> Transactions the end user still needs to sign and submit themselves\
> For admin-side transactions see GetAdminTransactions

```json
{"openapi":"3.0.0","info":{"title":"KiiChain Pay Backend","version":"v1"},"tags":[{"description":"Queries (read operations)","name":"TicketsQueryService"}],"servers":[{"description":"Production","url":"https://backend.pay.kiichain.io"},{"description":"Staging","url":"https://backend.pay.staging.kiichain.io"}],"security":[{"ApiKeyAuth":["tickets.tickets.read"]},{"BearerAuth":["tickets.tickets.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":{"v1GetUserTransactionsResponse":{"properties":{"transactions":{"additionalProperties":{"$ref":"#/components/schemas/v1AdminTransactionList"},"title":"Map of transaction group key to list of transactions the user can submit","type":"object"}},"required":["transactions"],"title":"GetUserTransactionsResponse is the response structure for the GetUserTransactions endpoint","type":"object"},"v1AdminTransactionList":{"properties":{"transactions":{"items":{"$ref":"#/components/schemas/blockchainV1Transaction"},"type":"array"}},"required":["transactions"],"title":"AdminTransactionList wraps a repeated list of blockchain transactions","type":"object"},"blockchainV1Transaction":{"properties":{"evm":{"$ref":"#/components/schemas/v1EVMTransaction"},"typedData":{"$ref":"#/components/schemas/v1EVMTypedData"}},"title":"Transaction wraps the user actions to build an ordered list, either a transaction to send\nor a typed data to sign","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"},"v1EVMTypedData":{"description":"Sign typed_data as is with eth_signTypedData_v4 from the signer wallet, then send the\nsignature back with SubmitTicketSignature","properties":{"chainId":{"title":"chain_id is the ID of the network the typed data is bound to","type":"string"},"metadata":{"additionalProperties":{"type":"string"},"title":"metadata is the map of additional information sent with the typed data","type":"object"},"signer":{"title":"signer is the address that must sign the typed data","type":"string"},"type":{"title":"type is what is being signed, the accepted values are: permit","type":"string"},"typedData":{"title":"typed_data is the full EIP-712 JSON (types, domain, primaryType and message)","type":"string"}},"required":["type","chainId","signer","typedData"],"title":"EVMTypedData is an EIP-712 message the user signs instead of sending a transaction","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":{"/tickets/v1/{ticketId}/user_txs":{"get":{"description":"Transactions the end user still needs to sign and submit themselves\nFor admin-side transactions see GetAdminTransactions","operationId":"TicketsQueryService_GetUserTransactions","parameters":[{"description":"The ID of the ticket","in":"path","name":"ticketId","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/v1GetUserTransactionsResponse"}}},"description":"A successful response."},"default":{"$ref":"#/components/responses/AppError"}},"summary":"GetUserTransactions returns the list of available user transactions for a ticket based on its current state","tags":["TicketsQueryService"]}}}}
```


---

# 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 by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

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

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
