Laso Finance
Server Details
Spend USDC in the real world: prepaid cards, gift cards, push-to-card, and bank payouts.
- Status
- Healthy
- Uptime
- 99.6% over 19 days
- OAuth
- Works in Glama
- Last Tested
- Transport
- Streamable HTTP · MCP 2025-11-25
- URL
TDQS
Scored across 68 tools
The set covers many financial rails—Venmo/PayPal, ACH, push-to-card, wallet transfers, x402, and several card products—so similar 'send', 'order', and 'delete' tools exist across domains. Descriptions clarify boundaries, but an agent could still confuse send_payment vs send_bank_payment, or the various recipient-list and delete-recipient tools.
Almost all tools use snake_case with a predictable verb_noun shape (get_, list_, create_, delete_, update_, send_, search_, order_). A few names deviate slightly, such as agent_wallet_transfer and push_to_card, but the convention remains readable overall.
68 tools is extreme for a single server, far beyond the 25+ threshold for 'too many'. Even though Laso Finance is a broad platform, the surface is fragmented into many narrow tools that could be consolidated.
The surface covers onboarding, auth, wallet funding, banking profiles/recipients/transactions, multiple card lifecycles, payments, withdrawals, webhooks, and support/docs. Core CRUD and lifecycle operations are present across nearly every domain, with no obvious dead ends.
Available Tools
68 toolsadd_banking_destinationAInspect
Attach bank details to a recipient
Attaches a bank account or crypto address to a recipient and returns the destination_id that /send-bank-payment pays out to.
Free.
| Name | Required | Description | Default |
|---|---|---|---|
| nickname | No | An optional label. The only field editable later, via `updateBankingDestination`. | |
| destination | Yes | The destination. For a US bank account: `destination_type: "fiat_us"` plus `aba_routing_number`, `account_number`, `account_type`, `account_holder_name`, and `bank_name`. Also supports `fiat_iban` and `crypto`. | |
| recipientId | Yes | The recipient from `createBankingRecipient`. | |
| recipientAddress | No | Sets the recipient's postal address before attaching the destination. Needed when the recipient was created name-only: bank destinations are rejected without one, so supplying it here avoids a dead end. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=false, destructiveHint=false, idempotentHint=false. The description adds useful behavioral context: it returns a `destination_id`, it supports multiple destination types (US bank, IBAN, crypto), and it warns that bank destinations are rejected without a postal address, so supplying `recipientAddress` avoids a dead end. This goes beyond the schema and annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded: the core action and return value appear in the first sentence, followed by a one-word 'Free.' and then a concise but informative parameter walkthrough. Every sentence earns its place; no fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has an output schema, so return values are covered. The description covers prerequisites, the dead-end scenario, and the editable field. It could be slightly more explicit about the exact structure of the `destination` object, but the schema already provides that. Overall, an agent has enough context to call this correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds meaning by explaining the relationship between `recipientId` and `createBankingRecipient`, clarifying that `nickname` is the only editable field later, and explaining why `recipientAddress` is needed (name-only recipients cause rejection). This adds value beyond the raw schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Attach' and the resource 'bank details to a recipient', and explicitly mentions the returned `destination_id` used by `/send-bank-payment`. This distinguishes it from sibling tools like `create_banking_recipient` (creates the recipient) and `update_banking_destination` (edits later).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains when to use this tool: to attach bank/crypto details to a recipient, and notes the prerequisite that a recipient must exist from `createBankingRecipient`. It also mentions the alternative `updateBankingDestination` for editing the nickname later. It doesn't explicitly say when NOT to use it, but the context is clear enough.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
agent_wallet_transferDestructiveInspect
Transfer USDC out of your managed agent wallet to any Solana address, or to any Base address by setting destination_network to base (bridged over CCTP, minimum 1 USDC, maximum your spend limit; the recipient receives the amount less a 0.01% bridge fee, usually within a minute). Use this to pay someone or to move funds to another wallet you control, including funding your own Base wallet (destination_network base, destination_address your base_wallet_address). It only sends from the Solana wallet: USDC in the Base wallet cannot be transferred back out, so move over only what you plan to spend.
| Name | Required | Description | Default |
|---|---|---|---|
| amount | Yes | Decimal USDC amount to send, as a string (e.g. 25.50). | |
| destination_address | Yes | Address to send the USDC to: a Solana address, or a 0x address when destination_network is base. | |
| destination_network | No | Chain the destination address is on (default solana). base delivers native USDC on Base. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
announce_connectionAInspect
Call this FIRST, before any other Laso tool. Your human is watching a screen that waits for you to connect; this is what resolves it, names you in their dashboard, and starts a session in their activity stream. Introduce yourself with agent_name and message. Also returns your wallet funding state, so it doubles as your setup check.
| Name | Required | Description | Default |
|---|---|---|---|
| message | No | A short greeting shown to your human, in your own words. Max 280 characters. | |
| agent_name | No | What to call you in your human's dashboard, e.g. Claude Code. Max 60 characters. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=false and destructiveHint=false. The description adds context about the side effects (starting a session, returning wallet funding state) which is not in annotations. However, it does not describe what happens if called again or whether it can be called multiple times, but idempotentHint=false already signals that. Overall it adds useful behavioral context without contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the critical instruction 'Call this FIRST'. Every sentence serves a purpose: the first explains what it does and when, the second mentions the extra return value. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with an output schema (not shown) and two well-documented parameters, the description fully covers the tool's role, timing, and return value. An agent can correctly invoke it as the first step without missing information.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and both parameters have descriptive text (message, agent_name with max lengths). The description mentions 'Introduce yourself with agent_name and message' but adds minimal new meaning beyond the schema. Baseline of 3 is appropriate since the schema already carries the parameter semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific purpose: resolving the connection screen, naming the agent in the dashboard, and starting a session. It clearly distinguishes itself from all sibling tools by positioning itself as the mandatory first call.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly instructs 'Call this FIRST, before any other Laso tool' and explains the context (human watching a waiting screen). It also notes it doubles as a setup check, giving the agent clear when-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
buy_with_saved_cardAInspect
Shop and pay with the holder's saved card
Buys from online merchants (Amazon, Walmart, Target, Best Buy, DoorDash and more) and pays with the card the account holder saved themselves (see GET /get-saved-cards). One conversation per purchase:
Send what to buy as
ask, in plain language. Passdelivery_addresson this first call when you know it.Relay
replyto the holder and send their answers back asaskwith the sameconversation_id, until acartcomes back.Show the holder the cart. Once they agree, send its
hashasconfirmwith theconversation_id. Nothing can be charged before this.The confirm answers
awaiting_approvalwith anapproval_url. Send it to your human; never open it yourself. They approve on their own device with their passkey. Then send the same confirm again to getorder_placed.
A turn runs against a live merchant and can take up to two minutes. This call waits about 45 seconds: a turn that finishes in time comes back complete (state: done); a slower one comes back as state: running with a turn_id to poll with GET /get-purchase-turn.
This route is free. The holder's own card pays the merchant, and no identity verification is needed.
| Name | Required | Description | Default |
|---|---|---|---|
| ask | No | What the holder wants, in plain language. Required unless confirming. | |
| confirm | No | A cart's `hash` from an earlier turn, to place exactly that cart. | |
| conversation_id | No | The conversation to continue. Required with `confirm`. | |
| delivery_address | No | Where to ship. Send it on the call that asks for the cart (a cart is bound to the address it was shown for) and on the confirm. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cart | No | The most recently shown cart. |
| note | No | The next step. |
| carts | No | Every open cart in the conversation, oldest first. |
| error | No | Present when `state` is `failed`. |
| reply | No | The shopping assistant's turn as prose, ready to show the holder. |
| state | No | `running` means the turn is still talking to the merchant; the fields below appear once it is `done`. One of: running, done, failed. |
| status | No | What to do next. `needs_input`: a question or a cart waiting on a confirm. `awaiting_approval`: send `approval_url` to the holder, then repeat the same confirm. `in_progress`: the order is already being placed; read `GET /get-purchase-conversation` instead of confirming again. `order_placed`. `declined`: see `decline_code`. `conflict`: nothing ran, see `error_code` and confirm the fresh cart's hash. Never branch on `reply`. One of: needs_input, awaiting_approval, in_progress, order_placed, declined, conflict. |
| catalog | No | The last product search. Empty on a turn that did not search again, so keep the previous one. |
| turn_id | No | This turn's id. Poll `GET /get-purchase-turn` with it while `state` is `running`. |
| order_id | No | Set when this turn placed an order. |
| unmatched | No | Things asked for that did not make it into a cart, with a reason. Show these rather than guessing from `reply`. |
| card_last4 | No | The saved card that paid, for naming it to the holder. |
| created_at | No | Milliseconds since the epoch. |
| error_code | No | On `conflict`: `cart_changed`, `turn_in_progress`, `delivery_address_changed`, or `delivery_address_bound_after_cart`. |
| approval_url | No | Send to the holder when `status` is `awaiting_approval`. Never open it yourself. |
| decline_code | No | The machine reason behind `declined`, e.g. `items_unavailable`. |
| charge_status | No | Whether money moved: `none`, `confirming`, `settled`, or `unknown` (do not retry; read the conversation). One of: none, confirming, settled, unknown, . |
| conversation_id | No | Send it back on every follow-up and on the confirm. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only cover the safety profile (non-read-only, non-idempotent, non-destructive); the description supplies the behavior that actually matters: the human approval gate via approval_url that the agent must never open, the ~45s wait versus a potential two-minute live turn with state: done/running plus turn_id polling, and that the route is free with no identity verification. This is behavior beyond what structured fields convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the purpose, then a numbered flow, then timing behavior; nearly every sentence carries operational weight. It is longer than strictly minimal, but the density of actionable detail (approval routing, poll fallback, free/no-KYC note) justifies most of the length.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a multi-turn live-merchant purchase flow with nested address input and an output schema, the description covers the conversation lifecycle, the approval gate, and the async return states, so an agent knows what to expect at each call and how to resume.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3, but the description adds real semantics: which parameter to send on which turn, that delivery_address should go on both the cart-requesting call and the confirm, and that the cart is bound to the address it was shown for. It does not restate the hash pattern or field formats, which the schema already covers.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Buys from online merchants ... and pays with the card the account holder saved'), names concrete merchants, and distinguishes itself from siblings like order_gift_card, order_intl_card, and send_payment by tying the payment to the holder's saved card. An agent can route to it without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit four-step when-and-how sequence, names the sibling route for prerequisites (GET /get-saved-cards) and the polling alternative (GET /get-purchase-turn), and states the precondition that nothing can be charged before confirm. Exclusions and conditions are all spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
cancel_intl_orderADestructiveInspect
Cancel a queued international card order
Cancel a previously queued international non-reloadable card order, as long as it has not yet been fulfilled by an admin (state=queued). The charged amount is credited back to the account balance.
| Name | Required | Description | Default |
|---|---|---|---|
| card_id | Yes | The card ID of the queued order to cancel (returned from `/order-intl-card`) |
Output Schema
| Name | Required | Description |
|---|---|---|
| card_id | No | |
| message | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, readOnly=false, and idempotent=false. The description adds valuable behavioral context beyond annotations: the charged amount is credited back to the account balance, and the state precondition (`state=queued`) is disclosed. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and front-loaded: first line states the action and resource, then the paragraph adds the eligibility condition and financial effect. Every sentence earns its place without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter mutation tool with a provided output schema and annotations covering destructiveness, the description covers the essential operational facts: what is cancelled, when it can be cancelled, and what happens to the charged amount. Nothing needed for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the only parameter, `card_id`, is already well documented by the schema with its source (`returned from /order-intl-card`). The description reinforces that it is a queued order ID but does not add significant meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Cancel') and resource ('queued international card order'), and adds the key qualifier 'non-reloadable' with the state constraint `state=queued`. This clearly distinguishes it from sibling ordering tools like `order_intl_card`, `order_card`, and `order_gift_card`.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when the tool applies: only for a previously queued order that has not yet been fulfilled by an admin. It gives a clear exclusion ('as long as it has not yet been fulfilled') but does not name an alternative tool or explain what to do if the condition is not met.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_agent_api_keyAInspect
Issue an API key
Issues a durable lasoak_ API key for the account. The raw key is returned once — only its hash is stored, so it cannot be retrieved again. Normally the human does this from the dashboard.
Free.
| Name | Required | Description | Default |
|---|---|---|---|
| label | No | A label to recognize the key by. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
It discloses important side-effect and security behavior beyond annotations: the raw key is shown once, only a hash is stored, and the key cannot be retrieved again. This substantially helps an agent reason about consequences, and it does not contradict the readOnly/destructive/idempotent hints.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded: the action appears first, followed by the critical one-time-raw-key caveat. The heading-like first sentence and 'Free.' are slightly redundant but not wasteful.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the single optional parameter, the presence of an output schema, and annotations, the description covers the essential operational facts: what is created, the credential-handling caveat, and normal human/dashboard context. It does not explain key lifecycle follow-ups, but that is not required for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The only parameter, label, is already fully described in the input schema ('A label to recognize the key by'), and the description adds no additional semantics about how the label behaves. With 100% schema coverage, baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: it issues a durable `lasoak_` API key for the account, and adds the distinguishing detail that the raw key is returned only once. It is not a tautology, though it does not explicitly name a sibling to differentiate from.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The only usage guidance is 'Normally the human does this from the dashboard,' which implies privileged/manual operation but gives no explicit when-to-use or when-not-to-use conditions. It does not mention alternatives like exchange_api_key or refresh_token.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_agent_walletIdempotentInspect
Create your managed agent wallets (one Solana wallet and one Base wallet per account; idempotent). Returns the Solana wallet as walletId and address, and the Base wallet as baseWalletId and baseAddress. An account created before Base support gets its Base wallet by calling this again. Fund the Solana address with USDC to pay for the paid tools; the Base wallet pays external x402 endpoints that settle in USDC on Base.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
create_banking_accountAInspect
Open an on-ramp or off-ramp account
Opens a banking rail. An on-ramp issues a virtual US bank account: dollars sent to it arrive as USDC in the managed wallet. An off-ramp pays out to a bank account you have registered, and is opened automatically by /send-bank-payment, so most agents never call this for one directly.
Free.
| Name | Required | Description | Default |
|---|---|---|---|
| rail | No | The payment rail for the account. | |
| asset | No | Crypto asset ticker, uppercase. | |
| networkId | No | On-ramp only. Defaults to Solana mainnet. | |
| accountType | Yes | Which rail to open. | |
| capabilities | No | On-ramp only. Bank rails to support. Defaults to ACH and wire. | |
| cryptoAddress | No | On-ramp only. Where the converted USDC should land. Defaults to the managed agent wallet. | |
| fiatDestinationId | No | Off-ramp only. The bank destination payouts go to, from `addBankingDestination`. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, destructiveHint=false, idempotentHint=false, so the description doesn't need to restate those. The description adds meaningful behavioral context: on-ramp issues a virtual US bank account and converts dollars to USDC in the managed wallet, off-ramp pays out to a registered bank account, and off-ramp is opened automatically by another tool. It also discloses that the tool is free. This goes beyond the annotations and helps the agent understand side effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a clear title, a short definition of each account type, and a note about when not to call it. Every sentence earns its place, and the most important distinction (on-ramp vs off-ramp) is front-loaded. The 'Free.' note is a minor extra but not wasteful.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the core behavior, the two modes, and the automatic off-ramp path, which is enough for an agent to decide whether to call it. The output schema exists, so return values don't need to be explained. It could mention prerequisites like needing a banking profile or KYC, but the schema and sibling tools (get_kyc_status, submit_banking_application) partially cover that context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents all 7 parameters. The description adds context for the two account types and mentions defaults (Solana mainnet, ACH and wire, managed agent wallet), which aligns with the schema. However, it doesn't add much beyond what the schema already says, so a baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool opens a banking rail and distinguishes between on-ramp and off-ramp accounts, explaining what each does. It names the specific resource (banking account) and the verb (open), and the title reinforces this. It also differentiates from siblings by noting off-ramp accounts are opened automatically by send-bank-payment, so most agents won't need to call this for off-ramp.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly explains when to use on-ramp vs off-ramp, and even tells agents they usually don't need to call this for off-ramp because send-bank-payment does it automatically. It also mentions the 'Free' pricing, which is a clear usage signal. This is strong guidance for an agent deciding whether to invoke this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_banking_profileAInspect
Create the banking profile
Opens the banking profile that all other banking calls hang off. Identity verification is required first; if the human has not verified, the reply carries kycRequired: true and a kycUrl to hand them. This is the only step an agent cannot complete itself. Retry once they finish.
Free.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only indicate it's not read-only, not idempotent, not destructive. The description adds crucial behavioral context: it's the only step an agent cannot complete itself, it returns kycRequired and kycUrl when verification is pending, and advises to retry after the human finishes. This goes well beyond annotations and is essential for the agent to handle correctly.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and front-loaded with the purpose and key prerequisite. The only blemish is the trailing 'Free.' sentence, which appears to be a stray or unrelated note and adds no value. This prevents a perfect score.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter tool with an output schema, the description fully covers what an agent needs: the purpose, the prerequisite, the failure mode (kycRequired), and the required human interaction. Nothing essential is missing. The output schema handles return values, so no further detail is needed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With zero parameters, the description has no parameter details to add. Per the rubric, the baseline is 4 for zero-parameter tools. The description appropriately focuses on preconditions and behavior instead of parameter semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool creates the banking profile and explains its role as the foundation for all other banking calls. It distinguishes itself from siblings like create_banking_account (accounts vs. profile) and get_banking_profile_status (status vs. creation). The verb-resource pairing is specific and unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies when to use it: before other banking calls, and it explicitly states the prerequisite (identity verification) and the action to take if verification is missing (hand the kycUrl to the human). However, it doesn't explicitly name alternatives or say when not to use it, such as checking if the profile already exists via get_banking_profile_status. This is a minor gap given the clear prerequisite and positioning.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_banking_recipientAInspect
Create a payout recipient
Creates a person or company money can be sent to. Bank details are attached separately with addBankingDestination.
Free.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | The recipient's name. | |
| address | No | The recipient's postal address. Required before a bank destination can be attached, so supplying it here avoids a second call. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false (write operation) and idempotentHint=false. The description adds 'Free' (a cost signal) but otherwise does not disclose potential failures, side effects, or prerequisites beyond what the schema provides. Since annotations cover the basic safety profile, this is adequate but not exceptional.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and well-structured: a title, a one-sentence definition, a key usage note pointing to the next step, and a cost indicator. No redundant information, and all sentences earn their place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple create operation with two parameters and a rich schema (100% coverage) and an output schema present, the description is sufficiently complete. It covers the main purpose, the next step (addBankingDestination), and a key prerequisite (address). It doesn't explain return values but the output schema presumably does.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema covers both parameters, and the description adds meaningful context: it explains that address is required before a bank destination can be attached, and supplying it here avoids a second call. This enhances understanding of the address parameter beyond the schema's basic description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool creates a payout recipient (a person or company) and differentiates it from attaching bank details by referencing addBankingDestination. This distinguishes it from sibling tools like add_banking_destination and delete_banking_recipient, making the purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context that bank details are attached separately via addBankingDestination, implying the correct sequence of use. However, it does not explicitly mention when not to use this tool or alternatives like update_payment_recipient, so it is slightly incomplete but still helpful.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_reloadable_cardAInspect
Create a reloadable card
Creates a reloadable card funded from the account holder's balance with the card issuer, and returns it. This is the same card the holder creates in the Laso dashboard, so an agent and a human end up with the same product.
The card is reusable by default (reusable: true): it stays open across charges until its limit is spent. Pass reusable: false for a single-use card that closes after its first approved charge.
This route is free — no x402 payment. The card draws on the account holder's own balance with the issuer, so Laso fronts nothing.
If the balance is short, this route answers 402. Fund it by sending USDC: GET /get-card-deposit-address returns the holder's own deposit address at the card issuer (USDC on Base only), and the balance credits within a couple of minutes. The holder can also top up with Apple or Google Pay in the dashboard.
Read the new card's number and CVV with /get-card-data?card_id=.... A card created here is Laso-issued, so its card_details come back directly — the approval step applies only to cards the holder created in a different app.
| Name | Required | Description | Default |
|---|---|---|---|
| reusable | No | Whether the card stays open across charges. Defaults to `true`; `false` closes it after the first approved charge. | |
| usd_amount | Yes | Amount in US dollars to load onto the card, minimum $1. Sent as dollars, not cents. |
Output Schema
| Name | Required | Description |
|---|---|---|
| card | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses far beyond the sparse annotations (readOnlyHint=false, destructiveHint=false): the route is free with no x402 payment, the 402 response when the balance is short, the funding path (USDC-on-Base deposit address with ~minutes credit, Apple/Google Pay top-up), and the behavior that created cards are Laso-issued so no approval step applies. Rich operational detail an agent needs before invoking.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well-organized with front-loaded essentials and effective bold callouts (reusable, this route is free, if the balance is short), but verbose: roughly seven sentences for a two-parameter create. Asides like the Apple/Google Pay dashboard top-up and the 'so an agent and a human end up with the same product' framing could be trimmed without losing decision-relevant content. Structured, but not tight.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Comprehensive for its complexity: an output schema exists (so return shape is covered), and the description handles error behavior (402 + funding remedy), payment cost, reusability, and follow-up reads via get-card-data. The only soft gap is that the 'approval step' for externally-created cards is referenced but never explained — minor in context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents both parameters (usd_amount as dollars-not-cents with $1 minimum; reusable defaulting true). The description adds narrative on the reusable semantics ('stays open across charges until its limit is spent', 'closes after its first approved charge') but this merely restates the schema meaning — no new syntax or format detail. Baseline 3 applies since the schema carries the load.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Creates a reloadable card funded from the account holder's balance') and grounds it in a concrete scenario — 'the same card the holder creates in the Laso dashboard.' It marks this as the free, balance-funded creation route, which distinguishes it from card siblings like order_card, fund_card_balance, and push_to_card without needing their schemas opened.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides strong context for when to use it: it's free (no x402), it mirrors the dashboard product, and it is the route for a Laso-issued card whose data comes back directly ('the approval step applies only to cards the holder created in a different app'). It names companion follow-ups (get-card-deposit-address, get-card-data) but never crisply names a sibling alternative and the trade-off for choosing it over order_card.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_saved_card_linkAInspect
Get a link for the holder to save their own card
Returns a single-use link where the account holder types a card they already own and locks it with their passkey. The card is encrypted on their device; Laso never sees the number.
Send the url to your human. Do not open it yourself. Saving a card is the holder's step, like identity verification: the page asks for the card and a passkey, with no account to create and no code to type.
Poll GET /get-saved-cards until the card appears. Each link works once and expires at expires_at; mint a new one if it lapses.
This route is free and needs no identity verification or prior setup: the holder's first saved card creates their card account.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | The single-use page where the holder saves their card. Send it to them. |
| note | No | How to hand the link over and what to poll. |
| expires_at | No | When the link stops working, in milliseconds since the epoch. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds substantial context beyond the annotations: single-use semantics (consistent with idempotentHint=false), expiry at expires_at, client-side encryption where Laso never sees the card number, and zero prerequisite setup. These are non-obvious behavioral traits an agent cannot infer from the annotation block.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the purpose, then bold callouts for the critical agent action and the polling loop, then prerequisites. Well ordered and mostly every sentence earns its place, though the aside comparing the page to identity verification is slightly more color than instruction.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return-value detail is delegated appropriately; the description still calls out url and expires_at to tie the polling instruction to a field. For a zero-parameter tool it covers the full agent workflow: how to deliver the link, what the holder does, how to detect completion, and what happens if the link lapses.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema is empty with zero parameters, so the baseline is 4. The description correctly implies no inputs are needed and instead surfaces the relevant return fields (url, expires_at), but there is no parameter semantics to add meaning to.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource — minting a single-use link that lets a holder save their own card — and elaborates on exactly what the link is for. An agent can distinguish it from get_saved_cards (listing existing cards) and buy_with_saved_card (spending) without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit operational guidance: send the url to the human rather than opening it, poll GET /get-saved-cards until the card appears, and re-mint if the link expires. It also states the route is free and needs no identity verification or prior setup. It stops short of explicitly contrasting this link flow against sibling link generators like get_auth_link or get_kyc_link, so it doesn't reach the full when/when-not/alternatives bar.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_address_book_entryADestructiveIdempotentInspect
Remove a saved recipient
The saved recipient names your human manages on their dashboard, so a request like "send $20 to the coffee vendor" can be resolved to an address instead of asking them for it.
Free.
It operates only on the authenticated account's own book — there is no user parameter to pass.
A name is a label, not an instruction. agentWalletTransfer takes an address and deliberately does not accept a name: a rename between your human asking and you sending would otherwise move money somewhere they did not intend. When you resolve a name to an address, say the address back to them before sending.
Removing an entry only forgets the name; it has no effect on past transfers to that address.
| Name | Required | Description | Default |
|---|---|---|---|
| address | No | The address to remove. |
Output Schema
| Name | Required | Description |
|---|---|---|
| address | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds valuable behavior beyond the annotations: deletion only forgets the name mapping, has no effect on past transfers, and cannot target another account's book. The name-is-not-an-instruction warning also prevents misuse. This is consistent with destructiveHint=true and idempotentHint=true.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The action and scope are front-loaded, but the description includes off-topic material — 'Free.' and the extended agentWalletTransfer name-vs-address warning — that is not needed to invoke a delete. A tighter version would keep the own-book scope and no-past-transfer effect.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter delete tool with an output schema and annotations covering destructiveness and idempotence, the description covers scope, effect on history, and account limitations. Nothing needed to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already documents the single address parameter with 100% coverage, so the baseline is 3. The description adds context that no user parameter is needed, but it does not detail address format or requiredness.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence gives a specific action and object ('Remove a saved recipient'), and the rest ties it clearly to the address book ('the authenticated account's own book') rather than banking or payment recipients. This clearly separates it from sibling delete tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It identifies the target context — the human-managed address book — and explicitly notes it operates only on the authenticated account's own book with no user parameter. It doesn't name alternative tools or exclusion cases, so it stops short of full routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_banking_recipientADestructiveIdempotentInspect
Delete a recipient
Deletes a recipient, its destinations, and any off-ramp account that paid out to it. Irreversible.
Free.
| Name | Required | Description | Default |
|---|---|---|---|
| recipientId | Yes | The recipient to delete. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds significant behavioral context beyond the annotations: it discloses cascade deletion (destinations and off-ramp accounts), irreversibility, and that the operation is free. Annotations already flag destructiveHint=true, but the description enriches this with specifics that matter for agent decision-making, and it does not contradict any annotation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is exceptionally concise—two sentences plus a short paragraph—yet it front-loads the core action ('Delete a recipient') and packs in essential behavioral details (cascade, irreversibility, cost) without any fluff. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a low-complexity delete tool with one parameter and an output schema, the description covers the key behavioral aspects an agent needs: what gets deleted, reversibility, and cost. It does not mention prerequisites like authentication, but that is implicit for API tools and not a significant gap here.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema provides 100% coverage for the single parameter (recipientId) with a clear description. The tool description adds no additional parameter-level meaning, so it stays at the baseline of 3 where the schema carries the semantic load.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states the verb 'Delete' and the resource 'recipient', and goes further to specify the scope: it deletes the recipient, its destinations, and any off-ramp account that paid out to it. This distinguishes it from sibling delete tools like delete_payment_recipient and delete_address_book_entry, which target different resource types.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage—use it to delete a banking recipient—but it does not explicitly mention alternatives or provide when-not guidance. While the sibling list includes similar delete tools, no exclusion criteria are given, so an agent must infer the correct choice based on the resource type.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_payment_recipientADestructiveIdempotentInspect
Remove a saved recipient (free)
Removes a saved Venmo or PayPal recipient. Payment history is kept; only the saved entry stops being offered.
This is not reversible through the API, so prefer archiving (POST /payment-recipients with archived: true) when the account owner may want the recipient back, and confirm before removing someone they did not ask you to remove.
platform and recipient_id may be sent in the JSON body or the query string.
| Name | Required | Description | Default |
|---|---|---|---|
| platform | No | Required unless sent in the body. | |
| recipient_id | No | Required unless sent in the body. The entry's `recipient_id` from `GET /payment-recipients` (an opaque id, not the phone number or email). |
Output Schema
| Name | Required | Description |
|---|---|---|
| deleted | No | |
| user_id | No | |
| recipient_id | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the destructiveHint annotation, the description adds meaningful behavior: the action is not reversible through the API, payment history is kept, only the saved entry stops being offered, and parameters may go in body or query string. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well organized and efficient: it states the action, the irreversible consequence, the preferred alternative, and the transport option. Slight redundancy between the opening title and first sentence, but every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter deletion tool with an output schema, the description covers all essential operational facts: irreversibility, history preservation, alternative archiving behavior, consent caution, and body/query flexibility. Nothing critical is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds genuinely useful transport semantics by stating that `platform` and `recipient_id` may be sent in the JSON body or query string, and clarifies that `recipient_id` is the opaque id from `GET /payment-recipients`, not the phone number or email.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource: 'Removes a saved Venmo or PayPal recipient.' It clearly distinguishes this from sibling tools like delete_banking_recipient by naming the payment recipient scope and noting that payment history is preserved.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly tells the agent when to prefer an alternative: archive via `POST /payment-recipients` with `archived: true` when the owner may want the recipient back. It also instructs to confirm before removing someone the owner did not ask to remove, providing clear selection guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_webhookADestructiveIdempotentInspect
Delete the notification webhook (free)
Removes the calling wallet's webhook registration. Notifications keep flowing to the user's other channels (push, SMS, Telegram, in-app); only the webhook deliveries stop. The account owner is notified of the removal.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| deleted | No | False when there was no registration to delete. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate destructiveHint=true and idempotentHint=true, so the description correctly aligns. It adds valuable context: that other notification channels continue, and the account owner is notified. No contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and well-structured: a clear title line, then a brief explanation of scope and side effects. Every sentence adds value, and the key point (only webhook stops) is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is simple with no parameters and an output schema exists (not shown but indicated). The description covers the main behavioral implications: removal scope and notification to owner. It could mention the return value or idempotency implications, but overall it's complete for an agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are zero parameters, so schema coverage is trivially 100%. The description doesn't need to explain params; it correctly focuses on behavior. This is a baseline of 4 for parameter-free tools.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'delete' and resource 'webhook', and specifies it removes the calling wallet's webhook registration. It distinguishes itself from sibling tools like register_webhook and get_webhook by focusing on removal.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context on when to use it: to remove the webhook for the calling wallet. However, it does not explicitly state when NOT to use it or mention alternatives, but the distinction from get/register webhook is implicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
exchange_api_keyAInspect
Exchange an API key for a session
Exchanges a durable lasoak_ API key for a short-lived id_token (one hour) plus a refresh_token, and returns an auth_url to hand your human so they can watch what you do. This is the first call an agent makes. The reply's id_token authenticates every other endpoint here.
If you have no key, your human creates one at https://laso.finance/agent/dashboard — there is no other way to obtain one.
Free.
| Name | Required | Description | Default |
|---|---|---|---|
| api_key | Yes | Your `lasoak_` API key. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare `readOnlyHint: false` and `destructiveHint: false`, but the description adds important context: it is a session-exchange that produces short-lived credentials (one hour), returns an `auth_url` so a human can monitor activity, and is a prerequisite for authenticating other endpoints. This is more informative than the bare annotations. A minor gap is that it does not explicitly state side effects like invalidating an older session, but this is not a strong deduction given the annotations are already present.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact, front-loads the core exchange mechanism, states the token duration, the auth_url purpose, prerequisites, and fallback path, all in three short paragraphs. No unnecessary detail; the format 'Free.' is an oddity but does not hurt clarity. The wording is direct and every sentence adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the essential context: what is exchanged, what the tokens do, how long they last, the human-facing `auth_url`, and the fallback if no key exists. The output schema is present, so return values don't need to be elaborated. A slight deduction: the description does not clarify behavior on invalid or expired keys, but given the presence of a clear prerequisite and output schema, this is not a major shortfall.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 100% schema description coverage and a single required `api_key` parameter, the schema fully explains the parameter. The description enriches it by clarifying the expected format (`lasoak_`) and that the key is durable and must be created by a human if absent. That is valuable additional semantics beyond the bare schema, though the schema already uses the same `lasoak_` example.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool exchanges a durable `lasoak_` API key for a short-lived `id_token` and `refresh_token`, and names the returned `auth_url` for human oversight. It also positions this as the first call an agent makes and that the `id_token` authenticates every other endpoint, which sharply distinguishes its purpose from other endpoints like `refresh_token` or `create_agent_api_key`.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says this is the first call an agent makes, that the resulting `id_token` authenticates all other endpoints, and that the only alternative to having a key is having the human create one at the dashboard URL. This tells an agent when to use this tool, that it must precede other calls, and what to do if no key is available.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fund_card_balanceDestructiveInspect
Load a reloadable card balance
Pay USDC to load the account holder's reloadable card balance at the card issuer.
Why this exists: the card issuer only accepts USDC on Base, and a Laso managed agent wallet holds USDC on Solana. Pay this route from either chain and Laso bridges the payment to your own deposit address at the issuer over Circle's CCTP, which burns on the source chain and mints native USDC on Base.
Price: exactly the amount you are loading, and exactly that amount is credited to the balance. Loading $50 costs $50 and puts $50 on the card. Laso covers Circle's bridging fee by burning slightly more than requested.
A linked card issuer account is required. The account holder sets it up at https://laso.finance/agent/dashboard/verified/card.
Delivery starts once your payment settles. The response confirms the payment and returns a top_up_id; the transfer to your card balance follows and usually lands in under a minute. A payment made on Base is already on the issuer's chain, so it is forwarded without a bridge. Watch the top-up under top_ups in GET /list-card-transactions, where status moves paid → bridging → delivered → credited and the transaction hash behind each leg appears as it lands, or poll GET /get-card-deposit-address until balance reflects it.
Follow with POST /create-reloadable-card to create a card against the balance once it has arrived.
If the top-up's status becomes failed, nothing is stranded: the USDC you paid has credited your Laso account balance. Retry, or recover it with POST /withdraw.
PAID ROUTE (5-10000 USD): the x402 USDC price is paid automatically from your managed agent wallet. Make sure the wallet exists and is funded first (get_agent_wallet).
| Name | Required | Description | Default |
|---|---|---|---|
| amount | Yes | USD of USDC to load onto the card balance (min $5, max $10,000). The x402 price equals this amount; Laso absorbs the bridge cost. |
Output Schema
| Name | Required | Description |
|---|---|---|
| note | No | |
| asset | No | |
| status | No | Always `paid` here: the payment settled and delivery to the card balance has started. Follow the later states in `GET /list-card-transactions`. |
| network | No | |
| top_up_id | No | Identifies this top-up under `top_ups` in `GET /list-card-transactions`. |
| funded_usd | No | USD loaded onto the card balance. |
| deposit_address | No | The account holder's own deposit address at the card issuer, on Base. |
| payment_network | No | The chain the payment settled on: `solana` (bridged to Base over CCTP) or `base` (forwarded directly). |
get_account_balanceARead-onlyIdempotentInspect
Get account balance
Returns the current account balance and total deposits for the authenticated user.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| balance | No | Current available balance in USD |
| user_id | No | The user's ID (lowercase wallet address) |
| total_deposits | No | Total lifetime deposits in USD |
| created_timestamp | No | |
| created_timestamp_readable | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, covering the safety profile. The description adds that it returns 'total deposits' in addition to balance, which is useful context beyond annotations. However, it doesn't disclose any other behavioral traits like authentication requirements or rate limits, which is acceptable given the simple read-only nature.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise, using two short sentences. The primary action and return details are front-loaded, with no wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has an output schema (not shown) and zero parameters, so the description only needs to convey the tool's purpose and scope. It states it's for the 'authenticated user' and covers the key outputs. It might have been clearer to specify 'banking account balance' to avoid ambiguity with wallet or card balances, but this is a minor gap given the sibling context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are no parameters, so the baseline is 4. The description doesn't need to elaborate on parameter semantics since none exist, and the schema coverage is trivially 100%.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Get account balance' and specifies it returns 'current account balance and total deposits for the authenticated user.' This is specific and distinguishes it from other get_* tools that target different resources like wallets or cards, though it doesn't explicitly name alternatives.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives such as get_agent_wallet or get_card_deposit_address. It simply states what it does without context on selection criteria or exclusions, leaving the agent to infer usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_agent_spend_limitARead-onlyIdempotentInspect
Read the per-payment spend limit
Returns the maximum the account owner allows for any single payment from the managed wallet: maxPerPaymentUsdc, plus the min, max, and default bounds it can be set within, all in whole USDC. The limit defaults to $1,000 and ranges from $1 to $50,000. It applies to every payment agentX402Pay makes, Laso routes and external url endpoints alike.
Check an amount against this before attempting a payment rather than waiting to be refused. Compare the fee-inclusive total, since fees are added on top of the amount you request. Read-only to an agent: only the account owner can change the limit, from the dashboard. If a payment would exceed it, do not split it into smaller payments. Stop and tell your human.
Free.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| max | No | The highest value the owner can set. |
| min | No | The lowest value the owner can set. |
| default | No | The limit that applies when the owner has never set one. |
| maxPerPaymentUsdc | No | The most a single payment may total, fees included. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark it read-only and idempotent, but the description adds substantial behavioral value: the default and allowed range, universal applicability to all payment routes, fee-inclusive comparison, owner-only modification, and the explicit 'do not split' guidance. This is exactly the kind of context an agent needs beyond the annotation hints.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is more verbose than the shortest possible definition, but nearly every sentence adds operational value: bounds, applicability, fee handling, access restrictions, and the no-split rule. Slight redundancy exists with the title in the first sentence and the standalone 'Free.', so it earns a 4 rather than a 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Backed by an output schema and no parameters, the description fully covers what the agent needs to know: return values, numeric bounds, payment scope, pre-payment checks, ownership, and failure behavior. Nothing necessary for correct invocation or interpretation is left to inference.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With zero parameters and 100% schema description coverage, there is nothing for the description to add about inputs. The baseline of 4 applies; the description correctly avoids inventing parameter details and instead focuses on explaining the read-only output and decision context.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with the specific verb-resource pair 'Read the per-payment spend limit' and then explains exactly what is returned: maxPerPaymentUsdc plus min/max/default bounds. This clearly distinguishes it from wallet-balance or account-status siblings in the tool list.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit operational guidance: check this limit before attempting a payment, compare the fee-inclusive total, and never split an over-limit payment. It also states who can change the limit, making it clear this is a pre-payment consultation tool rather than something that can alter limits.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_agent_walletRead-onlyIdempotentInspect
Get your managed agent wallet: whether one exists, its Solana address, its USDC balance, and whether it needs funding. Paid tools draw from this wallet, so check it before your first paid call. Fund it by sending USDC (Solana) to wallet_address. Also returns base_wallet_address and base_balance_usdc for the Base wallet that pays external x402 endpoints settling in USDC on Base (both null until create_agent_wallet has provisioned it; base_balance_usdc is read live from chain and is also null when it could not be read). wallet_address, balance_usdc and needs_funding describe the Solana wallet only.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
get_auth_linkARead-onlyIdempotentInspect
Get a login link for the web dashboard
Returns a URL that a human can open in a browser to log in to the Laso Finance web dashboard as the authenticated user. Useful for humans who want to see what their AI agent has been doing (view cards, transactions, balances, etc.).
The URL carries a short single-use login code rather than a long token, so relay it to your human verbatim; it passes through tool-output credential filters intact. Do not fetch or open the URL yourself: redeeming the code consumes the human's login.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| user_id | No | The authenticated user's ID (wallet address) |
| auth_url | No | URL to open in a browser to log in to the Laso Finance dashboard. Carries a short single-use login code. |
| expires_in | No | Seconds until the login code expires |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnlyHint, idempotentHint, destructiveHint), the description discloses critical behavioral details: the URL carries a short single-use login code, it passes through credential filters intact, and fetching/opening the URL would consume the human's login. This is exactly the kind of non-obvious behavior an agent needs to know.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose in the first sentence, then adds essential usage and security context. Every sentence earns its place: return value, use case, credential-filter behavior, and the explicit warning not to fetch the URL. No redundant or filler content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter tool with a rich annotation set and an output schema, the description covers everything an agent needs: what the tool returns, why it is useful, how to relay the URL, and a critical behavioral warning. There are no meaningful gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so parameter semantics are trivially satisfied. The description correctly adds no parameter-specific details because none exist; the baseline of 4 applies given the empty schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Get a login link for the web dashboard.' It clearly distinguishes this from sibling tools like get_kyc_link by specifying that the link logs the human into the Laso Finance web dashboard as the authenticated user, and it states the purpose ('see what their AI agent has been doing').
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives a clear use case: 'Useful for humans who want to see what their AI agent has been doing (view cards, transactions, balances, etc.).' It does not explicitly name alternative tools or state when not to use it, but the context is unambiguous enough for an agent to select this tool appropriately.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_banking_applicationARead-onlyIdempotentInspect
Read the banking application
Reads what the application still needs. Returns ready (whether it can be submitted), applicationStatus, and the outstanding questions. The identity answers carry over from verification; what remains are non-identity questions such as employment status and source of funds, which an agent can answer itself.
Free.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, so the description does not need to repeat those. It adds value by explaining the output fields (ready, applicationStatus, outstanding questions) and the nuance that identity answers carry over from verification, which is behavioral context beyond the annotations. No contradiction exists.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is structured with a clear first line that summarizes the purpose, followed by a concise explanation of return values and context. It is slightly verbose with the trailing 'Free.' which adds little value, but the core message is front-loaded and efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only, zero-parameter tool with an output schema, the description is highly complete. It explains what the tool returns, clarifies that identity answers are inherited, and describes the nature of remaining questions. No critical information for an agent to invoke the tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so there is nothing to explain. Per the calibration rule, 0 parameters earns a baseline score of 4. The description does not need to add parameter details since there are none.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states that the tool reads the banking application and returns readiness, status, and outstanding questions. It distinguishes itself from update/submit siblings by being a read operation, but it does not explicitly name any alternative tools. The verb 'Read' and the resource 'banking application' are specific and unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage after verification to discover non-identity questions, but it does not explicitly state when to use this tool versus others like submit_banking_application or update_banking_application_details. It provides context about what remains to be answered, but lacks direct guidance on alternatives or exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_banking_profile_statusARead-onlyIdempotentInspect
Check the banking profile status
Reads the current state of the banking profile: whether it exists, and where its application stands.
Free.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, so the safety profile is covered. The description adds useful context by specifying that the tool reports existence and application stage, and it also adds the note 'Free.' There is no contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is appropriately short and front-loaded. The opening line repeats the title almost verbatim, and 'Free.' is a minor extra, but the overall length is well controlled and the core behavior is stated in one sentence.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, read-only status tool with an output schema, the description provides sufficient context: it states what resource is being read and what aspect of its state is returned. Nothing essential for correct invocation appears to be missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has zero propertiesanding 100% schema description coverage, so there are no parameter semantics to explain. The description instead indicates the kind of information returned, which helps the agent interpret the output for a parameterless call.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description identifies a specific verb ('Reads') and resource ('banking profile') and clarifies what is returned: whether the profile exists and where its application stands. It is clear and easy to distinguish from creation/submission siblings, though it does not explicitly contrast with get_banking_application or other related status tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly establishes the use case: call this when you need to know the current state of the banking profile. It does not explicitly name alternatives or provide exclusion guidance, but the context is unambiguous and not misleading.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_banking_transactionARead-onlyIdempotentInspect
Read one transaction
Reads a single banking transaction — an on-ramp arriving or an off-ramp paying out — with its normalized status.
Free.
| Name | Required | Description | Default |
|---|---|---|---|
| transactionId | Yes | The transaction to read. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already carry readOnlyHint, idempotentHint, and destructiveHint, so the description does not need to restate safety behavior. It adds useful context beyond those annotations: the transaction can be an on-ramp arriving or off-ramp paying out, it returns a normalized status, and it is free. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three short sentences with no filler. The key action and scope are front-loaded, and the extra details (on-ramp/off-ramp, normalized status, free) each add value without bloating the text.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a low-complexity single-parameter read tool with an output schema and strong safety annotations, the description is complete. It communicates what the transaction represents, the status normalization, and the cost, so an agent has enough context to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema fully documents transactionId (100% coverage) with 'The transaction to read.' The description does not add additional parameter details such as expected format or how to obtain the ID, but the schema carries the necessary semantic weight. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Reads a single banking transaction') and a clear resource, explicitly narrowing the scope to one transaction as opposed to a list. The on-ramp/off-ramp clarification also disambiguates the transaction types covered, and the singular framing distinguishes it from sibling list_banking_transactions.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The context is clear: use this to fetch one banking transaction. However, it never explicitly names alternatives such as list_banking_transactions for multiple transactions, nor does it state when not to use this tool. Usage is implied rather than spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_card_dataARead-onlyIdempotentInspect
Get card details
Returns the current status and details of card orders. If card_id is provided, returns a single card, looked up across U.S. non-reloadable, international non-reloadable, and reloadable cards. If omitted, returns all cards of the given card_type for the authenticated user; card_type defaults to Non-Reloadable U.S. when omitted, so existing callers see unchanged behavior. Pass card_type=Non-Reloadable International to list international cards, or card_type=Reloadable to list reloadable cards.
For U.S. non-reloadable cards, details take ~7-10 seconds to become available after ordering; poll every 2-3 seconds until status is "ready", then read card_details. For international non-reloadable cards, the order is queued until an admin fulfills it (typically within 24 hours), after which card_details is populated.
For international cards, the card_id returned by /order-intl-card is a queue id. After admin fulfillment, the issuer's transaction id becomes the new card_id and the original queue id is preserved on the card as queued_order_card_id. You can keep polling /get-card-data?card_id=<original-queue-id> and it will resolve to the fulfilled card.
Reloadable cards are a separate product, set up by the account holder in the Laso dashboard rather than ordered through this API. They are reusable (a multi_use card stays open across charges until its limit is spent) and can be topped up, unlike the single-load non-reloadable cards. Listing them returns balance, spend_limit, last4, expiry, and reusable. If the wallet has no card issuer account linked, the list is empty and a note explains how the holder sets one up.
Reading a reloadable card's number and CVV is gated by the card issuer, and which gate applies depends on who issued it. Request the card by card_id; the response carries exactly one of three fields. card_details is the normal result for a card created through /create-reloadable-card, which Laso issues on the holder's behalf and can read for them directly — no approval step is involved. details_approval with status: "pending" and an approval_id appears only for a card the holder created in a DIFFERENT app: the issuer has emailed them an approve/deny link, and once they approve you retry as GET /get-card-data?card_id=<CARD_ID>&approval_id=<APPROVAL_ID> to receive card_details. details_error means the issuer could not return the number; retry shortly, and if it persists the holder can read the card in the dashboard. Spend the card by entering its number, expiry, and CVV at the merchant's checkout. billing_address is null on these cards and always will be — the issuer holds no billing address for a card. If a merchant requires one, use the address the account holder gave at identity verification (ask them; do not guess), since these cards are AVS-checked against it and a mismatch is the most common decline on a card that has funds. A card with reusable: true stays open after an approved charge and can be spent again up to its remaining balance; a charge larger than the balance is declined in full, as there are no partial approvals.
| Name | Required | Description | Default |
|---|---|---|---|
| card_id | No | The card ID returned from `/get-card` or `/order-intl-card`, or a reloadable card's id from `card_type=Reloadable`. Looked up across all three card types. If omitted, returns all cards of `card_type`. | |
| card_type | No | When listing all cards (no `card_id`), filters by card type. Defaults to `Non-Reloadable U.S.` if omitted (preserves existing client behavior). Pass `Non-Reloadable International` to list international cards, or `Reloadable` to list reloadable cards. | Non-Reloadable U.S. |
| approval_id | No | Reloadable cards only, and only for a card the account holder created in a DIFFERENT app: pass the approval_id from a prior details_approval response once they have approved it. Cards created through /create-reloadable-card are Laso-issued and never require this. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds rich behavioral context beyond the annotations. . The readOnlyHint=true and idempotentHint=true annotations are consistent with the description's read-only nature, and the description elaborates on the behavior of polling, approval gates, and data availability windows, which are not inferable from the annotations alone.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but every section is purposeful and necessary for correct operation. It is structured with clear paragraphs for each card type and edge cases. The most critical usage information (how to poll) is placed early, and the response format is not over-explained since an output schema exists. No redundant sentences.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (three card types, approval gates, polling behavior, and a complex output schema), the description is thorough. It covers all necessary conditions for successful invocation, including edge cases like missing billing_address and approval flows. The output schema exists, so the description doesn't need to enumerate return values. It is complete for an agent to use correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema description coverage is 100%, so parameters are well documented in the schema. The description adds value by providing additional context on how parameters interact (e.g., card_id lookup across all types, approval_id only for certain cards), but the schema already defines their basic semantics. The baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: to get card details and status. It specifies the resource (cards), the action (get), and differentiates between single card lookup and listing by card type. It also distinguishes from siblings like order_card and order_intl_card by describing the retrieval of card data, not creation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit guidance on when to use this tool versus alternatives, such as mentioning that reloadable cards are set up in the dashboard rather than ordered through the API. It explains the conditions for using card_id versus card_type, and how to handle different card types. It also clarifies when to use approval_id and how to poll for updates, which is critical for correct usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_card_deposit_addressARead-onlyIdempotentInspect
Get the reloadable card deposit address
Returns the account holder's own USDC deposit address at the card issuer, and the balance currently on it. This is how an agent funds a reloadable card balance with crypto.
Funding is user-funded: the address belongs to the account holder, so USDC sent to it credits their balance and funds their cards. The issuer provisions the address on first read, so simply calling this creates it.
Base only. The address takes USDC on Base. USDC sent on another chain is unrecoverable. A Laso managed agent wallet holds USDC on Solana, so fund from a wallet that holds USDC on Base rather than transferring straight from a managed wallet.
Deposits usually confirm within a couple of minutes. Poll this endpoint until balance reflects the deposit, then call POST /create-reloadable-card.
The address is stable per holder, but read it through this endpoint rather than caching it: the issuer is the only authority on it.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| note | No | Chain warning and the next step. |
| asset | No | The asset the address accepts. Always `USDC`. |
| address | No | The holder's own USDC receiving address at the card issuer. |
| balance | No | Dollars currently on the card balance, or `null` when the issuer cannot read it (which is not the same as zero). |
| network | No | The chain the address accepts. Always `base`. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool as read-only, idempotent, and non-destructive, and the description adds significant behavioral context beyond that: the issuer provisions the address on first read so calling creates it, deposits typically confirm within minutes, the address is stable per holder, and it should be read fresh rather than cached. These are valuable operational details not present in the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Although the description is longer than typical, every paragraph earns its place: purpose, funding semantics, chain constraint, polling workflow, and caching guidance. The content is front-loaded with the main purpose and organized with bolded key points, with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the complete invocation context: why to call it, what it returns, the one-time provisioning side effect, the critical chain restriction, expected timing, confirmation polling, and the next step. With an output schema also present to define the return shape, nothing an agent needs to call and use this tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters and schema description coverage is trivially 100%, so there is nothing for the description to clarify about inputs. This matches the baseline for a parameterless tool; no additional parameter-level semantics are needed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific operation: retrieve the account holder's USDC deposit address and current balance for a reloadable card. It also articulates the tool's unique role clearly ('This is how an agent funds a reloadable card balance with crypto'), which distinguishes it from the many card and payment siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly says when to use this tool: to fund a reloadable card balance with crypto. It gives a concrete workflow—poll until balance confirms, then call POST /create-reloadable-card—and provides an explicit exclusion: fund from a wallet holding USDC on Base rather than transferring from a Solana-managed wallet, with a warning that other chains are unrecoverable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_kyc_linkARead-onlyIdempotentInspect
Get a KYC verification link (optional)
KYC is optional. It is only needed for certain features such as Venmo/PayPal payouts via /send-payment, and may be used for additional controls in the future. If you are not using those features, you can ignore the verification endpoints.
Returns a one-time identity-verification link (kyc_url) for the calling wallet. Open it (or hand it to the wallet owner) to complete verification. The typical flow is: call /get-kyc-status, and only if kyc_verified is false call this to get a link, complete it, then proceed to /send-payment.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| kyc_url | No | One-time URL to open to complete identity verification. |
| user_id | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false. The description adds useful behavioral context beyond that: the link is one-time, meant to be opened or handed to the wallet owner, and is part of a larger verification flow. No contradictions with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is appropriately sized and well-structured, front-loading the optional nature of KYC and then explaining the flow. A minor redundancy exists in repeating that KYC is optional, but overall each section earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema exists, the annotations cover safety/idempotency, and there are no parameters, the description is complete. It explains why the tool exists, when to use it, what it returns, and how it fits with `get-kyc-status` and `send-payment`.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters and schema description coverage is 100%, so the description does not need to explain parameters. The baseline is therefore strong, and the description correctly focuses on behavior and flow rather than parameter details.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool gets a one-time identity-verification link (`kyc_url`) for the calling wallet, with the explicit verb 'Get' and specific resource. It also differentiates itself from related endpoints like `get-kyc-status` by describing the verification flow.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly says KYC is optional and only needed for certain features such as Venmo/PayPal payouts via `/send-payment`. It also prescribes a clear conditional flow: call `/get-kyc-status` first, and only call this if `kyc_verified` is `false`. This gives strong when-to-use and when-not-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_kyc_statusARead-onlyIdempotentInspect
Get KYC verification status (optional)
KYC is optional. Most endpoints (cards, gift cards, push-to-card, account balance, withdrawals) do not require verification. It is only needed for certain features such as Venmo/PayPal payouts via /send-payment, and may be used for additional controls in the future. If you are not using those features, you can ignore the verification endpoints entirely.
Returns the calling wallet's cached KYC verification status. Use this as a free pre-flight check before paying for /send-payment: if kyc_verified is true the payout will go through. If it is false, don't call /send-payment yet — that call would not send the payout (it returns kyc_required and a kyc_url), and the USDC you paid would just land in your account balance, recoverable with POST /withdraw. To start verification when not verified, call /get-kyc-link.
This reads the cached status kept up to date by the verification webhook; it does not start verification or return a verification link.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| user_id | No | |
| kyc_verified | No | Whether the wallet has completed identity verification. When true, /send-payment dispatches the payout. When false, /send-payment does not send: it returns kyc_required and the USDC paid lands in account balance (recoverable via POST /withdraw). Verify before calling /send-payment. |
| kyc_review_answer | No | Latest review answer (e.g. GREEN for approved, RED for rejected), or null if never reviewed. |
| kyc_review_status | No | Latest review status from the verification provider, or null if never reviewed. |
| kyc_last_reviewed_at | No | Epoch milliseconds of the last review, or null if never reviewed. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description transparently states that the endpoint reads cached status maintained by a webhook, does not start verification, and does not return a verification link. It also communicates the important behavioral nuance that a false status would not cause /send-payment to fail destructively—the USDC would land in the account balance and be recoverable. This goes well beyond the annotations, which only declare readOnly/idempotent/destructive hints.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is somewhat long but every sentence earns its place: it explains optionality, the pre-flight use case, the failure mode, and the alternative endpoint. The opening bolded 'KYC is optional' is an effective front-loaded summary, though the paragraph could be trimmed slightly without losing key guidance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter read-only tool with an output schema available, the description fully covers what an agent needs: what the tool returns, how to act on the result, what it does not do, and how it relates to other endpoints. No important operational context is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters and 100% schema coverage, so the baseline is 4. The description adds relevant context about the returned field `kyc_verified` and its semantics, which is useful for interpreting the output, though it doesn't need to document any parameters since none exist.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool returns the calling wallet's cached KYC verification status, uses a specific verb and resource, and distinguishes this read-only status check from the related /get-kyc-link endpoint. It is not confused with any sibling tool despite many similar-looking KYC-related operations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says when to use the tool (as a free pre-flight check before calling /send-payment), what to do if kyc_verified is false (do not call /send-payment; call /get-kyc-link instead), and even provides nuanced fallback context about recoverable USDC. This is exemplary usage guidance with clear alternatives and conditions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_payment_statusRead-onlyIdempotentInspect
Check Venmo and PayPal payout status (free)
Reports the state of the Venmo and PayPal payouts this account has sent with GET /send-payment. Free: only the payout itself is a paid action.
Three ways to call it: with payment_id to fetch one payout, with recipient_id (from GET /payment-recipients) to list every payout to that saved recipient, or with neither to list every payout this account has sent, newest first.
state is queued (waiting on account balance), awaiting-funding (debited and accepted, but delayed on our side before it reaches the platform, usually until the next business day), in-process (dispatched to the platform), complete, failed, or cancelled. queued, awaiting-funding and in-process are the states still in flight; poll every few minutes, or register a webhook with POST /register-webhook to be told when a payout completes instead. A payout that has been in-process for more than an hour is worth raising with the account owner. state is absent on payouts sent before state tracking existed.
Bank payouts are not listed here: follow those with listBankingTransactions. Push-to-card transfers are completed by the recipient in the browser and have no server-side state.
| Name | Required | Description | Default |
|---|---|---|---|
| payment_id | No | Fetch one payout by its `id`. Takes precedence over `recipient_id`. | |
| recipient_id | No | List every payout to one saved recipient. This is the `recipient_id` returned by `GET /payment-recipients`, not the phone number or email. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
get_pricingARead-onlyIdempotentInspect
Get the fee schedule
Returns the fee and limits of every paid product: the route, the amount range it accepts, the fee rate, and the minimum fee. Free, no auth or payment header, so you can budget before you have an account.
Fees are added on top of amount. The total is amount + max(amount × fee_rate, min_fee), rounded up to the cent. The international card's fee_rate is the rate in effect now, including any running fee promotion. For the exact total of one specific request, read the amount in that route's 402 challenge: requesting a paid route without a payment header returns the quote and charges nothing.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| note | No | How fees are applied. |
| products | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the read-only/idempotent profile, but the description adds substantive behavior: no auth or payment header required, no charge incurred, and the exact fee computation formula including rounding and min-fee interaction. It also explains that the fee_rate reflects any live promotion, which the agent cannot infer elsewhere.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core purpose, then progressively adds formula and quote-retrieval detail. Every sentence carries information, though the third paragraph is fairly dense and could be tightened slightly.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Even though an output schema exists (so return fields needn't be spelled out), the description goes further by explaining the fee formula and the authoritative per-route quote path. An agent has everything needed to call this correctly and interpret its output.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline is 4 and there is nothing for the description to clarify. It correctly implies a parameterless global read.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Get the fee schedule') and immediately enumerates the returned fields: route, amount range, fee rate, minimum fee. This is clearly distinguishable from billing-related siblings like get_account_balance or get_payment_status, which report state rather than pricing.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit context for use ('so you can budget before you have an account') and routes the agent to the 402-challenge path when an exact per-request total is needed. It does not explicitly name or exclude any sibling tools, so it falls short of a full 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_purchase_conversationARead-onlyIdempotentInspect
Read a purchase conversation's orders
The record of a purchase conversation: whether a turn is still running, the last checkout attempt, and every order it placed with its charge status. Use it to track an order, and to settle what happened before repeating a confirm whose outcome is unclear (in_progress, charge_status: unknown, or a failed turn).
| Name | Required | Description | Default |
|---|---|---|---|
| conversation_id | Yes | The `conversation_id` from a purchase turn. |
Output Schema
| Name | Required | Description |
|---|---|---|
| open | No | |
| carts | No | Carts still open in the conversation. |
| orders | No | Every order this conversation placed, oldest first. |
| last_checkout | No | |
| conversation_id | No | |
| turn_in_progress | No | True while a turn is still running. Wait for it to clear before reading `orders`. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint/idempotentHint/non-destructive, so the safety bar is pre-met; the description adds real value by stating what the record exposes (turn state, last checkout attempt, per-order charge status) and its reconciliation role. No auth, rate-limit, or pagination notes, but those are minor for a read-only call.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the verb and resource and then the use case; little waste. The long parenthetical of failure states is dense but each element is load-bearing, so it earns its space.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, and the description covers inputs, purpose, and the operational trigger well. The one real gap is the absence of any differentiation from get_purchase_turn, which an agent choosing between the two would want.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Only one parameter with 100% schema description coverage, so the schema already documents `conversation_id` as the id from a purchase turn. The description adds no format, sourcing, or edge-case detail beyond that, making the baseline 3 correct.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource (read a purchase conversation's orders) and enumerates the payload: turn running state, last checkout attempt, and each order's charge status. It is clear what the tool returns, but it never names or distinguishes itself from the sibling get_purchase_turn, which an agent must disambiguate against.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete when-to-use guidance: to track an order, and to settle an unclear outcome before repeating a confirm, with the exact triggers (`in_progress`, `charge_status: unknown`, `failed` turn). It lacks any when-not or explicit alternative routing, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_purchase_turnARead-onlyIdempotentInspect
Read a purchase turn that was still running
Reads back a turn from POST /buy-with-saved-card that came back state: running. Poll every few seconds until state is done or failed; the response has the same shape as the POST.
A failed confirm may still have placed the order. Read GET /get-purchase-conversation before sending it again.
| Name | Required | Description | Default |
|---|---|---|---|
| turn_id | Yes | The `turn_id` from `POST /buy-with-saved-card`. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cart | No | The most recently shown cart. |
| note | No | The next step. |
| carts | No | Every open cart in the conversation, oldest first. |
| error | No | Present when `state` is `failed`. |
| reply | No | The shopping assistant's turn as prose, ready to show the holder. |
| state | No | `running` means the turn is still talking to the merchant; the fields below appear once it is `done`. One of: running, done, failed. |
| status | No | What to do next. `needs_input`: a question or a cart waiting on a confirm. `awaiting_approval`: send `approval_url` to the holder, then repeat the same confirm. `in_progress`: the order is already being placed; read `GET /get-purchase-conversation` instead of confirming again. `order_placed`. `declined`: see `decline_code`. `conflict`: nothing ran, see `error_code` and confirm the fresh cart's hash. Never branch on `reply`. One of: needs_input, awaiting_approval, in_progress, order_placed, declined, conflict. |
| catalog | No | The last product search. Empty on a turn that did not search again, so keep the previous one. |
| turn_id | No | This turn's id. Poll `GET /get-purchase-turn` with it while `state` is `running`. |
| order_id | No | Set when this turn placed an order. |
| unmatched | No | Things asked for that did not make it into a cart, with a reason. Show these rather than guessing from `reply`. |
| card_last4 | No | The saved card that paid, for naming it to the holder. |
| created_at | No | Milliseconds since the epoch. |
| error_code | No | On `conflict`: `cart_changed`, `turn_in_progress`, `delivery_address_changed`, or `delivery_address_bound_after_cart`. |
| approval_url | No | Send to the holder when `status` is `awaiting_approval`. Never open it yourself. |
| decline_code | No | The machine reason behind `declined`, e.g. `items_unavailable`. |
| charge_status | No | Whether money moved: `none`, `confirming`, `settled`, or `unknown` (do not retry; read the conversation). One of: none, confirming, settled, unknown, . |
| conversation_id | No | Send it back on every follow-up and on the confirm. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already carry the safety profile (readOnly, idempotent, non-destructive, not open-world), yet the description still adds real behavior: the response matches the POST shape, the polling cadence, and the important caveat that a failed confirm may still have placed the order. It does not cover rate limits or what states other than running/done/failed look like, so it stops just short of exhaustive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight paragraphs, front-loaded with the core read, then the polling rule, then the failure warning. No sentence is redundant and each advances correct usage.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be enumerated — and the description's note that the response mirrors the POST is a useful pointer rather than padding. For a one-parameter polling read with full annotation coverage, nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the single parameter already documents its provenance in the schema description. The prose adds no syntax, format, or constraint beyond what the schema provides, which is the expected baseline when the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Read') and resource ('a purchase turn') scoped precisely to turns from POST /buy-with-saved-card that returned state: running. It also implicitly distinguishes itself from buy_with_saved_card (the creator) and names get_purchase_conversation as a related read, so an agent can place it among siblings without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit operational loop: poll every few seconds until state is done or failed. It also names the alternative action and its precondition — read GET /get-purchase-conversation before resending a failed confirm. When-to-use, when-to-stop, and the alternative are all spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_saved_cardsARead-onlyIdempotentInspect
List the holder's saved cards
Lists the cards the account holder saved themselves: a card they already own, typed once on the card issuer's page and locked behind their passkey. Nothing is issued or prefunded, and no identity verification is needed. Every purchase paid with a saved card is approved by the holder on their own device.
The response carries display fields only, never a card number. An empty cards list means nothing is saved yet: call POST /create-saved-card-link and send the returned url to your human.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| note | No | The next step. |
| cards | No | |
| blocker | No | Present only when the holder finished saving a card but it is not readable yet. `needs_code`: they saved it on a card account they already had, and confirm it once with a one-time code in the dashboard. `linked_elsewhere`: the card account they unlocked is linked to another Laso account. Relay `note`; sending another link does not help with `needs_code`. One of: needs_code, linked_elsewhere. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only, idempotent, non-destructive, closed-world, but the description adds meaningfully beyond them: no card is issued or prefunded, no identity verification is required, purchases are approved by the holder on their device, and the payload never contains a card number. That last point is critical safety context for an agent handling payment data.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action, then semantics, then response shape and next step — a logical order with no filler sentences. It runs three short paragraphs where two would do, and the bolded 'Nothing is issued or prefunded' clause is slightly promotional, but every line carries information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, annotated, output-schema-bearing read tool, the description covers the remaining unknowns: what a saved card actually is, that no verification or issuance occurs, that numbers are absent from the response, how to read an empty list, and what to do next. Nothing an agent needs to call and interpret it is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is no parameter surface for the description to clarify; baseline 4 applies. Nothing in the text misrepresents or invents inputs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb+resource ('List the holder's saved cards') and immediately disambiguates the resource from sibling concepts: these are cards the holder already owns, typed once at the issuer and passkey-locked, not newly issued cards. This separates it cleanly from order_card, create_reloadable_card, and get_card_data.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit downstream routing for the empty-result case ('call POST /create-saved-card-link and send the returned url to your human'), which is genuine when-to-act guidance. It does not, however, state when to prefer this over other read tools such as get_card_data or list_card_transactions, so the routing is one-directional rather than a full use/avoid statement.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_signup_statusARead-onlyIdempotentInspect
Wait for your human to finish the signup
Long-polls until the human opens the claim link and finishes creating the account. Holds the connection open for about 60 seconds and returns 204 No Content if they have not finished yet.
Retry on 204 and nothing else. The call already blocks for you, so add no sleep between attempts. Every other status is final and retrying will not change the answer: 401 means the token is wrong, 410 means the link expired. Both carry "terminal": true in the body. A loop written as "retry until 200" spins at network speed against those, because they answer instantly rather than holding the connection.
On completion it returns your api_key — delivered exactly once. Store it before doing anything else; a later poll returns the account without it. By that point the human is on their dashboard, their agent wallet is provisioned, and you are already recorded as their connected agent, so announceAgentConnection is not needed on this path.
| Name | Required | Description | Default |
|---|---|---|---|
| claim_code | Yes | The claim_code from the same POST /signup response. | |
| claim_token | Yes | The claim_token from POST /signup. |
Output Schema
| Name | Required | Description |
|---|---|---|
| auth | No | An id_token / refresh_token bundle you can use immediately. |
| status | No | |
| api_key | No | Your lasoak_ key. Delivered EXACTLY ONCE — null on any later poll. |
| user_id | No | The Laso user id of the new account. |
| next_steps | No | |
| api_key_note | No | Present only when api_key is null, explaining that it was already delivered. |
| callable_base_url | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark this as read-only, idempotent, and non-destructive, but the description adds substantial behavioral detail: it blocks for ~60 seconds, returns 204 on incomplete signup, treats 401/410 as terminal with 'terminal': true, and delivers api_key exactly once. This goes far beyond the annotations and gives the agent a precise mental model.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but every sentence earns its place: it front-loads the core purpose, then covers retry behavior, terminal statuses, and the one-time api_key delivery in a structured, bolded format. No filler or repetition beyond the title echo.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a long-polling tool with an output schema, the description covers all essential context: blocking behavior, status code semantics, retry policy, terminality, api_key delivery, and downstream implications like not needing announceAgentConnection. Nothing critical is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, with both claim_token and claim_code described as coming from POST /signup. The description does not add extra parameter-level meaning beyond that, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Wait for your human to finish the signup' and then explains the long-polling behavior. It clearly distinguishes itself from siblings like start_signup and announce_connection by describing exactly what this tool does and what it does not do.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit when-to-use and when-not-to-use guidance: 'Retry on 204 and nothing else', 'Every other status is final', and 'announceAgentConnection is not needed on this path'. It also warns against a naive 'retry until 200' loop, which is actionable and prevents misuse.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_supported_countriesARead-onlyIdempotentInspect
Get supported countries
Returns where each product can be used or sent, as ISO 3166-1 alpha-2 country codes. Free, no auth or payment header.
The USA prepaid card, Venmo payments, and bank payments are U.S. only. PayPal pays recipients in every country Laso serves; countries_by_platform separates it from Venmo. Push to card pays out to debit cards in the U.S. (USD), the euro area (EUR), and the U.K. (GBP); countries_by_currency maps each currency to its countries. The gift card list is the live catalog's: pass one of its codes as country to GET /order-gift-card. The international prepaid card has no fixed list (countries: null); check a merchant with GET /search-merchants?card_type=Non-Reloadable International.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| products | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint/idempotentHint/no-destructive, so the safety profile is covered. The description adds real behavioral context beyond that: 'Free, no auth or payment header,' plus which products are U.S.-only vs global and where `countries: null` occurs, which an agent needs to interpret results.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the purpose and return format, then appends dense product-specific caveats. It is on the long side for a zero-param tool and some sentences verge on tangential endpoint routing, but every sentence carries distinct, decision-relevant information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no parameters, an output schema present, and full annotations, the definition needs little more; the description still supplies the domain semantics (per-product scope, U.S.-only vs global, null list) that make the returned codes interpretable. Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
This tool takes zero parameters, so the baseline is 4. The `country` reference in the description pertains to a different endpoint rather than this tool's inputs, but there are no parameters to clarify.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Get supported countries') and then immediately clarifies what that means concretely: 'Returns where each product can be used or sent, as ISO 3166-1 alpha-2 country codes.' No sibling does the same thing, so the agent can distinguish it without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear context for the various product-specific country lists and routes the agent to the right alternative endpoints (e.g. `GET /order-gift-card` with a listed code, `GET /search-merchants` for the international card). It doesn't phrase explicit 'use this vs X' when/when-not rules, but the routing guidance covers the relevant cases.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_versionARead-onlyIdempotentInspect
Get the current docs version
Returns the current API contract version (api_version), the versioning and deprecation policy, and the content-hash version of the Laso Finance agent docs (SKILL.md, openapi.json, llms.txt, llms-full.txt, ai-plugin.json). Free, no auth or payment header.
Agents aggressively cache these docs, so use this to detect a stale cache: if the docs_version you last saw differs from the value returned here, refetch the docs. Every API response also carries this value in the X-Laso-Docs-Version response header, alongside X-Laso-Docs-Manifest, which points at the authoritative freshness beacon at https://laso.finance/.well-known/docs-version.json.
This route is also the status target of the API catalog at https://laso.finance/.well-known/api-catalog (RFC 9727), which every response advertises via a Link header with rel="api-catalog".
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| docs | No | Per-file entries, each with a `url` and a stable `sha256` content identifier. Compare against the values you last saw to tell which file changed. |
| note | No | |
| versioning | No | The versioning and deprecation policy in machine-readable form: which header carries the version, what counts as an additive versus a breaking change, and how a retirement is signalled. |
| api_version | No | Version of the API contract itself (this description's `info.version`). Moves only on a breaking change, unlike `docs_version`. Also sent on every response as `X-Laso-Api-Version`. |
| docs_version | No | 12-character content hash of the agent docs. Changes only when the docs change. |
| api_catalog_url | No | URL of the RFC 9727 API catalog (`application/linkset+json`) indexing the OpenAPI description, the agent docs, and this status route. |
| docs_manifest_url | No | URL of the authoritative freshness beacon, served with no-cache. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only, idempotent, non-destructive behavior, but the description goes further: it declares the endpoint is free, needs no auth or payment header, explains aggressive client-side caching, and documents the response header and freshness beacon. This is rich context beyond structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded: purpose first, then return contents, usage, and supporting headers. It is longer than strictly necessary for a zero-param tool, and the final paragraph about RFC 9727 API catalog and Link header is tangential, but no sentence is confusing or out of order.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description need not enumerate return values, yet it still explains api_version, versioning policy, and docs_version clearly. Combined with explicit auth and cache-detection guidance, an agent has everything needed to call this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the schema is empty and schema coverage is 100%. Per the rubric, zero parameters sets a baseline of 4; there is nothing to clarify or compensate for.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb+resource ('Get the current docs version') and details exactly what version data is returned. It never names a sibling or differentiates itself from tools like search_docs, so it stops short of the top score.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly states when to call it ('use this to detect a stale cache') and gives the triggering condition (docs_version differs from last seen). It also points to the X-Laso-Docs-Version header as an equivalent mechanism, though it never states when not to call it or how it relates to the sibling search_docs.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_webhookARead-onlyIdempotentInspect
Get webhook registration & delivery health (free)
Returns the calling wallet's webhook registration and its delivery health. The signing secret is never returned here — it is shown once by POST /register-webhook; re-register to rotate it.
A registration is auto-disabled after 50 consecutive failed deliveries (disabled becomes true); re-register to re-enable it.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | |
| disabled | No | True when auto-disabled after repeated delivery failures. Re-register to re-enable. |
| registered | No | |
| disabled_reason | No | |
| consecutive_failures | No | |
| last_delivery_detail | No | `HTTP <status>` of the last attempt, or the error message. |
| last_delivery_status | No | `delivered` or `failed`, or null before the first delivery. |
| last_delivery_timestamp | No | Epoch milliseconds of the last delivery attempt. |
| last_delivery_message_id | No | The `webhook-id` header of the last delivery. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/idempotent/destructive annotations, the description adds meaningful behavior: the signing secret is never returned, it is only shown once at registration, and registrations auto-disable after 50 consecutive delivery failures. This gives the agent useful operational context that annotations alone do not provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded with the tool's purpose. The follow-up sentences each add necessary operational details, and there is no filler or redundant schema repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no parameters, an output schema available, and annotations covering safety, the description provides everything needed to call the tool correctly. It also covers the important edge case of auto-disablement and the path to recovery.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has zero parameters, so there are no parameter semantics to document. The description still adds relevant context by clarifying that the operation applies to the calling wallet's webhook, which is the only implicit input.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a specific verb and resource: 'Get webhook registration & delivery health.' It also scopes the operation to 'the calling wallet's' webhook, making the read-only intent unambiguous and clearly distinguishing it from sibling tools like register_webhook and delete_webhook.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly routes the agent away from this tool when the signing secret is needed or when rotation is desired, pointing to POST /register-webhook instead. It also explains that a disabled registration must be re-registered to re-enable, giving concrete when-not-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_withdrawal_statusARead-onlyIdempotentInspect
Get withdrawal statuses
Returns the status of withdrawals for the authenticated user. If withdrawal_id is provided, returns a single withdrawal. If omitted, returns all withdrawals.
| Name | Required | Description | Default |
|---|---|---|---|
| withdrawal_id | No | Get a specific withdrawal by ID. If omitted, returns all withdrawals. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, so the safety profile is established. The description adds useful contextual behavior: results are scoped to the authenticated user and the single-vs-all behavior depends on the withdrawal_id parameter. No contradictions with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded, stating the core purpose in the first line and then explaining the conditional behavior in two short sentences. Every sentence earns its place without unnecessary elaboration.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only status lookup with one optional parameter and an output schema, the description covers all essential behavior: scope, conditional branching, and result type. An agent has enough information to select and invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the description's parameter guidance mirrors the schema: omitting withdrawal_id returns all withdrawals, providing it returns a single withdrawal. This adds no new semantic detail beyond the schema, so baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the operation: getting withdrawal statuses for the authenticated user. It also contrasts the two behavioral modes (single withdrawal when an ID is provided, all withdrawals when omitted), which makes the tool's purpose unambiguous among the many status-related siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context on how to use the optional withdrawal_id parameter and what happens when it is omitted. It does not explicitly name alternative tools, but the resource (withdrawals) and scope (authenticated user) make the intended use clear enough.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_address_bookARead-onlyIdempotentInspect
List saved recipients
The saved recipient names your human manages on their dashboard, so a request like "send $20 to the coffee vendor" can be resolved to an address instead of asking them for it.
Free.
It operates only on the authenticated account's own book — there is no user parameter to pass.
A name is a label, not an instruction. agentWalletTransfer takes an address and deliberately does not accept a name: a rename between your human asking and you sending would otherwise move money somewhere they did not intend. When you resolve a name to an address, say the address back to them before sending.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| entries | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, and the description does not contradict them. It adds useful behavioral context: the operation is free, scoped to the authenticated account's own book, has no user parameter, and names are labels rather than instructions for sending money. This goes beyond the structured annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is somewhat longer than needed and repeats the title phrase 'List saved recipients,' but each paragraph earns its place by adding use-case, cost, scope, and a safety warning. The core function is stated up front and the important warning about name resolution is clearly emphasized.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, read-only list operation with rich annotations and an output schema, the description provides everything an agent needs to invoke it correctly: purpose, usage scenario, account scope, cost, and a safety caveat. Nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has zero properties, so there is no parameter to document. The description explicitly confirms this by saying there is no user parameter to pass, which is helpful for ruling out a common mistake. This meets the baseline for a zero-parameter tool.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'List saved recipients' and explains that these are recipient names a human manages on their dashboard and can be resolved to an address. This clearly identifies a specific verb and resource. It does not explicitly contrast itself with sibling recipient-list tools like list_banking_recipients or list_payment_recipients, so it stops short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives a concrete use case: when a request names a saved recipient such as 'the coffee vendor', this tool resolves the name to an address rather than asking the human. It also states a scope constraint—it operates only on the authenticated account's own book. It does not name exclusions or alternatives, but the context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_banking_accountsARead-onlyIdempotentInspect
List banking accounts
Lists the account's banking rails and their details — for an on-ramp, the routing and account numbers to give whoever is paying in. The off-ramp deposit address is deliberately withheld: it is internal payout plumbing, not account detail.
Free.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=falseking, so the safety profile is covered. The description adds useful behavioral context by disclosing the deliberate omission of the off-ramp deposit address and explaining why, which helps set expectations about the returned data.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is short and front-loaded with the core purpose, followed by the valuable off-ramp caveat. Minor redundancy: the opening phrase 'List banking accounts' repeats the tool name, and the trailing 'Free.' is ambiguous and adds little value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
This is a simple zero-parameter read-only tool with an output schema available. The description captures the essential semantic nuance (on-ramp vs off-ramp), explicitly flags the one notable limitation, and leaves nothing an agent needs to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters and schema description coverage is 100%, so there are no parameter semantics for the description to compensate for. Per the baseline for zero-parameter tools, this dimension is well satisfied.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Lists') and defines the resource as 'the account's banking rails and their details.' It goes beyond the tool name by explaining on-ramp vs off-ramp semanticsholics, which clearly separates it from siblings like list_banking_transactions and list_banking_recipients.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear use context: an on-ramp needs routing and account numbers to give to a payer. It also explicitly tells the agent the off-ramp deposit address is deliberately withheld, so it knows this tool is not for payout plumbing. It does not explicitly name alternative tools or state when-not-to-use, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_banking_recipientsARead-onlyIdempotentInspect
List recipients and destinations
Lists payout recipients and their destinations, with account numbers masked to the last four digits. This is where destination_id values come from. Also available as the free paywalled route GET /bank-recipients.
Free.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only, idempotent, and non-destructive behavior. The description adds that account numbers are masked and that it is a free paywalled route, which is valuable beyond the annotations. No contradiction found.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is short and front-loaded with the core purpose. The additional details about masking and the free route are useful and not redundant. Every sentence serves a purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple list tool with no parameters and an output schema, the description covers all needed aspects: what it lists, the masking behavior, the source of destination_id, and even the route. Nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With zero parameters, the description doesn't need to explain any. The schema is trivially covered, and the description doesn't attempt to document parameters. Baseline for 0 params is 4, which is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it lists payout recipients and destinations, and explicitly mentions account numbers are masked. It distinguishes itself from other list tools like list_payment_recipients by specifying the banking domain and the destination_id source.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It states this is where destination_id values come from, giving clear context for when to use it (to obtain destination IDs). It doesn't explicitly mention when not to use it or compare to alternatives, but the context is strong enough for most agents.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_banking_transactionsARead-onlyIdempotentInspect
List transactions
Lists banking transactions for the account: money arriving over the on-ramp and paying out over the off-ramp, with normalized statuses and amounts.
Free.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, so the safety profile is covered. The description adds useful behavioral context: it lists both incoming and outgoing money and returns normalized statuses and amounts. It does not go into pagination, ordering, or how the account is determined, but with annotations and an output schema present, this is adequate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is short and front-loaded, with the main purpose stated immediately. The opening 'List transactions' is slightly redundant with the body, and 'Free.' is terse but informative. Overall, every sentence contributes to understanding the tool's scope and behavior.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a no-parameter, read-only list operation with annotations and an output schema, the description is complete enough. It explains what kind of transactions are included and what normalization to expect. It does not mention alternatives or limitations, but those are not required for this simple tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the baseline is 4. There is no parameter semantics for the description to add, and the schema correctly reflects an empty input. The description focuses on the output scope instead, which is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: it lists banking transactions for the account, including both incoming and outgoing movements. It also clarifies scope by mentioning on-ramp and off-ramp flows, which distinguishes it from card-transaction or single-transaction siblings like list_card_transactions and get_banking_transaction.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context about what the tool does and what it covers: banking transactions for the account, with normalized statuses and amounts. It does not explicitly name alternatives or state when not to use it, but the context is specific enough for an agent to know this is the right tool for listing account-level banking transactions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_card_transactionsARead-onlyIdempotentInspect
List reloadable card transactions
Returns transactions on the authenticated user's reloadable cards, newest first: amount, merchant, status, and timestamps.
Pass card_id for one card's history, or omit it for every reloadable card on the account. Filter with status and cap the page with limit.
This route covers reloadable cards only. The two non-reloadable products keep their history in Laso's own records and are read through /get-card-data.
If the wallet has no card issuer account linked, the list is empty and a note explains how the account holder sets one up at https://laso.finance/agent/dashboard/verified/card.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of transactions to return. Defaults to the issuer's own page size (20). | |
| status | No | Filter by status, e.g. `pending`, `settled`, `declined`, `reversed`, `refunded`. | |
| card_id | No | Return only this card's transactions. Omit for every reloadable card on the account. |
Output Schema
| Name | Required | Description |
|---|---|---|
| note | No | Present only when no card issuer account is linked. |
| transactions | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint false. The description adds that results are newest first, include specified fields, and returns an empty list with a setup note when no issuer account is linked. No contradiction; the added detail complements annotation coverage.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Five tight sentences: main action, return shape, parameter usage, scope boundary, and empty-edge-case. No filler; the most important scoping and routing constraints are prominently positioned.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema exists, return fields need no further explanation. The description covers card scoping, filtering, pagination, scope boundary, and the no-issuer edge case, so an agent has everything needed to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the description largely restates the schema in natural language. It adds minimal new meaning beyond the schema's existing parameter descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: list reloadable card transactions. It distinguishes itself from the non-reloadable product history route by explicitly naming /get-card-data as the alternative. This is clear and actionable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly instructs when to pass card_id vs omit, how to use status and limit, and clarifies this route only covers reloadable cards. It names the sibling tool /get-card-data for non-reloadable products and describes the empty-list scenario when no issuer account is linked.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_payment_recipientsARead-onlyIdempotentInspect
List saved Venmo and PayPal recipients (free)
Lists the Venmo or PayPal recipients this account has paid before, so you can resolve a name your human said ("send $20 to Jane") into the handle that GET /send-payment takes as its recipient_id. Free — only the payout itself is a paid action.
Two different ids are in play. Each entry's recipient_id is an opaque saved-entry id: pass it to POST and DELETE /payment-recipients. Its handle is the phone number or email you actually pay: pass that as recipient_id to GET /send-payment. Passing the saved-entry id to GET /send-payment does not send to the saved person.
Use total_sent and last_sent_timestamp to disambiguate similar names, and confirm with your human rather than guessing between two entries.
| Name | Required | Description | Default |
|---|---|---|---|
| platform | Yes | Payment platform whose saved recipients to list. | |
| include_archived | No | Include archived entries. Defaults to false. |
Output Schema
| Name | Required | Description |
|---|---|---|
| user_id | No | |
| platform | No | One of: venmo, paypal. |
| recipients | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/idempotent annotations, the description exposes a subtle behavioral trap: two different id types exist, and using the wrong one silently fails to send to the intended person. It also explains how total_sent and last_sent_timestamp help disambiguate similar entries, adding genuine value not present in annotations or schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose, then adds high-value operational warnings and disambiguation guidance. Every sentence contributes meaningful information, and the length is justified by the need to prevent a real misuse of recipient identifiers.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema exists to describe return values, the description covers everything else needed for a safe and correct call: the supported platforms, the free nature, the identifier distinction, and how to handle ambiguous names. No critical operational context is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already documents both parameters with 100% coverage, including enums for platform and a default for include_archived. The description adds context about Venmo/PayPal and the overall purpose, but it does not significantly deepen the meaning of the two input parameters beyond what the schema provides, so the baseline score applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a precise verb-resource pair: 'List saved Venmo and PayPal recipients', and then clarifies the exact scope ('recipients this account has paid before'). It also clearly distinguishes this tool from related operations like GET /send-payment and recipient management endpoints, so an agent can select it accurately.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives a concrete scenario: resolving a spoken name into a handle before calling GET /send-payment. It explicitly contrasts the free listing action with the paid payout and warns against passing the saved-entry id to GET /send-payment, which is an effective when-not-to behavior.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
order_cardADestructiveInspect
Order a USA prepaid card
Pay between $5–$1000 USDC to order a Laso Finance USA prepaid card. By default returns JSON with auth credentials and card info (for AI agents). Pass format=html to get an HTML redirect to the card redemption URL (for browser-based flows).
The JSON response includes a card.status of "pending". Card details (number, CVV, etc.) take ~7-10 seconds to become available. Poll getCardData at the callableBaseUrl to check when status becomes "ready".
U.S. only. This card is issued in USD and can only be used for purchases at U.S.-based merchants. Physical goods must ship to a U.S. address. For non-U.S. merchants or non-USD currencies, use GET /order-intl-card instead. This endpoint is intended for the caller's own use — the card is non-transferable.
PAID ROUTE (5-1000 USD): the x402 USDC price is paid automatically from your managed agent wallet. Make sure the wallet exists and is funded first (get_agent_wallet).
| Name | Required | Description | Default |
|---|---|---|---|
| amount | Yes | USD amount to load on the card (min $5, max $1000) | |
| format | No | Response format. `json` (default) returns auth credentials and card info for agents. `html` returns a redirect page for browsers. | json |
Output Schema
| Name | Required | Description |
|---|---|---|
| auth | No | |
| card | No | Card order info returned by /get-card. Status is always `pending` initially — poll `/get-card-data` to check when card details are ready. |
| user_id | No | The user's ID (lowercase wallet address) |
| callable_base_url | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations by disclosing that USDC is paid automatically from the managed wallet, that the card starts in a pending status, that getCardData should be polled at callableBaseUrl, and that the card is US-only and non-transferable. This gives the agent a clear picture of side effects and follow-up behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well organized with bolded sections and front-loaded key information. It is slightly verbose and repeats 'Order a USA prepaid card' near the beginning, but every major paragraph adds relevant operational or routing context.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers the payment side effect, response format options, pending-to-ready status behavior, polling instructions, geographic restrictions, and wallet prerequisites. With an output schema presentanding return-value documentation, nothing essential is missing for an agent to invoke and follow up correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already fully documents amount and format, but the description adds operational meaning: payment is in USDC via x402, and the format parameter maps to agent-vs-browser flows. It clarifies that amount is expressed in USD but funded in USDC, which is not fully captured in the schema alone.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Order a USA prepaid card' from Laso Finance, with a clear amount range. It is explicitly distinguished from international card ordering, so an agent can separate it from order_intl_card and other card-related siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit routing guidance: use order_intl_card for non-U.S. merchants or non-USD currencies, and notes the endpoint is for the caller's own use. It also gives a prerequisite to ensure the agent wallet exists and is funded via get_agent_wallet. It does not compare against create_reloadable_card or order_gift_card, so it stops short of covering all sibling alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
order_gift_cardADestructiveInspect
Order a gift card
Pay USDC via x402 to order a gift card. First browse the catalog via GET /search-gift-cards to find the laso_server_id for the card you want, then call this endpoint with the amount and product ID.
Pricing: amount is the card's face value in the product's own currency, not USD. Laso converts it to USD at the current exchange rate and adds the product's fee (up to 4.8%); that total is the x402 USDC price. A 100 SAR card costs roughly $28 USDC, not $100. Check the product's currency field in GET /search-gift-cards to see what amount is denominated in.
The $5 minimum and $9,000 maximum apply to the converted USD value, not the raw amount, so a foreign-currency amount is accepted only when its USD equivalent falls inside that range.
Returns redemption details (URL, code, and/or PIN) depending on the gift card brand.
PAID ROUTE (5-9432 USD): the x402 USDC price is paid automatically from your managed agent wallet. Make sure the wallet exists and is funded first (get_agent_wallet).
| Name | Required | Description | Default |
|---|---|---|---|
| amount | Yes | Gift card face value in the product's own currency (see the product's `currency` field in `GET /search-gift-cards`), not USD. The x402 price is this value converted to USD plus the product fee. After conversion it must be worth at least $5 and at most $9,000 USD. | |
| country | No | ISO 3166-1 alpha-2 country code (defaults to "US") | US |
| laso_server_id | Yes | The product identifier from the gift card catalog (GET /search-gift-cards). Always copy it from a search result; an id that is not in the catalog returns 404 `unknown_laso_server_id`. Amazon is `amazon` for every country, selected with `country`. |
Output Schema
| Name | Required | Description |
|---|---|---|
| auth | No | |
| user_id | No | The user's ID (lowercase wallet address) |
| gift_card | No | Gift card order result with redemption details. |
| callable_base_url | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes well beyond the annotations: it discloses that this is a paid route, that funds are automatically deducted from the managed agent wallet, that the wallet must exist and be funded, and that pricing involves currency conversion plus fees. It also clarifies the USD min/max applies to converted value, which is critical behavioral context for a destructive purchase operation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is longer than average but every section earns its place: workflow, pricing, limits, return values, and wallet funding. The bold labels and short paragraphs aid scanning. Minor wording like 'PAID ROUTE (5-9432 USD)' is slightly awkward but does not undermine clarity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a paid, destructive purchase tool, the description covers the full calling context: prerequisite catalog lookup, currency conversion, fee structure, min/max validation, return contents, and wallet funding requirement. The output schema exists, so return details need not be exhaustively repeated. No essential information is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds value beyond the schema with a concrete example ('A 100 SAR card costs roughly $28 USDC, not $100') and explicitly states the fee cap (up to 4.8%), which the schema does not mention. This helps the agent reason about amount semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action ('Order a gift card'), identifies the payment mechanism (x402 USDC), and clearly distinguishes the workflow from siblings like search_gift_cards by specifying the prerequisite catalog lookup. It leaves no ambiguity about what this tool does.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly instructs the agent to first browse the catalog via GET /search-gift-cards to obtain laso_server_id, then call this endpoint. It provides clear context for when to use the tool, though it does not explicitly contrast it with alternatives like order_card or order_intl_card.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
order_intl_cardADestructiveInspect
Order an international prepaid card
Order an international non-reloadable prepaid card (USD). The order is queued and fulfilled by an admin — after fulfillment, card details become available via GET /get-card-data with card_type=Non-Reloadable International.
The x402 payment covers the on-card amount plus a 3.8% fee, or a lower rate while a limited-time fee promotion is running (it can be 0%). The 402 challenge always carries the exact total. Minimum $100, maximum $1,000 on-card amount. The $1,000 maximum is the amount loaded on the card and does not change with the fee rate. Submit a whole dollar amount.
Placing the order accepts the card issuer's terms on behalf of the account holder: the Cardholder Agreement, the E-Communications Disclosure, and the Privacy Notice.
If you need to cancel a queued order before it is fulfilled, use POST /cancel-intl-order.
PAID ROUTE (100-1038 USD): the x402 USDC price is paid automatically from your managed agent wallet. Make sure the wallet exists and is funded first (get_agent_wallet).
| Name | Required | Description | Default |
|---|---|---|---|
| amount | Yes | On-card USD amount (min $100, max $1,000 regardless of the fee rate). Must be a whole dollar amount: the issuer only issues whole-dollar cards. The x402 payment is this amount plus a 3.8% fee, or less during a fee promotion. |
Output Schema
| Name | Required | Description |
|---|---|---|
| auth | No | |
| message | No | |
| user_id | No | |
| intl_card_order | No | |
| callable_base_url | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare the safety profile (destructiveHint=true, non-idempotent, openWorld), and the description adds substantial context beyond them: the order is queued and admin-fulfilled, the x402 charge covers amount + 3.8% fee (or promotional rate), the 402 challenge carries the exact total, and placing the order accepts three legal agreements on the account holder's behalf. This is rich behavioral disclosure that goes well past the structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the one-line purpose, then layered detail in digestible paragraphs. Slightly redundant, since the fee and min/max rules are stated twice (description and schema), but every paragraph carries information an agent needs before committing a payment.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, and the description covers payment mechanics, prerequisites, queuing, terms acceptance, and cancellation. The only minor gap is expected fulfillment timing, which an agent might want before deciding to order.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the min/max and whole-dollar constraints are already documented in the schema. The description largely restates them, but adds the useful clarification that the $1,000 maximum is the on-card loaded amount and is independent of the fee rate, which sharpens interpretation of the single parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Order an international prepaid card') and immediately narrows to 'international non-reloadable prepaid card (USD)', which distinguishes it from siblings like order_card, create_reloadable_card, and order_gift_card. An agent can route to this tool without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly gives prerequisites ('Make sure the wallet exists and is funded first (get_agent_wallet)'), the cancellation alternative ('use POST /cancel-intl-order'), and the follow-up path to retrieve results ('GET /get-card-data'). It names the conditions that select each alternative, which is exactly the routing guidance the dimension asks for.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
pay_x402_endpointDestructiveInspect
Pay ANY external x402-paywalled endpoint from your managed agent wallet: the target's 402 challenge is settled in USDC and the response body is returned, with the settlement transaction as txHash. A challenge offering Solana is paid from the Solana wallet. A challenge offering Base mainnet (eip155:8453) is paid from your Base wallet, with no ETH needed for gas; other EVM networks are refused. If the endpoint offers both, pin expected_network to choose which wallet pays. Paying a Base-only endpoint without a Base wallet fails: call create_agent_wallet, fund base_wallet_address with USDC on Base, and retry. txHash is the Base transaction hash for a Base payment and the Solana signature for a Solana one. The wallet balance can take up to a minute to reflect a payment, so confirm with txHash rather than an immediate balance read. Use the guardrail arguments to pin what you agreed to pay. For Laso's own paid routes, prefer their dedicated tools instead.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Full https URL of the x402 endpoint to call and pay. | |
| body | No | JSON request body (for POST/PUT). | |
| method | No | HTTP method (default GET). | |
| params | No | Query parameters to append to the URL. | |
| expected_asset | No | Refuse to settle in any other asset (e.g. a USDC mint/contract address; USDC on Base is 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913). | |
| expected_pay_to | No | Refuse to settle to any other receiving address. | |
| max_amount_usdc | No | Refuse to settle if the endpoint asks for more USDC than this. | |
| expected_network | No | Refuse to settle on any other network (CAIP-2 id): eip155:8453 for Base, solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp for Solana. Pin it when an endpoint offers both, to choose which wallet pays. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
push_to_cardADestructiveInspect
Send money to a debit card (USD, EUR, GBP)
Pay USDC to initiate a push-to-card transfer. Specify the face value in the target currency (USD, EUR, or GBP); Laso computes the USDC cost using the current exchange rate plus a 4.8% fee (minimum fee of $1.50/€1.50/£1.50 in the transfer currency), and that becomes the x402 price. Returns a redemption_url that must be opened to complete the transfer. The form requires sender name, debit card number, and cardholder name.
Supported currencies:
USD— U.S. debit cards (U.S. bank accounts only)EUR— Eurozone debit cardsGBP— U.K. debit cards
Laso cannot perform the transfer directly — the redemption URL must be visited and the debit card details entered manually (by the agent or a human).
Fee: 4.8%, with a minimum of 1.50 in the transfer currency (included in the USDC price, computed from the requested face value).
PAID ROUTE (11.50-10000 USD): the x402 USDC price is paid automatically from your managed agent wallet. Make sure the wallet exists and is funded first (get_agent_wallet).
| Name | Required | Description | Default |
|---|---|---|---|
| amount | Yes | Face value to send to the debit card, denominated in the chosen `currency` (min 10, max 9,541.98). The x402 payment price is this face value converted to USD plus a 4.8% fee (minimum fee of 1.50 in the chosen currency). | |
| currency | No | Target currency for the debit card transfer. Defaults to `USD`. | USD |
Output Schema
| Name | Required | Description |
|---|---|---|
| auth | No | |
| note | No | Important information about the currency's regional restriction and required form fields |
| amount | No | The face value sent to the debit card, in the requested `currency` |
| message | No | |
| success | No | |
| user_id | No | The user's ID (lowercase wallet address) |
| currency | No | The target currency of the debit card transfer One of: USD, EUR, GBP. |
| redemption_url | No | URL to open and complete the push-to-card transfer. The form requires: sender name, debit card number, and cardholder name. |
| callable_base_url | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate destructiveHint=true, so the description's mention of sending money is consistent. It adds valuable behavior beyond annotations: the fee (4.8% with minimum), the requirement to visit a redemption_url, the manual entry of card details, and the automatic payment from the agent wallet. This gives the agent a full picture of side effects and prerequisites.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is moderately long but well-structured: it leads with the core action, then covers supported currencies, fee, and the paid route. Each section adds necessary information, and the formatting (bold headers) aids scanning. It could be trimmed slightly, but nothing is redundant.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a money-transfer tool with multiple prerequisites and a manual step, the description covers all essential aspects: the transfer mechanism, currency restrictions, fee structure, the redemption_url requirement, the need for a funded agent wallet, and the manual entry of card details. The presence of an output schema means return values need not be described, so this is complete for an agent to execute correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already describes both parameters thoroughly (amount and currency), with coverage at 100%. The description reinforces this and adds nuance: the amount is a 'face value' that gets converted to USDC with a fee, and the currency restricts card eligibility. This exceeds the schema's detail, particularly around the fee calculation and currency-specific limits.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a clear action verb and resource ('Send money to a debit card') and specifies the currencies and the payment mechanism (USDC). It distinguishes itself from other money-movement tools like send_bank_payment or withdraw by focusing on debit card transfers, making the purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides strong contextual guidance: it explains the manual redemption step, the wallet funding prerequisite, and the fee structure. It does not explicitly name alternative tools or state when not to use it, but the context is clear enough that an agent can infer appropriate use. A small deduction for lacking explicit exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
refresh_card_dataAInspect
Trigger a card data refresh
Requests an updated balance for a card.
For U.S. non-reloadable cards (default), the card is re-scraped from the issuer via a retrieval queue and processed asynchronously. Rate limited per card to one request every 5 minutes, and to at most 12 refreshes in any rolling 24-hour period.
For international non-reloadable cards, a balance update request is recorded; an admin will manually update the balance within 24 hours. While a balance update is already pending for a card, additional requests for that card return 409.
| Name | Required | Description | Default |
|---|---|---|---|
| card_id | Yes | The card ID to refresh data for | |
| card_type | No | The type of card. Defaults to `Non-Reloadable U.S.` if omitted. |
Output Schema
| Name | Required | Description |
|---|---|---|
| message | No | |
| success | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnlyHint=false, destructiveHint=false), the description discloses async processing, rate limits (5-minute and 12 per 24h), manual handling for international cards, and the 409 conflict behavior. This gives the agent a clear picture of side effects and failure modes without contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise, front-loaded with the purpose, and structured into clear paragraphs for U.S. and international behavior. Every sentence adds value, with no redundancy or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the action, parameters, rate limits, error condition, and async behavior. An output schema is present, so return values are covered. For a refresh tool with this complexity, nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so both parameters are documented. The description adds value by explaining the impact of card_type (defaulting to U.S., different processing paths) and the meaning of card_id in context, which goes beyond the schema's terse descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool triggers a card data refresh and requests an updated balance. It distinguishes itself from siblings like get_card_data by focusing on the refresh action, and the title and description align with the resource and action.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains when to use the tool: to refresh card data, and it differentiates behavior for U.S. vs international cards, including rate limits and async processing. It also notes the 409 error when a refresh is already pending. However, it doesn't explicitly contrast with get_card_data or other alternatives, leaving some inference needed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
refresh_tokenAInspect
Refresh an ID token
Exchange a refresh token for a new ID token. This is a free endpoint — no x402 payment required. Uses the standard OAuth2 grant_type=refresh_token pattern.
| Name | Required | Description | Default |
|---|---|---|---|
| grant_type | Yes | Must be "refresh_token" | |
| refresh_token | Yes | The refresh token received from a previous /auth or /get-card call |
Output Schema
| Name | Required | Description |
|---|---|---|
| user_id | No | The user's ID (lowercase wallet address) |
| id_token | No | New ID token — use as Bearer token for Laso Finance APIs |
| expires_in | No | Token lifetime in seconds |
| refresh_token | No | New refresh token — use for the next refresh |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond annotations, the description adds valuable behavioral context: 'free endpoint — no x402 payment required' and 'standard OAuth2 grant_type=refresh_token pattern.' It does not disclose refresh-token rotation or auth requirements, but the annotations and output schema cover the remaining safety profile.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is short, front-loaded with the action, and every clause earns its place. The payment/cost note is a single useful addition, and the protocol reference is concise.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple token-refresh endpoint, the description plus full parameter schema and output schema covers purpose, parameters, cost, and protocol. There is no significant missing information needed to call the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and both parameters already have descriptive text: grant_type must be 'refresh_token' and refresh_token comes from a previous /auth or /get-card call. The description reinforces their purpose but adds little new parameter-level meaning, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a specific verb and resource: 'Refresh an ID token' and 'Exchange a refresh token for a new ID token.' It is immediately clear what this tool does and how it differs from auth-related siblings by naming the OAuth2 refresh-token flow.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The intended use is implied: use this when you have a refresh token and need a new ID token. However, there is no explicit 'use when' guidance or mention of alternatives such as exchange_api_key, so the agent must infer the selection context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
register_webhookAInspect
Register a notification webhook (free)
Registers (or replaces) an HTTPS webhook URL to receive the calling wallet's account notifications as signed POSTs — banking application status changes, bank transfer and payout completions, agent wallet deposits, card orders, and every other event the user is notified about. This closes the polling gap for agents: instead of re-fetching status endpoints, point this at any URL you can receive HTTP on (your harness's inbound webhook endpoint, or a relay you poll).
Deliveries are signed per the Standard Webhooks specification (https://www.standardwebhooks.com/): each POST carries webhook-id, webhook-timestamp, and webhook-signature (v1,<base64 HMAC-SHA256>) headers verifiable with any standard-webhooks library using the returned secret. The body is {"type": "notification.<category>", "timestamp": "<ISO 8601>", "data": {"user_id", "title", "text", "category"}}.
The secret is returned exactly once, by this call. Re-registering rotates the secret, replaces the URL, and re-enables a registration that was auto-disabled after 50 consecutive failed deliveries. Registering also notifies the account owner through their other channels and fires a first signed test delivery (type notification.account) at the new URL.
Deliveries time out after 10 seconds and are not retried; treat the webhook as a low-latency hint and the status endpoints as the source of truth. The URL must be public HTTPS.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Public HTTPS URL to receive signed notification POSTs. Max 512 characters. Private/internal hosts are rejected. |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | |
| secret | No | Standard Webhooks signing secret (`whsec_...`). Shown only in this response — store it now. Rotate by re-registering. |
| signing | No | Always `standard-webhooks`. |
| registered | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses rich behavioral detail beyond the sparse annotations: registering replaces the existing webhook, rotates the secret, re-enables disabled registrations, sends a test delivery, notifies the account owner, times out after 10 seconds, and does not retry. It also documents the signing headers and one-time secret return. This fully informs the agent of side effects and operational constraints.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is longer than average but every paragraph adds distinct operational detail: registration semantics, signing format, failure/disabling behavior, and delivery timeout. Small redundancies such as 'free' and repeated HTTPS requirements exist, but the structure is logical and front-loaded with the core purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with one well-documented parameter and an output schema, the description is complete. It explains the returned secret, webhook payload shape, signature verification, replacement behavior, disable condition, timeout policy, and the relationship to status endpoints. An agent has everything needed to invoke and interpret this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the schema already documents the URL requirements. The description adds context about what kind of URL is acceptable ('your harness's inbound webhook endpoint, or a relay you poll') and reinforces that private/internal hosts are rejected. This goes beyond the schema without being redundant.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource: 'Registers (or replaces) an HTTPS webhook URL to receive the calling wallet's account notifications as signed POSTs.' This clearly differentiates it from sibling tools like get_webhook and delete_webhook. The scope and effect are unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context for when to use the tool: 'This closes the polling gap for agents: instead of re-fetching status endpoints, point this at any URL...' It also explains delivery limitations and directs agents to treat status endpoints as the source of truth. It does not explicitly name alternatives/exclusions, but the context is strong enough for an agent to decide.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
save_address_book_entryAIdempotentInspect
Save or rename a recipient
The saved recipient names your human manages on their dashboard, so a request like "send $20 to the coffee vendor" can be resolved to an address instead of asking them for it.
Free.
It operates only on the authenticated account's own book — there is no user parameter to pass.
A name is a label, not an instruction. agentWalletTransfer takes an address and deliberately does not accept a name: a rename between your human asking and you sending would otherwise move money somewhere they did not intend. When you resolve a name to an address, say the address back to them before sending.
The address is the entry's key, so saving one that is already saved renames it rather than creating a duplicate. That makes this safe to retry.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | The name to save it under. Sanitized and capped server-side (max 60 characters). | |
| address | Yes | The recipient's Solana address. |
Output Schema
| Name | Required | Description |
|---|---|---|
| name | No | |
| address | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond annotations (idempotentHint=true, readOnlyHint=false), it discloses that the address is the key, saving an existing address renames instead of duplicating, retries are safe, and the tool only touches the authenticated account's own book. It also warns that a name is a label, not an instruction, preventing misdirected transfers.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Structured with a bolded critical warning, short paragraphs, and no filler. Each sentence contributes either scoping, retry semantics, or safety guidance; 'Free' is minor but acceptable as context.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers scope, idempotency, relationship to transfer, and the no-user-parameter constraint. Output schema exists so return details are covered elsewhere; nothing an agent needs to call this safely is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema already documents both parameters at 100% coverage; description adds the key insight that address is the entry's unique key and explains how the two params interact during rename. This is meaningful semantic value beyond the schema, though not exhaustive.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opening line 'Save or rename a recipient' states a concrete verb and resource, and the rest clarifies it manages the human's address book for name-to-address resolution. It distinguishes itself from agentWalletTransfer by noting that transfer takes an address, not a name.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context: use it to persist/rename addresses so the human's dashboard can resolve labels, and it explicitly notes agentWalletTransfer does not accept names. It doesn't explicitly enumerate when to prefer sibling address-book tools like list_address_book or delete_address_book_entry, but the intended workflow is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_docsARead-onlyIdempotentInspect
Search the Laso Finance agent docs (SKILL.md and the full API reference). Returns the most relevant sections. Use this for anything the tool descriptions don't answer: auth flows, funding, fees, webhooks, error handling.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Search terms, e.g. fund managed wallet, or: gift card fees. |
Output Schema
| Name | Required | Description |
|---|---|---|
| note | No | Where to read the full docs when nothing matched. |
| results | No | Best-matching doc sections, most relevant first. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and idempotentHint=true, so the description need not repeat that. The description adds the scope of the search (SKILL.md and API reference) and that it returns sections, which is useful context but not substantial behavioral disclosure beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with the core purpose, then output, then usage guidance. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter read-only search tool with an output schema, the description covers purpose, usage context, and scope. It is complete enough for an agent to decide when and how to invoke it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema fully documents the query parameter with examples. The description adds no additional parameter semantics, but with 100% schema coverage the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool searches the Laso Finance agent docs, specifically SKILL.md and the full API reference, and returns the most relevant sections. This is a specific verb and resource that distinguishes it from sibling search tools like search_gift_cards and search_merchants.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when to use: 'for anything the tool descriptions don't answer', with examples like auth flows, funding, fees, webhooks, and error handling. This provides clear decision guidance for agents.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_gift_cardsARead-onlyIdempotentInspect
Search the gift card catalog
Browse and search available gift cards. Returns a list of gift card products with pricing, denomination, and catalog information. Use the laso_server_id from the results to order a card via GET /order-gift-card.
Every response includes a facets object listing the valid values for the category, currency, and country filters. The facets are computed from the full catalog, so a single unfiltered request (no query parameters) is enough to discover everything you can filter on.
This is a free endpoint — no x402 payment required.
| Name | Required | Description | Default |
|---|---|---|---|
| q | No | Search query to filter gift cards by name (e.g. "Amazon", "Uber") | |
| country | No | ISO 3166-1 alpha-2 country code to filter by (e.g. "US", "GB"). Returns gift cards available in that country, including borderless products that have no country restriction. | |
| category | No | Category to filter by (e.g. "ecommerce", "travel", "gaming"). See the `facets.categories` array in any response for the full list of valid values. | |
| currency | No | Currency code to filter by (e.g. "USD", "EUR") |
Output Schema
| Name | Required | Description |
|---|---|---|
| count | No | Number of results returned |
| facets | No | Valid filter values, computed from the full catalog. Use these to discover what you can pass to the `category`, `currency`, and `country` query parameters. |
| filters | No | |
| gift_cards | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds significant behavioral context beyond the annotations. While annotations already mark it as read-only and idempotent, the description discloses that every response includes a `facets` object with valid filter values, and that facets are computed from the full catalog, so an unfiltered request reveals all options. It also explicitly states the endpoint is free, a trait not covered by annotations. No contradictions with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and well-structured, with three short paragraphs. The first sentence front-loads the core purpose, the second paragraph explains the facets behavior without fluff, and the third is a single note about payment. Every sentence earns its place, and the layout aids quick comprehension.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given that the tool has an output schema (confirmed by context signals), the description does not need to detail every return field. It covers the essential behavioral aspects: return of a list with pricing/denomination/catalog info, the facets object for filter discovery, and the ordering workflow. This is complete for a search tool, and no critical missing information is apparent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 100% parameter coverage, so each parameter is already well-documented. The description adds extra value by explaining how to discover valid values for `category`, `currency`, and `country` via the `facets` object, and by noting that an unfiltered request yields all filters. This goes beyond the schema's static descriptions, providing actionable guidance for parameter usage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Search the gift card catalog' and 'Browse and search available gift cards.' It specifies the resource (gift cards) and the action (search/browse), and implicitly distinguishes itself from the sibling 'search_merchants' by focusing on gift card products. It also mentions the return of pricing, denomination, and catalog information, making the scope explicit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear usage guidance: it explains that results include a `laso_server_id` used to order a card via `GET /order-gift-card`, which directs the agent to a separate workflow. It also advises that a single unfiltered request is sufficient to discover all filter values via facets, offering a practical tip for exploring the catalog. Additionally, it notes that the endpoint is free (no x402 payment), which is a useful operational guideline.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_merchantsARead-onlyIdempotentInspect
Search merchant spend data
Search Laso's merchant database for confirmed spend data for a given card type. Returns whether the card was accepted, not accepted, or unknown at each merchant.
Use card_type to search by the USA prepaid card (Non-Reloadable U.S., the default) or the international prepaid card (Non-Reloadable International). USA searches exclude merchants with non-US country-code TLDs; international searches do not.
Important: This database only contains merchants where Laso users have previously attempted a transaction. A merchant not being listed, or being listed as unknown, does NOT mean the card won't work there — it just means it hasn't been tried yet. If a merchant is listed as accepted, you can confidently use the card there. If listed as not_accepted, the card will fail at that merchant.
Banking and money-transfer merchants are always returned as not_accepted with a restriction_note, whatever the transaction history shows. Spending there counts as a transfer of value and is not supported on any card.
| Name | Required | Description | Default |
|---|---|---|---|
| q | Yes | Search query — the merchant name to search for (e.g. "amazon", "netflix") | |
| card_type | No | Which card type to search acceptance for. Defaults to `Non-Reloadable U.S.` if omitted (preserves existing client behavior). Pass `Non-Reloadable International` to search for international prepaid card acceptance. | Non-Reloadable U.S. |
Output Schema
| Name | Required | Description |
|---|---|---|
| note | No | Important caveat about the data — this database only includes merchants where users have previously attempted transactions |
| count | No | Number of merchants returned |
| query | No | The search query that was used |
| card_type | No | The card type results are filtered for |
| merchants | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish read-only, idempotent, non-destructive behavior, and the description adds substantial context beyond them: the database only covers merchants previously attempted by Laso users, unknown/absent does not mean rejection, accepted is a confident signal, and banking/money-transfer merchants are always not_accepted with a restriction_note. It also discloses the TLD-filtering difference between card types — genuinely valuable behavioral detail.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose, then flows into parameter guidance, then the critical interpretation caveat, then the banking exception. Each block earns its place given the real risk of misinterpreting results, though the length is slightly more than a minimal search tool would require.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present and only two parameters, the description covers everything an agent needs to call the tool correctly and interpret the response safely: database scope, result semantics, the banking edge case, and card-type behavior. No critical gap remains for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so both q and card_type are already documented, which sets a baseline of 3. The description adds real functional meaning beyond the schema by explaining card_type's behavioral consequences (USA vs international TLD exclusion) and the semantic weight of the default, plus what q represents in the merchant-search context.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb-resource pair ('Search Laso's merchant database for confirmed spend data') and the concrete outcome: whether a card was accepted, not accepted, or unknown at each merchant. It is clearly distinguishable from sibling search tools (search_docs, search_gift_cards) and from get_card_data by anchoring on merchant-level acceptance results.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear, practical usage context: it explains how to pick card_type (USA vs international, with TLD-exclusion differences), and crucially clarifies how to interpret accepted / not_accepted / unknown results so the agent doesn't over-conclude. It does not explicitly name alternative tools or state when-not-to-use this one, which keeps it just below the top score.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
send_bank_paymentADestructiveInspect
Send dollars to a bank account
Pay USDC to send dollars to a bank account by ACH. The x402 USDC price is the requested amount plus a 0.25% transfer fee (with a $1.50 minimum fee). On-chain payment credits the calling wallet's Laso account balance via the standard deposit webhook; the callable then debits the gross amount and queues the transfer.
A bank destination is required first. destination_id comes from the banking callables: create the banking profile with createBankingProfile, register who is being paid with createBankingRecipient, and attach their bank account with addBankingDestination, which returns the id. List what you already have at GET /bank-recipients (free). See the bank accounts guide for the full setup.
Identity verification is required on the account that owns the banking profile, and only the human owner can complete it. createBankingProfile hands back a kycUrl when it is outstanding.
If the payout cannot be fulfilled (no approved banking profile, a destination that is not yours, an amount out of range), nothing is stranded: the USDC you paid has already credited your account balance. Fix the problem and retry, or recover it with POST /withdraw.
Settlement: ACH, normally 1-2 business days. Follow it with listBankingTransactions / getBankingTransaction.
Fee: 0.25% with a $1.50 minimum (included in the USDC price).
PAID ROUTE (11.50-50125 USD): the x402 USDC price is paid automatically from your managed agent wallet. Make sure the wallet exists and is funded first (get_agent_wallet).
| Name | Required | Description | Default |
|---|---|---|---|
| amount | Yes | USD delivered to the recipient's bank account (min $10, max $50,000). The x402 payment price is this amount plus a 0.25% fee (with a $1.50 minimum). | |
| destination_id | Yes | Bank destination to pay out to. Returned by `addBankingDestination`, and listed by `GET /bank-recipients`. |
Output Schema
| Name | Required | Description |
|---|---|---|
| auth | No | |
| message | No | |
| success | No | |
| user_id | No | |
| bank_payment | No | |
| callable_base_url | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover safety (destructive, non-readonly, non-idempotent), but the description adds critical behavioral details beyond them: the exact fee structure, the on-chain credit-then-debit flow, failure handling where USDC is credited and recoverable, ACH settlement timing, and the requirement to fund the agent wallet first.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The definition is front-loaded and well-structured with bold headings, and most sentences earn their place by covering prerequisites, failure modes, and fees. It is slightly verbose and repeats the fee (0.25% with $1.50 minimum) in multiple places, preventing a perfect score.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be described. The description fully covers the prerequisite setup, identity verification, failure recovery, settlement timing, fees, and wallet funding, leaving no significant gaps for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds procedural meaning for destination_id (how to obtain it via createBankingProfile, createBankingRecipient, and addBankingDestination) and clarifies that amount is the net USD delivered with fees added on top, which goes beyond the schema's brief parameter descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource ('Send dollars to a bank account') and clarifies the mechanism (USDC paid to send dollars via ACH). It distinguishes this from card and general payment siblings by explicitly requiring a bank destination and describing the ACH flow.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives extensive prerequisites (banking profile, recipient, destination, KYC verification) and failure recovery via POST /withdraw. However, it does not explicitly compare this tool to sibling alternatives like send_payment for the primary use case, leaving some routing inference to the agent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
send_feedbackAInspect
Send feedback about the API
Tell the humans running Laso what worked, what was confusing, and what you wish existed. It lands on their dashboard, so it is the best channel for API friction and feature requests.
Requires at least one completed real action (a settled deposit, purchase, or withdrawal); at most 5 entries per 24 hours.
| Name | Required | Description | Default |
|---|---|---|---|
| rating | No | A 1-5 satisfaction rating. Optional; ignored when not an integer in range. | |
| endpoint | No | Which API endpoint or route the feedback is about. Optional. Capped at 120 characters. | |
| feedback | Yes | The main free-text feedback. Required. Sanitized and capped server-side (max 2000 characters). | |
| how_it_went | No | How it went. Optional. Capped at 500 characters. | |
| what_they_want | No | What you were trying to do. Optional. Capped at 500 characters. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds meaningful behavioral context beyond annotations: the feedback lands on a human dashboard, there is a per-24-hour rate limit, and a real prior action is required. This is useful for an agent deciding whether and how often to call this tool. It doesn't cover authentication or side effects beyond emphasizing that it is a channel to humans, but it's still solidly transparent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three concise sentences front-load the core purpose, then add audience and constraints. Every sentence earns its place and there is no filler or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple feedback submission tool, the description covers purpose, audience, eligibility, and rate limits, while the input schema documents all parameters and an output schema exists. Nothing needed for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, with each parameter having a description and example, so the description doesn't need to restate parameter details. The prose about 'what worked, what was confusing, and what you wish existed' loosely maps to the optional free-text fields but adds no syntax-level meaning. A baseline 3 is appropriate since the schema carries the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('send feedback about the API') and the destination (the humans running Laso's dashboard). It also positions the tool as the channel for API friction and feature requests, which distinguishes it from all sibling tools that perform financial or account operations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly indicates when to use the tool (for feedback, friction, feature requests) and imposes concrete eligibility and rate-limit constraints (requires a completed real action, max 5 entries per 24 hours). It doesn't name alternatives or exclusions, but no comparable feedback tool appears among the siblings, so the guidance is adequate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
send_paymentADestructiveInspect
Send a payment via Venmo or PayPal
Pay USDC to send money to a Venmo or PayPal recipient. The x402 USDC price is the requested amount plus a 4.9% fee (with a $1.50 minimum fee). On-chain payment credits the calling wallet's Laso account balance via the standard deposit webhook; the callable then debits the gross amount and dispatches the payout.
Asynchronous. A dispatched payout answers 202 Accepted, not 200: the payment is recorded and handed to the payout provider, which settles it afterwards. Poll the returned status_url (GET /get-payment-status?payment_id=...) until state reaches a terminal value rather than treating the 202 as money received. A 200 means the opposite: nothing was dispatched because identity verification is required.
KYC required. The first time a wallet sends a Venmo or PayPal payout it must complete identity verification. If the wallet is not yet verified the response returns kyc_required: true and a kyc_url — open the URL, complete the flow, and retry. If you don't want to proceed, the credited account balance can be withdrawn with POST /withdraw.
Recipient details. For Venmo, recipient_id is the recipient's 10-digit U.S. phone number, and the first and last name are optional. No email is needed. For PayPal, recipient_id is the recipient's PayPal email, which also serves as recipient_email (so recipient_email is optional), and the first and last name are required.
Fee: 4.9% with a $1.50 minimum (included in the USDC price).
PAID ROUTE (6.50-1049 USD): the x402 USDC price is paid automatically from your managed agent wallet. Make sure the wallet exists and is funded first (get_agent_wallet).
| Name | Required | Description | Default |
|---|---|---|---|
| amount | Yes | USD amount to send to the recipient (min $5, max $1,000). The x402 payment price is this amount plus a 4.9% fee (with a $1.50 minimum). | |
| platform | Yes | Payment platform. | |
| recipient_id | Yes | Recipient identifier. For Venmo: 10-digit U.S. phone number. For PayPal: email address. | |
| recipient_email | No | PayPal only. Recipient's email address; defaults to recipient_id (the PayPal email). Ignored for Venmo. | |
| recipient_last_name | No | Recipient's last name (English letters A-Z and a-z only). Required for PayPal, optional for Venmo. | |
| recipient_first_name | No | Recipient's first name (English letters A-Z and a-z only). Required for PayPal, optional for Venmo. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations (destructiveHint/openWorld/idempotent) by explaining the 202-vs-200 distinction, the async polling contract via status_url, the on-chain credit/deposit webhook flow, the fee math, and the KYC escape hatch. An agent knows exactly what state the money is in.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Long but tightly organized with bold lead-ins that let an agent skim to the async, KYC, recipient, and fee sections. Front-loaded with the core action, though the fee is stated twice (top and bottom).
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex, mutating, cross-chain payment tool this covers everything an agent needs before calling: prerequisites, async semantics, failure/KYC branches, and per-platform recipient rules. The output schema handles return shape, so no gap remains.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the field descriptions already document the Venmo phone/PayPal email rules and the required/optional name fields. The description restates these per-platform rules but adds little the schema does not already carry, so baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (send a payment) and names the two supported networks. This cleanly separates it from sibling send_bank_payment and the order_/top-up tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives strong procedural context: KYC must be completed before the first payout, the wallet must exist and be funded, and if the user declines they can withdraw instead. It does not explicitly say when to prefer this over send_bank_payment, so it stops short of a full routing rule.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
start_signupAInspect
Start a signup for a human with no Laso account
Begins account creation for a human who does not have a Laso account yet. Requires no authentication, because the caller has no account.
This does not create the account. An agent cannot: the account is created by Privy in the human's own browser, so it belongs to them and not to their agent. What this returns is a claim_url to hand over.
Give your human the claim_url verbatim in your very next reply (send message_for_human if unsure what to say), and do not open it yourself. Then poll GET /signup-status, which holds the connection open until they finish and hands you your lasoak_ API key.
Rate limited per IP.
| Name | Required | Description | Default |
|---|---|---|---|
| label | No | Optional label recorded on the minted API key so your human can tell keys apart. | |
| agent_name | No | Your name, shown to your human on the claim screen and recorded as the connected agent. |
Output Schema
| Name | Required | Description |
|---|---|---|
| claim_url | No | Give this to your human verbatim. Never open it yourself. |
| claim_code | No | The code inside claim_url. Pass it back to /signup-status alongside claim_token. |
| expires_at | No | Epoch ms when the claim link expires. |
| expires_in | No | Seconds until the claim link expires (86400). |
| next_steps | No | |
| claim_token | No | Your receipt for this signup. Shown once; store it. Exchanged at /signup-status for your API key. |
| message_for_human | No | A ready-to-send reply containing the link. Send this as your next message. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no useful annotations (all hints false), the description carries the full burden and does so strongly: it discloses no authentication required, non-creation of the account, Privy's browser-side ownership, the claim_url return, the polling behavior, and per-IP rate limiting. This is rich behavioral context beyond the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded and mostly information-dense, with useful operational details. The first two sentences are somewhat redundant ('Start a signup' / 'Begins account creation'), but the rest of the description earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with two optional parameters, an output schema, and no required inputs, the description covers everything needed to invoke and follow up correctly: auth expectations, what is returned, what the agent should do next, and rate-limit behavior. Nothing critical is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents both optional parameters. The description adds no parameter-specific detail beyond the schema, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource: 'Start a signup for a human with no Laso account' and clarifies it begins account creation without creating the account itself. This clearly distinguishes it from related signup/auth/API-key tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly states the condition for use ('human with no Laso account') and gives a clear follow-up workflow: hand over the claim_url, do not open it, and poll GET /signup-status. It does not explicitly name alternatives for humans who already have accounts, but the condition is clear enough.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
submit_banking_applicationAInspect
Submit the application
Submits the completed application for review. If the partner rejects it as incomplete, the reply says what is still missing rather than failing opaquely.
Free.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds meaningful behavioral detail beyond the annotations: incomplete submissions are rejected with a reply explaining what is missing rather than an opaque failure. The standalone 'Free' also signals cost behavior. It does not mention side effects such as locking the application or changing its status, but the disclosed failure behavior is valuable.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded with the core action. The opening line 'Submit the application' is somewhat redundant with the tool name, and the standalone 'Free' is terse, but the total length is appropriate and the key behavioral detail earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter tool with an output schema already present, the description covers the main action, the prerequisite, and an important failure mode. It does not explain what happens after a successful submission or repeated submissions, but those gaps are minor given the tool's simplicity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has zero parameters, so there is no parameter detail for the description to provide. The description correctly adds no parameter information, and none is needed for an agent to call this tool correctly.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a concrete verb and resource: 'Submits the completed application for review.' The action is clearly distinct from sibling tools like get_banking_application, update_banking_application_details, and upload_banking_document, even without naming them explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'completed application' gives clear context for when the tool is appropriate: only after the application has been finished. It does not explicitly state when not to use it or name alternative tools, but the submission-for-review framing provides enough usage guidance for an agent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_banking_application_detailsAIdempotentInspect
Answer application questions
Submits answers to the non-identity application questions read from getBankingApplication. Call as many times as needed; each call merges.
Free.
| Name | Required | Description | Default |
|---|---|---|---|
| details | Yes | The answers to submit, keyed by the field names `getBankingApplication` reported as outstanding. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate idempotent and non-destructive behavior, but the description adds the key merge semantics and the fact that calls are free. It also makes clear that partial updates are acceptable. There is no contradiction with the provided annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and every sentence earns its place: purpose, merge behavior, and cost. The one-word 'Free.' is terse but communicates a material constraint. No fluff or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with one nested parameter and a schema that fully describes that parameter, the description plus schema provides enough to call it correctly. A small gap is that it does not explicitly distinguish this from submit_banking_application or describe what happens after all questions are answered, so it is not quite a 5.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema description covers the only parameter fully, explaining that details are keyed by the field names getBankingApplication reported as outstanding. The tool description reinforces the relationship to getBankingApplication but does not add substantial new semantic detail beyond the schema, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action ('Submits answers') and resource ('non-identity application questions read from getBankingApplication'), clearly identifying this as a partial update tool rather than a full application submission. The 'non-identity' qualifier and the merge behavior help distinguish it from siblings like submit_banking_application.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is tied to getBankingApplication output and repeated calls are explicitly supported ('Call as many times as needed; each call merges'). However, it does not explicitly name alternative tools such as submit_banking_application or state when not to use this tool, so it falls just short of full guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_banking_destinationAIdempotentInspect
Rename a destination
Sets or clears a destination's nickname. This is the only editable field: bank details are immutable at the partner, so anything else wrong means deleting the recipient and creating a new one.
Free.
| Name | Required | Description | Default |
|---|---|---|---|
| nickname | Yes | The new nickname. An empty string clears it. | |
| destinationId | Yes | The destination to rename. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds the constraint that bank details are immutable and describes the fallback of deleting/recreating. It does not contradict the annotations (readOnlyHint false, destructiveHint false, idempotentHint true) and adds context beyond them. The 'Free.' note is unexplained but harmless.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is mostly concise and front-loads the action, but the trailing 'Free.' is ambiguous and does not earn its place. The title is repeated from annotations, adding slight redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple 2-parameter tool with an output schema and annotations covering safety, the description sufficiently covers scope, limitations, and alternatives. No critical information is missing for correct usage.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already documents both parameters, including that an empty string clears the nickname. The description adds no new parameter-level meaning, so it does not exceed the baseline of 3 given 100% schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb ('sets or clears') and the resource ('destination's nickname'), making it distinct from other update tools. It also notes this is the only editable field, differentiating it from siblings like update_payment_recipient or delete_banking_recipient.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly explains when not to use the tool: bank details are immutable, so any other change requires deleting and recreating the recipient. This gives clear guidance on alternatives, though it does not name specific sibling tools directly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_payment_recipientAIdempotentInspect
Rename or archive a saved recipient (free)
Renames a saved Venmo or PayPal recipient, archives it, or both. Provide at least one of display_name or archived.
Archiving hides an entry from the default list while keeping its history, which is the reversible way to retire a recipient. Prefer it over DELETE.
| Name | Required | Description | Default |
|---|---|---|---|
| archived | No | Must be a boolean. A wrong type returns a terminal 400 with code `invalid_archived`. | |
| platform | Yes | Payment platform the recipient is saved under. | |
| display_name | No | Must be a string. A wrong type returns a terminal 400 with code `invalid_display_name`. | |
| recipient_id | Yes | The entry's `recipient_id` from `GET /payment-recipients` (an opaque id, not the phone number or email). |
Output Schema
| Name | Required | Description |
|---|---|---|
| user_id | No | |
| archived | No | |
| platform | No | |
| display_name | No | |
| recipient_id | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=false, destructiveHint=false, and idempotentHint=true. The description adds meaningful context beyond annotations by explaining that archiving hides an entry from the default list while preserving history, making it reversible. It clearly communicates the mutation is non-destructive and reversible, aligning with the annotations. No contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Concise and front-loaded: the first sentence states the purpose and scope, the second explains the constraint, and the third gives the behavioral nuance about archiving. No wasted words; every sentence adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given an output schema exists, return values are already covered. The description covers the key usage constraint, the behavior of archiving, and differentiates from DELETE. It is complete for an agent to correctly invoke the tool without missing critical information.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. The description adds value by stating the 'at least one of display_name or archived' constraint, which is not captured in the schema's required fields. It also explains the semantics of archived (hides from list, keeps history), going beyond the schema's simple type descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('rename or archive') and resource ('saved recipient'), explicitly mentions Venmo/PayPal, and distinguishes itself from the DELETE sibling by recommending archiving over deletion. An agent can immediately understand what the tool does and how it differs.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides a clear usage constraint: must provide at least one of display_name or archived. Explicitly recommends archiving over DELETE for retiring recipients, which is a direct alternative. However, it does not discuss when to use this versus list or other tools, though the context implies it's for existing recipients only.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
upload_banking_documentAInspect
Upload a proof-of-address document
Attaches a proof-of-address document to the banking application, for the cases where the partner asks for one. The application must already exist and have an individual on it, so complete the application first.
Two things reject uploads that otherwise look fine. A .jpg file must be sent as fileType: "jpeg" — "jpg" is refused. And the partner caps the decoded size at 10MB, even though their own upload page advertises 20MB; oversized files are rejected here before the round-trip.
fileContent accepts either a bare base64 string or a data: URL, so a browser FileReader.readAsDataURL result can be passed through unchanged.
Free.
| Name | Required | Description | Default |
|---|---|---|---|
| country | Yes | The document's country, ISO 3166-1 alpha-2. | |
| fileType | Yes | The file's format. Send a .jpg as `jpeg`. | |
| filename | No | The file's name. | |
| fileContent | Yes | The file, base64-encoded. A `data:` URL is also accepted. Decoded size must be 10MB or less. | |
| documentType | Yes | The kind of document. |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | No | |
| documentId | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (which only indicate non-read-only, non-destructive), the description discloses two critical behavioral quirks: the .jpg must be sent as 'jpeg' and the decoded size limit is 10MB despite the partner's page advertising 20MB. It also explains fileContent accepts bare base64 or data URL. These are exactly the kind of hidden behaviors an agent needs to know.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-organized: it opens with the purpose, then details prerequisites and behavioral caveats, then explains the fileContent flexibility. Every sentence earns its place, and the most critical pitfalls (jpg vs. jpeg, size cap) are surfaced prominently. No filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has an output schema (not shown) and the input schema is fully covered, the description fills the essential gaps: prerequisites, format constraints, and size limits. An agent can call this tool correctly without needing additional information, making it complete for its complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so all parameters are described. The description adds important nuances: it reinforces the jpg/jpeg mapping and the size constraint, and explains the flexibility of fileContent (data URL accepted). This adds meaning beyond the schema's basic field descriptions, helping the agent construct valid calls.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Upload') and resource ('proof-of-address document') and clarifies it attaches to an existing banking application. It clearly distinguishes this tool from siblings by its unique purpose, even though it doesn't name alternatives. The purpose is unambiguous and actionable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly mentions the use case ('for the cases where the partner asks for one') and gives a clear prerequisite: the application must already exist with an individual on it. It also instructs to complete the application first, providing concrete context for when to invoke this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
withdrawADestructiveInspect
Withdraw from account balance
Initiate a withdrawal from the user's account balance. The USDC is sent on Solana to the solana_address you supply; the destination is never inferred, so the address is required.
This is an asynchronous operation. A successful call answers 202 Accepted: the withdrawal is created in a pending state and sent within a few minutes. Poll the returned status_url (GET /get-withdrawal-status?withdrawal_id=...) until state reaches a terminal value rather than treating the 202 as completion.
| Name | Required | Description | Default |
|---|---|---|---|
| amount | Yes | Amount to withdraw in USD | |
| solana_address | Yes | Solana wallet address that receives the USDC. Must be a valid base58 Solana address. |
Output Schema
| Name | Required | Description |
|---|---|---|
| success | No | |
| status_url | No | Absolute URL to poll for this withdrawal's state. Always present, including on an idempotent replay, so prefer it over the `Location` header. |
| withdrawal | No | A withdrawal record. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag destructiveHint=true, readOnlyHint=false and idempotentHint=false, but the description adds substantial behavior beyond them: the operation is asynchronous, returns 202 Accepted, creates a pending withdrawal settled within minutes, and requires polling the returned status_url. That is exactly the kind of timing and completion semantics annotations cannot convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short paragraphs, front-loaded with the core action, then the asset/address constraint, then the async contract. Every sentence carries information an agent needs; there is no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an async, destructive, non-idempotent money-movement tool with two fully documented params and an output schema, the description covers everything the agent needs: what it does, the required destination, and how to determine completion via status_url. Nothing material is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds meaning beyond the schema: it states the address is mandatory because the destination is never inferred, and that the recipient receives USDC on Solana. That clarifies the address parameter's intent rather than just restating it.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (withdraw) and resource (account balance) and immediately clarifies the asset and rail: USDC sent on Solana to a supplied address. This distinguishes it from the sibling withdraw_card_balance and from send_payment without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explains the key usage constraint (the destination is never inferred, so solana_address is required) and prescribes the follow-up workflow of polling status_url until terminal state rather than treating 202 as completion. It doesn't explicitly name an alternative sibling to route to, which keeps it short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
withdraw_card_balanceADestructiveInspect
Withdraw from a reloadable card balance
Move unspent money off the account holder's reloadable card. The balance behind a reloadable card is held by the card issuer, and this asks the issuer to pay amount of it out as USDC on Base to the destination_address you supply. It is the reverse of GET /fund-card-balance, and free: the money is the holder's own, and Laso moves nothing itself.
Base only. The issuer pays on Base and nowhere else, so the destination must be a Base wallet you control. A Laso managed agent wallet holds USDC on Solana and cannot receive this. The card deposit address from GET /get-card-deposit-address is not a valid destination either.
Not instant. The issuer processes payouts manually, usually within 1-3 business days, and emails the account holder when the payout is sent. The response carries the issuer's withdrawal_id; there is no status route to poll. The request is recorded as a withdrawal event under card_events in GET /list-card-transactions, and the balance from GET /get-card-deposit-address drops once it is paid.
Amount: $2 to $10,000, and no more than the balance the issuer can release. Withdrawals the issuer has not paid yet still count against the balance, so a second request can only take what remains.
Confirm the amount and destination with the account holder before calling this. A linked card issuer account is required; the holder sets it up at https://laso.finance/agent/dashboard/verified/card.
| Name | Required | Description | Default |
|---|---|---|---|
| amount | Yes | USD to withdraw from the card balance (min $2, max $10,000). | |
| destination_address | Yes | The 0x-prefixed Base wallet address that receives the USDC. Must be one you control; Base only. |
Output Schema
| Name | Required | Description |
|---|---|---|
| note | No | Timing and where to see the request afterwards. |
| asset | No | |
| amount | No | USD the issuer will pay out. |
| status | No | Always `requested`: the issuer has accepted the request and will pay it out manually. |
| network | No | |
| withdrawal_id | No | The card issuer's reference for this payout request. Quote it to support; it also appears on the matching `withdrawal` card event. |
| destination_address | No | The Base address the USDC goes to. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark destructiveHint=true and idempotentHint=false, and the description adds substantial behavioral context beyond that: payouts are manual and take 1-3 business days, there is no status route to poll, the request is recorded as a withdrawal event, and pending withdrawals count against the balance. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well-structured with bolded section headers and no filler; every paragraph serves a concrete purpose. It is slightly longer than strictly necessary and repeats a few schema-covered facts such as the amount range and Base-only requirement, but that redundancy is defensible for a destructive financial operation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a high-stakes, externally-settled mutation, the description covers prerequisites, destination constraints, timing, ledger visibility, and balance semantics. Since an output schema exists, not describing the response shape in prose is acceptable.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although schema coverage is 100%, the description adds meaning beyond the schema: the amount is bounded by the issuer-releasable balance including pending withdrawals, and the destination must be a Base wallet you control, explicitly excluding Solana agent wallets and the card deposit address.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource: 'Withdraw from a reloadable card balance' and immediately defines the operation as moving unspent money off the card via the issuer paying USDC on Base. It is explicitly contrasted with GET /fund-card-balance, making the tool's purpose distinguishable from a key sibling.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
States clear when-to-use and when-not-to-use conditions: Base only; a Solana agent wallet cannot receive this; the card deposit address is not a valid destination. It also names the reverse operation, fund-card-balance, and gives a prerequisite: a linked card issuer account is required.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
1 tool update
- Changed
pay_x402_endpoint2 fields changed- changed
Input schema / properties / expected_asset / descriptionPrevious value: -"Refuse to settle in any other asset (e.g. a USDC mint/contract address)."New value: +"Refuse to settle in any other asset (e.g. a USDC mint/contract address; USDC on Base is 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913)." - changed
Input schema / properties / expected_network / descriptionPrevious value: -"Refuse to settle on any other network (CAIP-2 id)."New value: +"Refuse to settle on any other network (CAIP-2 id): eip155:8453 for Base, solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp for Solana. Pin it when an endpoint offers both, to choose which wallet pays."
1 tool update
- Changed
get_payment_status1 field changed- changed
Output schema / anyOfPrevious value: -[ - { - "properties": { - "payment": { - "description": "One Venmo or PayPal payout sent from this account.", - "properties": { - "amount_pre_fees": { - "description": "Dollars the recipient receives.", - "type": [ - "number", - "null" - ] - }, - "amount_with_fees": { - "description": "Dollars debited from the account balance, fee included.", - "type": [ - "number", - "null" - ] - }, - "fees_paid": { - "type": [ - "number", - "null" - ] - }, - "id": { - "description": "Pass as `payment_id` to fetch this payout on its own.", - "type": [ - "string", - "null" - ] - }, - "platform": { - "description": "One of: venmo, paypal.", - "type": [ - "string", - "null" - ] - }, - "recipient_first_name": { - "type": [ - "string", - "null" - ] - }, - "recipient_id": { - "description": "The saved recipient this went to, as returned by `GET /payment-recipients`.", - "type": [ - "string", - "null" - ] - }, - "recipient_last_name": { - "type": [ - "string", - "null" - ] - }, - "state": { - "description": "`queued` and `in-process` are still in flight. Absent on payouts sent before state tracking existed. One of: queued, in-process, complete, failed, cancelled.", - "type": [ - "string", - "null" - ] - }, - "state_updated_at": { - "description": "Milliseconds since the epoch when `state` last changed.", - "type": [ - "number", - "null" - ] - }, - "timestamp": { - "description": "Milliseconds since the epoch when the payout was sent.", - "type": [ - "number", - "null" - ] - }, - "timestamp_readable": { - "type": [ - "string", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - } - }, - "type": "object" - }, - { - "properties": { - "payments": { - "items": { - "description": "One Venmo or PayPal payout sent from this account.", - "properties": { - "amount_pre_fees": { - "description": "Dollars the recipient receives.", - "type": [ - "number", - "null" - ] - }, - "amount_with_fees": { - "description": "Dollars debited from the account balance, fee included.", - "type": [ - "number", - "null" - ] - }, - "fees_paid": { - "type": [ - "number", - "null" - ] - }, - "id": { - "description": "Pass as `payment_id` to fetch this payout on its own.", - "type": [ - "string", - "null" - ] - }, - "platform": { - "description": "One of: venmo, paypal.", - "type": [ - "string", - "null" - ] - }, - "recipient_first_name": { - "type": [ - "string", - "null" - ] - }, - "recipient_id": { - "description": "The saved recipient this went to, as returned by `GET /payment-recipients`.", - "type": [ - "string", - "null" - ] - }, - "recipient_last_name": { - "type": [ - "string", - "null" - ] - }, - "state": { - "description": "`queued` and `in-process` are still in flight. Absent on payouts sent before state tracking existed. One of: queued, in-process, complete, failed, cancelled.", - "type": [ - "string", - "null" - ] - }, - "state_updated_at": { - "description": "Milliseconds since the epoch when `state` last changed.", - "type": [ - "number", - "null" - ] - }, - "timestamp": { - "description": "Milliseconds since the epoch when the payout was sent.", - "type": [ - "number", - "null" - ] - }, - "timestamp_readable": { - "type": [ - "string", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - }, - "type": [ - "array", - "null" - ] - } - }, - "type": "object" - } -]New value: +[ + { + "properties": { + "payment": { + "description": "One Venmo or PayPal payout sent from this account.", + "properties": { + "amount_pre_fees": { + "description": "Dollars the recipient receives.", + "type": [ + "number", + "null" + ] + }, + "amount_with_fees": { + "description": "Dollars debited from the account balance, fee included.", + "type": [ + "number", + "null" + ] + }, + "fees_paid": { + "type": [ + "number", + "null" + ] + }, + "id": { + "description": "Pass as `payment_id` to fetch this payout on its own.", + "type": [ + "string", + "null" + ] + }, + "platform": { + "description": "One of: venmo, paypal.", + "type": [ + "string", + "null" + ] + }, + "recipient_first_name": { + "type": [ + "string", + "null" + ] + }, + "recipient_id": { + "description": "The saved recipient this went to, as returned by `GET /payment-recipients`.", + "type": [ + "string", + "null" + ] + }, + "recipient_last_name": { + "type": [ + "string", + "null" + ] + }, + "state": { + "description": "`queued`, `awaiting-funding` and `in-process` are still in flight. `awaiting-funding` means the payout was debited and accepted but is delayed on our side before it reaches Venmo or PayPal, usually until the next business day. Absent on payouts sent before state tracking existed. One of: queued, awaiting-funding, in-process, complete, failed, cancelled.", + "type": [ + "string", + "null" + ] + }, + "state_updated_at": { + "description": "Milliseconds since the epoch when `state` last changed.", + "type": [ + "number", + "null" + ] + }, + "timestamp": { + "description": "Milliseconds since the epoch when the payout was sent.", + "type": [ + "number", + "null" + ] + }, + "timestamp_readable": { + "type": [ + "string", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + } + }, + "type": "object" + }, + { + "properties": { + "payments": { + "items": { + "description": "One Venmo or PayPal payout sent from this account.", + "properties": { + "amount_pre_fees": { + "description": "Dollars the recipient receives.", + "type": [ + "number", + "null" + ] + }, + "amount_with_fees": { + "description": "Dollars debited from the account balance, fee included.", + "type": [ + "number", + "null" + ] + }, + "fees_paid": { + "type": [ + "number", + "null" + ] + }, + "id": { + "description": "Pass as `payment_id` to fetch this payout on its own.", + "type": [ + "string", + "null" + ] + }, + "platform": { + "description": "One of: venmo, paypal.", + "type": [ + "string", + "null" + ] + }, + "recipient_first_name": { + "type": [ + "string", + "null" + ] + }, + "recipient_id": { + "description": "The saved recipient this went to, as returned by `GET /payment-recipients`.", + "type": [ + "string", + "null" + ] + }, + "recipient_last_name": { + "type": [ + "string", + "null" + ] + }, + "state": { + "description": "`queued`, `awaiting-funding` and `in-process` are still in flight. `awaiting-funding` means the payout was debited and accepted but is delayed on our side before it reaches Venmo or PayPal, usually until the next business day. Absent on payouts sent before state tracking existed. One of: queued, awaiting-funding, in-process, complete, failed, cancelled.", + "type": [ + "string", + "null" + ] + }, + "state_updated_at": { + "description": "Milliseconds since the epoch when `state` last changed.", + "type": [ + "number", + "null" + ] + }, + "timestamp": { + "description": "Milliseconds since the epoch when the payout was sent.", + "type": [ + "number", + "null" + ] + }, + "timestamp_readable": { + "type": [ + "string", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + "type": [ + "array", + "null" + ] + } + }, + "type": "object" + } +]
1 tool update
- Changed
fund_card_balance2 fields changed- changed
Input schema / properties / amount / descriptionPrevious value: -"USD of USDC to load onto the card balance (min $5, max $1,000). The x402 price equals this amount; Laso absorbs the bridge cost."New value: +"USD of USDC to load onto the card balance (min $5, max $10,000). The x402 price equals this amount; Laso absorbs the bridge cost." - changed
Input schema / properties / amount / maximumPrevious value: -1000New value: +10000
2 tool updates
- Added
get_pricing - Added
get_supported_countries
1 tool update
- Changed
get_version2 fields changed- added
Output schema / properties / api_versionAdded value: +{ + "description": "Version of the API contract itself (this description's `info.version`). Moves only on a breaking change, unlike `docs_version`. Also sent on every response as `X-Laso-Api-Version`.", + "type": [ + "string", + "null" + ] +} - added
Output schema / properties / versioningAdded value: +{ + "description": "The versioning and deprecation policy in machine-readable form: which header carries the version, what counts as an additive versus a breaking change, and how a retirement is signalled.", + "type": [ + "object", + "null" + ] +}
4 tool updates
- Added
buy_with_saved_card - Added
get_purchase_conversation - Added
get_purchase_turn - Changed
get_saved_cards1 field changed- added
Output schema / properties / blockerAdded value: +{ + "description": "Present only when the holder finished saving a card but it is not readable yet. `needs_code`: they saved it on a card account they already had, and confirm it once with a one-time code in the dashboard. `linked_elsewhere`: the card account they unlocked is linked to another Laso account. Relay `note`; sending another link does not help with `needs_code`. One of: needs_code, linked_elsewhere.", + "type": [ + "string", + "null" + ] +}
3 tool updates
- Removed
buy_with_saved_card - Removed
get_purchase_conversation - Removed
get_purchase_turn
1 tool update
- Changed
agent_wallet_transfer2 fields changed- changed
Input schema / properties / destination_address / descriptionPrevious value: -"Solana address to send the USDC to."New value: +"Address to send the USDC to: a Solana address, or a 0x address when destination_network is base." - added
Input schema / properties / destination_networkAdded value: +{ + "description": "Chain the destination address is on (default solana). base delivers native USDC on Base.", + "enum": [ + "solana", + "base" + ], + "type": "string" +}
3 tool updates
- Added
buy_with_saved_card - Added
get_purchase_conversation - Added
get_purchase_turn
1 tool update
- Changed
order_intl_card1 field changed- changed
Input schema / properties / amount / descriptionPrevious value: -"On-card USD amount (min $100, max $1,000). Must be a whole dollar amount: the issuer only issues whole-dollar cards. The x402 payment is this amount plus a 3.8% fee."New value: +"On-card USD amount (min $100, max $1,000 regardless of the fee rate). Must be a whole dollar amount: the issuer only issues whole-dollar cards. The x402 payment is this amount plus a 3.8% fee, or less during a fee promotion."
2 tool updates
- Changed
send_payment1 field changed- changed
Output schema / anyOfPrevious value: -[ - { - "properties": { - "amount": { - "type": [ - "number", - "null" - ] - }, - "auth": { - "properties": { - "expires_in": { - "description": "Token lifetime in seconds", - "type": [ - "string", - "null" - ] - }, - "id_token": { - "description": "ID token — use as Bearer token for Laso Finance APIs", - "type": [ - "string", - "null" - ] - }, - "refresh_token": { - "description": "Use with POST /auth (grant_type=refresh_token) to get a new id_token when it expires", - "type": [ - "string", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - }, - "callable_base_url": { - "type": [ - "string", - "null" - ] - }, - "message": { - "type": [ - "string", - "null" - ] - }, - "platform": { - "description": "One of: venmo, paypal.", - "type": [ - "string", - "null" - ] - }, - "recipient_id": { - "type": [ - "string", - "null" - ] - }, - "state": { - "description": "Payment lifecycle state (e.g. `in-process`, `queued`).", - "type": [ - "string", - "null" - ] - }, - "success": { - "type": [ - "boolean", - "null" - ] - }, - "user_id": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - { - "properties": { - "amount": { - "type": [ - "number", - "null" - ] - }, - "auth": { - "properties": { - "expires_in": { - "description": "Token lifetime in seconds", - "type": [ - "string", - "null" - ] - }, - "id_token": { - "description": "ID token — use as Bearer token for Laso Finance APIs", - "type": [ - "string", - "null" - ] - }, - "refresh_token": { - "description": "Use with POST /auth (grant_type=refresh_token) to get a new id_token when it expires", - "type": [ - "string", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - }, - "callable_base_url": { - "type": [ - "string", - "null" - ] - }, - "kyc_required": { - "description": "One of: true.", - "type": [ - "boolean", - "null" - ] - }, - "kyc_url": { - "description": "URL the wallet owner must open to complete identity verification. No payout was sent, but the x402 payment you made was still credited to your Laso account balance. After verifying, retry /send-payment to dispatch the payout, or call POST /withdraw to pull the credited USDC back to your wallet.", - "type": [ - "string", - "null" - ] - }, - "message": { - "description": "Human-readable explanation of the KYC requirement and how to recover the credited funds via retry or POST /withdraw.", - "type": [ - "string", - "null" - ] - }, - "platform": { - "description": "One of: venmo, paypal.", - "type": [ - "string", - "null" - ] - }, - "recipient_id": { - "type": [ - "string", - "null" - ] - }, - "user_id": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - } -]New value: +[ + { + "properties": { + "amount": { + "type": [ + "number", + "null" + ] + }, + "auth": { + "properties": { + "expires_in": { + "description": "Token lifetime in seconds", + "type": [ + "string", + "null" + ] + }, + "id_token": { + "description": "ID token — use as Bearer token for Laso Finance APIs", + "type": [ + "string", + "null" + ] + }, + "refresh_token": { + "description": "Use with POST /auth (grant_type=refresh_token) to get a new id_token when it expires", + "type": [ + "string", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + "callable_base_url": { + "type": [ + "string", + "null" + ] + }, + "kyc_required": { + "description": "One of: true.", + "type": [ + "boolean", + "null" + ] + }, + "kyc_url": { + "description": "URL the wallet owner must open to complete identity verification. No payout was sent, but the x402 payment you made was still credited to your Laso account balance. After verifying, retry /send-payment to dispatch the payout, or call POST /withdraw to pull the credited USDC back to your wallet.", + "type": [ + "string", + "null" + ] + }, + "message": { + "description": "Human-readable explanation of the KYC requirement and how to recover the credited funds via retry or POST /withdraw.", + "type": [ + "string", + "null" + ] + }, + "platform": { + "description": "One of: venmo, paypal.", + "type": [ + "string", + "null" + ] + }, + "recipient_id": { + "type": [ + "string", + "null" + ] + }, + "user_id": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "properties": { + "amount": { + "type": [ + "number", + "null" + ] + }, + "auth": { + "properties": { + "expires_in": { + "description": "Token lifetime in seconds", + "type": [ + "string", + "null" + ] + }, + "id_token": { + "description": "ID token — use as Bearer token for Laso Finance APIs", + "type": [ + "string", + "null" + ] + }, + "refresh_token": { + "description": "Use with POST /auth (grant_type=refresh_token) to get a new id_token when it expires", + "type": [ + "string", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + "callable_base_url": { + "type": [ + "string", + "null" + ] + }, + "message": { + "type": [ + "string", + "null" + ] + }, + "payment_id": { + "description": "Id of the payout record just created. Pass it to `GET /get-payment-status?payment_id=...` to follow this specific payout.", + "type": [ + "string", + "null" + ] + }, + "platform": { + "description": "One of: venmo, paypal.", + "type": [ + "string", + "null" + ] + }, + "recipient_id": { + "type": [ + "string", + "null" + ] + }, + "state": { + "description": "Payment lifecycle state (e.g. `in-process`, `queued`).", + "type": [ + "string", + "null" + ] + }, + "status_url": { + "description": "Absolute URL to poll for this payout's state. Always present, so prefer it over the `Location` header.", + "type": [ + "string", + "null" + ] + }, + "success": { + "type": [ + "boolean", + "null" + ] + }, + "user_id": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + } +]
- Changed
withdraw1 field changed- added
Output schema / properties / status_urlAdded value: +{ + "description": "Absolute URL to poll for this withdrawal's state. Always present, including on an idempotent replay, so prefer it over the `Location` header.", + "type": [ + "string", + "null" + ] +}
2 tool updates
- Added
create_saved_card_link - Added
get_saved_cards
1 tool update
- Changed
send_payment4 fields changed- changed
Input schema / properties / recipient_email / descriptionPrevious value: -"Recipient's email address. Required for Venmo. Optional for PayPal, where it defaults to recipient_id (the PayPal email)."New value: +"PayPal only. Recipient's email address; defaults to recipient_id (the PayPal email). Ignored for Venmo." - changed
Input schema / properties / recipient_first_name / descriptionPrevious value: -"Recipient's first name (English letters A-Z and a-z only)."New value: +"Recipient's first name (English letters A-Z and a-z only). Required for PayPal, optional for Venmo." - changed
Input schema / properties / recipient_last_name / descriptionPrevious value: -"Recipient's last name (English letters A-Z and a-z only)."New value: +"Recipient's last name (English letters A-Z and a-z only). Required for PayPal, optional for Venmo." - changed
Input schema / requiredPrevious value: -[ - "amount", - "platform", - "recipient_id", - "recipient_first_name", - "recipient_last_name" -]New value: +[ + "amount", + "platform", + "recipient_id" +]
63 tool updates
- Changed
add_banking_destination2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "type": "object" +}
- Changed
agent_wallet_transfer2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "type": "object" +}
- Changed
announce_connection2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "type": "object" +}
- Changed
cancel_intl_order2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "card_id": { + "type": [ + "string", + "null" + ] + }, + "message": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" +}
- Changed
create_agent_api_key2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "type": "object" +}
- Changed
create_agent_wallet2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "type": "object" +}
- Changed
create_banking_account2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "type": "object" +}
- Changed
create_banking_profile2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "type": "object" +}
- Changed
create_banking_recipient2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "type": "object" +}
- Changed
create_reloadable_card2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "card": { + "properties": { + "balance": { + "description": "Card balance in US dollars.", + "type": [ + "number", + "null" + ] + }, + "card_id": { + "type": [ + "string", + "null" + ] + }, + "card_type": { + "type": [ + "string", + "null" + ] + }, + "expiry": { + "type": [ + "string", + "null" + ] + }, + "last4": { + "type": [ + "string", + "null" + ] + }, + "reusable": { + "type": [ + "boolean", + "null" + ] + }, + "spend_limit": { + "type": [ + "number", + "null" + ] + }, + "status": { + "type": [ + "string", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + } + }, + "type": "object" +}
- Changed
delete_address_book_entry2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "address": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" +}
- Changed
delete_banking_recipient2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "type": "object" +}
- Changed
delete_payment_recipient2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "deleted": { + "type": [ + "boolean", + "null" + ] + }, + "recipient_id": { + "type": [ + "string", + "null" + ] + }, + "user_id": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" +}
- Changed
delete_webhook2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "deleted": { + "description": "False when there was no registration to delete.", + "type": [ + "boolean", + "null" + ] + } + }, + "type": "object" +}
- Changed
exchange_api_key1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "type": "object" +}
- Changed
fund_card_balance2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "asset": { + "type": [ + "string", + "null" + ] + }, + "deposit_address": { + "description": "The account holder's own deposit address at the card issuer, on Base.", + "type": [ + "string", + "null" + ] + }, + "funded_usd": { + "description": "USD loaded onto the card balance.", + "type": [ + "number", + "null" + ] + }, + "network": { + "type": [ + "string", + "null" + ] + }, + "note": { + "type": [ + "string", + "null" + ] + }, + "payment_network": { + "description": "The chain the payment settled on: `solana` (bridged to Base over CCTP) or `base` (forwarded directly).", + "type": [ + "string", + "null" + ] + }, + "status": { + "description": "Always `paid` here: the payment settled and delivery to the card balance has started. Follow the later states in `GET /list-card-transactions`.", + "type": [ + "string", + "null" + ] + }, + "top_up_id": { + "description": "Identifies this top-up under `top_ups` in `GET /list-card-transactions`.", + "type": [ + "string", + "null" + ] + } + }, + "type": "object" +}
- Changed
get_account_balance2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "Account balance information.", + "properties": { + "balance": { + "description": "Current available balance in USD", + "type": [ + "number", + "null" + ] + }, + "created_timestamp": { + "type": [ + "number", + "null" + ] + }, + "created_timestamp_readable": { + "type": [ + "string", + "null" + ] + }, + "total_deposits": { + "description": "Total lifetime deposits in USD", + "type": [ + "number", + "null" + ] + }, + "user_id": { + "description": "The user's ID (lowercase wallet address)", + "type": [ + "string", + "null" + ] + } + }, + "type": "object" +}
- Changed
get_agent_spend_limit2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "default": { + "description": "The limit that applies when the owner has never set one.", + "type": [ + "number", + "null" + ] + }, + "max": { + "description": "The highest value the owner can set.", + "type": [ + "number", + "null" + ] + }, + "maxPerPaymentUsdc": { + "description": "The most a single payment may total, fees included.", + "type": [ + "number", + "null" + ] + }, + "min": { + "description": "The lowest value the owner can set.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" +}
- Changed
get_agent_wallet2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "type": "object" +}
- Changed
get_auth_link2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "auth_url": { + "description": "URL to open in a browser to log in to the Laso Finance dashboard. Carries a short single-use login code.", + "type": [ + "string", + "null" + ] + }, + "expires_in": { + "description": "Seconds until the login code expires", + "type": [ + "number", + "null" + ] + }, + "user_id": { + "description": "The authenticated user's ID (wallet address)", + "type": [ + "string", + "null" + ] + } + }, + "type": "object" +}
- Changed
get_banking_application2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "type": "object" +}
- Changed
get_banking_profile_status2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "type": "object" +}
- Changed
get_banking_transaction2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "type": "object" +}
- Removed
get_card - Changed
get_card_data2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "anyOf": [ + { + "description": "Response from `/get-card-data`. Three card types share this shape and each populates a different subset.\n\n**Non-reloadable (U.S. and International):** when `status` is `ready`, `card_details` carries the number, CVV, and expiry. International cards add `label`, `charged_usd_amount`, `fees_paid`, `state`, `balance_update_requested_timestamp`, and `queued_order_card_id`.\n\n**Reloadable:** returns `last4`, `expiry`, `balance`, `spend_limit`, `reusable`, `issuer_status`, `created_at`, and `expires_at` instead of the `usd_amount`/`timestamp` fields above. Reading its number and CVV is gated by the card issuer, so exactly one of `card_details`, `details_approval`, or `details_error` is present on a single-card lookup.", + "properties": { + "balance": { + "description": "Reloadable cards only. Spendable balance in dollars.", + "type": [ + "number", + "null" + ] + }, + "balance_update_requested_timestamp": { + "description": "International cards only. Unix timestamp (ms) of an outstanding admin balance update request, or null if none is pending.", + "type": [ + "number", + "null" + ] + }, + "card_details": { + "description": "Only present when status is `ready` (U.S.) or `complete` (international).", + "properties": { + "available_balance": { + "type": [ + "number", + "null" + ] + }, + "billing_address": { + "description": "The card billing address to enter when a merchant asks for one at checkout. The billing name is always `Laso Finance`. For USA non-reloadable cards `required` is `false` (any valid U.S. billing address works; this is a known-good default). For international non-reloadable cards `required` is `true` and the merchant AVS check is validated against exactly this address. On reloadable cards this is always null: the card issuer holds no billing address for a card, and they are AVS-checked against the address the account holder gave at their own identity verification. Ask the holder for it; do not substitute Laso's address.", + "properties": { + "city": { + "type": [ + "string", + "null" + ] + }, + "country": { + "type": [ + "string", + "null" + ] + }, + "line_1": { + "type": [ + "string", + "null" + ] + }, + "line_2": { + "type": [ + "string", + "null" + ] + }, + "name": { + "description": "Always `Laso Finance`.", + "type": [ + "string", + "null" + ] + }, + "note": { + "type": [ + "string", + "null" + ] + }, + "required": { + "description": "`true` if the card enforces AVS against this exact address (international cards); `false` if any valid U.S. address works (USA cards).", + "type": [ + "boolean", + "null" + ] + }, + "state": { + "type": [ + "string", + "null" + ] + }, + "zip": { + "type": [ + "string", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + "card_number": { + "type": [ + "string", + "null" + ] + }, + "cvv": { + "type": [ + "string", + "null" + ] + }, + "exp_month": { + "type": [ + "string", + "null" + ] + }, + "exp_year": { + "type": [ + "string", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + "card_id": { + "type": [ + "string", + "null" + ] + }, + "card_type": { + "description": "One of: Non-Reloadable U.S., Non-Reloadable International, Reloadable.", + "type": [ + "string", + "null" + ] + }, + "charged_usd_amount": { + "description": "International cards only. Amount the user was charged including fees.", + "type": [ + "number", + "null" + ] + }, + "country": { + "description": "U.S. cards only.", + "type": [ + "string", + "null" + ] + }, + "created_at": { + "description": "Reloadable cards only. Epoch milliseconds.", + "type": [ + "number", + "null" + ] + }, + "details_approval": { + "description": "Reloadable cards only, and only for a card the holder created in ANOTHER app. The issuer has emailed them an approve/deny link; retry with `approval_id` once they approve. Cards created through `/create-reloadable-card` are Laso-issued and never take this path.", + "properties": { + "approval_id": { + "type": [ + "string", + "null" + ] + }, + "note": { + "type": [ + "string", + "null" + ] + }, + "status": { + "description": "One of: pending.", + "type": [ + "string", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + "details_error": { + "description": "Reloadable cards only. Present when the issuer could not return the number, so a card with no `card_details` is never silently indistinguishable from one whose details are pending.", + "type": [ + "string", + "null" + ] + }, + "expires_at": { + "description": "Reloadable cards only. Epoch milliseconds, or null when the card does not expire.", + "type": [ + "number", + "null" + ] + }, + "expiry": { + "description": "Reloadable cards only. MM/YY.", + "type": [ + "string", + "null" + ] + }, + "fees_paid": { + "description": "International cards only. Fees paid for this card.", + "type": [ + "number", + "null" + ] + }, + "issuer_status": { + "description": "Reloadable cards only. The issuer's own status string, kept verbatim.", + "type": [ + "string", + "null" + ] + }, + "label": { + "description": "International cards only. User-supplied label, may be empty.", + "type": [ + "string", + "null" + ] + }, + "last4": { + "description": "Reloadable cards only. Last four digits.", + "type": [ + "string", + "null" + ] + }, + "last_updated_timestamp": { + "description": "U.S. cards only. Unix timestamp (ms) of the last time card data was refreshed.", + "type": [ + "number", + "null" + ] + }, + "queued_order_card_id": { + "description": "International cards only. The original `card_id` returned by `/order-intl-card`. After admin fulfillment the card is reissued with a new `card_id` (the issuer's transaction id); querying `/get-card-data?card_id=<original>` continues to resolve to the fulfilled card via this field.", + "type": [ + "string", + "null" + ] + }, + "reusable": { + "description": "Reloadable cards only. True for a multi-use card.", + "type": [ + "boolean", + "null" + ] + }, + "spend_limit": { + "description": "Reloadable cards only. Spend cap in dollars.", + "type": [ + "number", + "null" + ] + }, + "state": { + "description": "International cards only. Raw card state. One of: queued, redeemable, complete, refund-requested, refund-requested-approved-for-queue, archived, refunded.", + "type": [ + "string", + "null" + ] + }, + "status": { + "description": "One of: pending, ready, queued, complete, refund-requested, refunded, archived.", + "type": [ + "string", + "null" + ] + }, + "timestamp": { + "type": [ + "number", + "null" + ] + }, + "timestamp_readable": { + "type": [ + "string", + "null" + ] + }, + "transactions": { + "description": "Card transaction history. U.S. and international cards use slightly different shapes — see `CardTransaction` and `IntlCardTransaction`.", + "items": { + "anyOf": [ + { + "description": "U.S. prepaid card transaction.", + "properties": { + "amount": { + "type": [ + "number", + "null" + ] + }, + "date": { + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "is_credit": { + "type": [ + "boolean", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + { + "description": "International prepaid card transaction.", + "properties": { + "amount": { + "description": "Transaction amount in USD.", + "type": [ + "number", + "null" + ] + }, + "date": { + "description": "Unix timestamp (ms) of the transaction.", + "type": [ + "number", + "null" + ] + }, + "merchant": { + "type": [ + "string", + "null" + ] + }, + "status": { + "description": "Optional status, e.g. `pending`.", + "type": [ + "string", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + } + ] + }, + "type": [ + "array", + "null" + ] + }, + "usd_amount": { + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + { + "properties": { + "cards": { + "items": { + "description": "Response from `/get-card-data`. Three card types share this shape and each populates a different subset.\n\n**Non-reloadable (U.S. and International):** when `status` is `ready`, `card_details` carries the number, CVV, and expiry. International cards add `label`, `charged_usd_amount`, `fees_paid`, `state`, `balance_update_requested_timestamp`, and `queued_order_card_id`.\n\n**Reloadable:** returns `last4`, `expiry`, `balance`, `spend_limit`, `reusable`, `issuer_status`, `created_at`, and `expires_at` instead of the `usd_amount`/`timestamp` fields above. Reading its number and CVV is gated by the card issuer, so exactly one of `card_details`, `details_approval`, or `details_error` is present on a single-card lookup.", + "properties": { + "balance": { + "description": "Reloadable cards only. Spendable balance in dollars.", + "type": [ + "number", + "null" + ] + }, + "balance_update_requested_timestamp": { + "description": "International cards only. Unix timestamp (ms) of an outstanding admin balance update request, or null if none is pending.", + "type": [ + "number", + "null" + ] + }, + "card_details": { + "description": "Only present when status is `ready` (U.S.) or `complete` (international).", + "properties": { + "available_balance": { + "type": [ + "number", + "null" + ] + }, + "billing_address": { + "description": "The card billing address to enter when a merchant asks for one at checkout. The billing name is always `Laso Finance`. For USA non-reloadable cards `required` is `false` (any valid U.S. billing address works; this is a known-good default). For international non-reloadable cards `required` is `true` and the merchant AVS check is validated against exactly this address. On reloadable cards this is always null: the card issuer holds no billing address for a card, and they are AVS-checked against the address the account holder gave at their own identity verification. Ask the holder for it; do not substitute Laso's address.", + "properties": { + "city": { + "type": [ + "string", + "null" + ] + }, + "country": { + "type": [ + "string", + "null" + ] + }, + "line_1": { + "type": [ + "string", + "null" + ] + }, + "line_2": { + "type": [ + "string", + "null" + ] + }, + "name": { + "description": "Always `Laso Finance`.", + "type": [ + "string", + "null" + ] + }, + "note": { + "type": [ + "string", + "null" + ] + }, + "required": { + "description": "`true` if the card enforces AVS against this exact address (international cards); `false` if any valid U.S. address works (USA cards).", + "type": [ + "boolean", + "null" + ] + }, + "state": { + "type": [ + "string", + "null" + ] + }, + "zip": { + "type": [ + "string", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + "card_number": { + "type": [ + "string", + "null" + ] + }, + "cvv": { + "type": [ + "string", + "null" + ] + }, + "exp_month": { + "type": [ + "string", + "null" + ] + }, + "exp_year": { + "type": [ + "string", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + "card_id": { + "type": [ + "string", + "null" + ] + }, + "card_type": { + "description": "One of: Non-Reloadable U.S., Non-Reloadable International, Reloadable.", + "type": [ + "string", + "null" + ] + }, + "charged_usd_amount": { + "description": "International cards only. Amount the user was charged including fees.", + "type": [ + "number", + "null" + ] + }, + "country": { + "description": "U.S. cards only.", + "type": [ + "string", + "null" + ] + }, + "created_at": { + "description": "Reloadable cards only. Epoch milliseconds.", + "type": [ + "number", + "null" + ] + }, + "details_approval": { + "description": "Reloadable cards only, and only for a card the holder created in ANOTHER app. The issuer has emailed them an approve/deny link; retry with `approval_id` once they approve. Cards created through `/create-reloadable-card` are Laso-issued and never take this path.", + "properties": { + "approval_id": { + "type": [ + "string", + "null" + ] + }, + "note": { + "type": [ + "string", + "null" + ] + }, + "status": { + "description": "One of: pending.", + "type": [ + "string", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + "details_error": { + "description": "Reloadable cards only. Present when the issuer could not return the number, so a card with no `card_details` is never silently indistinguishable from one whose details are pending.", + "type": [ + "string", + "null" + ] + }, + "expires_at": { + "description": "Reloadable cards only. Epoch milliseconds, or null when the card does not expire.", + "type": [ + "number", + "null" + ] + }, + "expiry": { + "description": "Reloadable cards only. MM/YY.", + "type": [ + "string", + "null" + ] + }, + "fees_paid": { + "description": "International cards only. Fees paid for this card.", + "type": [ + "number", + "null" + ] + }, + "issuer_status": { + "description": "Reloadable cards only. The issuer's own status string, kept verbatim.", + "type": [ + "string", + "null" + ] + }, + "label": { + "description": "International cards only. User-supplied label, may be empty.", + "type": [ + "string", + "null" + ] + }, + "last4": { + "description": "Reloadable cards only. Last four digits.", + "type": [ + "string", + "null" + ] + }, + "last_updated_timestamp": { + "description": "U.S. cards only. Unix timestamp (ms) of the last time card data was refreshed.", + "type": [ + "number", + "null" + ] + }, + "queued_order_card_id": { + "description": "International cards only. The original `card_id` returned by `/order-intl-card`. After admin fulfillment the card is reissued with a new `card_id` (the issuer's transaction id); querying `/get-card-data?card_id=<original>` continues to resolve to the fulfilled card via this field.", + "type": [ + "string", + "null" + ] + }, + "reusable": { + "description": "Reloadable cards only. True for a multi-use card.", + "type": [ + "boolean", + "null" + ] + }, + "spend_limit": { + "description": "Reloadable cards only. Spend cap in dollars.", + "type": [ + "number", + "null" + ] + }, + "state": { + "description": "International cards only. Raw card state. One of: queued, redeemable, complete, refund-requested, refund-requested-approved-for-queue, archived, refunded.", + "type": [ + "string", + "null" + ] + }, + "status": { + "description": "One of: pending, ready, queued, complete, refund-requested, refunded, archived.", + "type": [ + "string", + "null" + ] + }, + "timestamp": { + "type": [ + "number", + "null" + ] + }, + "timestamp_readable": { + "type": [ + "string", + "null" + ] + }, + "transactions": { + "description": "Card transaction history. U.S. and international cards use slightly different shapes — see `CardTransaction` and `IntlCardTransaction`.", + "items": { + "anyOf": [ + { + "description": "U.S. prepaid card transaction.", + "properties": { + "amount": { + "type": [ + "number", + "null" + ] + }, + "date": { + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "is_credit": { + "type": [ + "boolean", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + { + "description": "International prepaid card transaction.", + "properties": { + "amount": { + "description": "Transaction amount in USD.", + "type": [ + "number", + "null" + ] + }, + "date": { + "description": "Unix timestamp (ms) of the transaction.", + "type": [ + "number", + "null" + ] + }, + "merchant": { + "type": [ + "string", + "null" + ] + }, + "status": { + "description": "Optional status, e.g. `pending`.", + "type": [ + "string", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + } + ] + }, + "type": [ + "array", + "null" + ] + }, + "usd_amount": { + "type": [ + "number", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + "type": [ + "array", + "null" + ] + } + }, + "type": "object" + } + ], + "type": "object" +}
- Changed
get_card_deposit_address2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "address": { + "description": "The holder's own USDC receiving address at the card issuer.", + "type": [ + "string", + "null" + ] + }, + "asset": { + "description": "The asset the address accepts. Always `USDC`.", + "type": [ + "string", + "null" + ] + }, + "balance": { + "description": "Dollars currently on the card balance, or `null` when the issuer cannot read it (which is not the same as zero).", + "type": [ + "number", + "null" + ] + }, + "network": { + "description": "The chain the address accepts. Always `base`.", + "type": [ + "string", + "null" + ] + }, + "note": { + "description": "Chain warning and the next step.", + "type": [ + "string", + "null" + ] + } + }, + "type": "object" +}
- Changed
get_kyc_link2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "kyc_url": { + "description": "One-time URL to open to complete identity verification.", + "type": [ + "string", + "null" + ] + }, + "user_id": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" +}
- Changed
get_kyc_status2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "kyc_last_reviewed_at": { + "description": "Epoch milliseconds of the last review, or null if never reviewed.", + "type": [ + "number", + "null" + ] + }, + "kyc_review_answer": { + "description": "Latest review answer (e.g. GREEN for approved, RED for rejected), or null if never reviewed.", + "type": [ + "string", + "null" + ] + }, + "kyc_review_status": { + "description": "Latest review status from the verification provider, or null if never reviewed.", + "type": [ + "string", + "null" + ] + }, + "kyc_verified": { + "description": "Whether the wallet has completed identity verification. When true, /send-payment dispatches the payout. When false, /send-payment does not send: it returns kyc_required and the USDC paid lands in account balance (recoverable via POST /withdraw). Verify before calling /send-payment.", + "type": [ + "boolean", + "null" + ] + }, + "user_id": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" +}
- Changed
get_payment_status2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "anyOf": [ + { + "properties": { + "payment": { + "description": "One Venmo or PayPal payout sent from this account.", + "properties": { + "amount_pre_fees": { + "description": "Dollars the recipient receives.", + "type": [ + "number", + "null" + ] + }, + "amount_with_fees": { + "description": "Dollars debited from the account balance, fee included.", + "type": [ + "number", + "null" + ] + }, + "fees_paid": { + "type": [ + "number", + "null" + ] + }, + "id": { + "description": "Pass as `payment_id` to fetch this payout on its own.", + "type": [ + "string", + "null" + ] + }, + "platform": { + "description": "One of: venmo, paypal.", + "type": [ + "string", + "null" + ] + }, + "recipient_first_name": { + "type": [ + "string", + "null" + ] + }, + "recipient_id": { + "description": "The saved recipient this went to, as returned by `GET /payment-recipients`.", + "type": [ + "string", + "null" + ] + }, + "recipient_last_name": { + "type": [ + "string", + "null" + ] + }, + "state": { + "description": "`queued` and `in-process` are still in flight. Absent on payouts sent before state tracking existed. One of: queued, in-process, complete, failed, cancelled.", + "type": [ + "string", + "null" + ] + }, + "state_updated_at": { + "description": "Milliseconds since the epoch when `state` last changed.", + "type": [ + "number", + "null" + ] + }, + "timestamp": { + "description": "Milliseconds since the epoch when the payout was sent.", + "type": [ + "number", + "null" + ] + }, + "timestamp_readable": { + "type": [ + "string", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + } + }, + "type": "object" + }, + { + "properties": { + "payments": { + "items": { + "description": "One Venmo or PayPal payout sent from this account.", + "properties": { + "amount_pre_fees": { + "description": "Dollars the recipient receives.", + "type": [ + "number", + "null" + ] + }, + "amount_with_fees": { + "description": "Dollars debited from the account balance, fee included.", + "type": [ + "number", + "null" + ] + }, + "fees_paid": { + "type": [ + "number", + "null" + ] + }, + "id": { + "description": "Pass as `payment_id` to fetch this payout on its own.", + "type": [ + "string", + "null" + ] + }, + "platform": { + "description": "One of: venmo, paypal.", + "type": [ + "string", + "null" + ] + }, + "recipient_first_name": { + "type": [ + "string", + "null" + ] + }, + "recipient_id": { + "description": "The saved recipient this went to, as returned by `GET /payment-recipients`.", + "type": [ + "string", + "null" + ] + }, + "recipient_last_name": { + "type": [ + "string", + "null" + ] + }, + "state": { + "description": "`queued` and `in-process` are still in flight. Absent on payouts sent before state tracking existed. One of: queued, in-process, complete, failed, cancelled.", + "type": [ + "string", + "null" + ] + }, + "state_updated_at": { + "description": "Milliseconds since the epoch when `state` last changed.", + "type": [ + "number", + "null" + ] + }, + "timestamp": { + "description": "Milliseconds since the epoch when the payout was sent.", + "type": [ + "number", + "null" + ] + }, + "timestamp_readable": { + "type": [ + "string", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + "type": [ + "array", + "null" + ] + } + }, + "type": "object" + } + ], + "type": "object" +}
- Changed
get_signup_status1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "api_key": { + "description": "Your lasoak_ key. Delivered EXACTLY ONCE — null on any later poll.", + "type": [ + "string", + "null" + ] + }, + "api_key_note": { + "description": "Present only when api_key is null, explaining that it was already delivered.", + "type": [ + "string", + "null" + ] + }, + "auth": { + "description": "An id_token / refresh_token bundle you can use immediately.", + "type": [ + "object", + "null" + ] + }, + "callable_base_url": { + "type": [ + "string", + "null" + ] + }, + "next_steps": { + "items": { + "type": [ + "string", + "null" + ] + }, + "type": [ + "array", + "null" + ] + }, + "status": { + "type": [ + "string", + "null" + ] + }, + "user_id": { + "description": "The Laso user id of the new account.", + "type": [ + "string", + "null" + ] + } + }, + "type": "object" +}
- Changed
get_version1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "api_catalog_url": { + "description": "URL of the RFC 9727 API catalog (`application/linkset+json`) indexing the OpenAPI description, the agent docs, and this status route.", + "type": [ + "string", + "null" + ] + }, + "docs": { + "description": "Per-file entries, each with a `url` and a stable `sha256` content identifier. Compare against the values you last saw to tell which file changed.", + "type": [ + "object", + "null" + ] + }, + "docs_manifest_url": { + "description": "URL of the authoritative freshness beacon, served with no-cache.", + "type": [ + "string", + "null" + ] + }, + "docs_version": { + "description": "12-character content hash of the agent docs. Changes only when the docs change.", + "type": [ + "string", + "null" + ] + }, + "note": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" +}
- Changed
get_webhook2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "consecutive_failures": { + "type": [ + "number", + "null" + ] + }, + "disabled": { + "description": "True when auto-disabled after repeated delivery failures. Re-register to re-enable.", + "type": [ + "boolean", + "null" + ] + }, + "disabled_reason": { + "type": [ + "string", + "null" + ] + }, + "last_delivery_detail": { + "description": "`HTTP <status>` of the last attempt, or the error message.", + "type": [ + "string", + "null" + ] + }, + "last_delivery_message_id": { + "description": "The `webhook-id` header of the last delivery.", + "type": [ + "string", + "null" + ] + }, + "last_delivery_status": { + "description": "`delivered` or `failed`, or null before the first delivery.", + "type": [ + "string", + "null" + ] + }, + "last_delivery_timestamp": { + "description": "Epoch milliseconds of the last delivery attempt.", + "type": [ + "number", + "null" + ] + }, + "registered": { + "type": [ + "boolean", + "null" + ] + }, + "url": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" +}
- Changed
get_withdrawal_status2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "anyOf": [ + { + "properties": { + "withdrawal": { + "description": "A withdrawal status record.", + "properties": { + "address": { + "description": "The wallet address the withdrawal is sent to", + "type": [ + "string", + "null" + ] + }, + "amount": { + "type": [ + "number", + "null" + ] + }, + "asset": { + "type": [ + "string", + "null" + ] + }, + "id": { + "type": [ + "string", + "null" + ] + }, + "network": { + "type": [ + "string", + "null" + ] + }, + "state": { + "type": [ + "string", + "null" + ] + }, + "timestamp": { + "type": [ + "number", + "null" + ] + }, + "timestamp_readable": { + "type": [ + "string", + "null" + ] + }, + "tx_hash": { + "description": "On-chain transaction hash, present once the withdrawal is processed", + "type": [ + "string", + "null" + ] + }, + "tx_url": { + "description": "Block explorer URL for the transaction, present when tx_hash exists", + "type": [ + "string", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + } + }, + "type": "object" + }, + { + "properties": { + "withdrawals": { + "items": { + "description": "A withdrawal status record.", + "properties": { + "address": { + "description": "The wallet address the withdrawal is sent to", + "type": [ + "string", + "null" + ] + }, + "amount": { + "type": [ + "number", + "null" + ] + }, + "asset": { + "type": [ + "string", + "null" + ] + }, + "id": { + "type": [ + "string", + "null" + ] + }, + "network": { + "type": [ + "string", + "null" + ] + }, + "state": { + "type": [ + "string", + "null" + ] + }, + "timestamp": { + "type": [ + "number", + "null" + ] + }, + "timestamp_readable": { + "type": [ + "string", + "null" + ] + }, + "tx_hash": { + "description": "On-chain transaction hash, present once the withdrawal is processed", + "type": [ + "string", + "null" + ] + }, + "tx_url": { + "description": "Block explorer URL for the transaction, present when tx_hash exists", + "type": [ + "string", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + "type": [ + "array", + "null" + ] + } + }, + "type": "object" + } + ], + "type": "object" +}
- Changed
list_address_book2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "entries": { + "items": { + "properties": { + "address": { + "description": "The recipient's Solana address. This is the entry's key.", + "type": [ + "string", + "null" + ] + }, + "last_used_at": { + "description": "When a transfer last went to this address, in milliseconds since epoch. Absent if never sent to.", + "type": [ + "number", + "null" + ] + }, + "name": { + "description": "The name your human gave this recipient.", + "type": [ + "string", + "null" + ] + }, + "saved_at": { + "description": "When the entry was last saved or renamed, in milliseconds since epoch.", + "type": [ + "number", + "null" + ] + }, + "send_count": { + "description": "How many transfers have gone to this address.", + "type": [ + "number", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + "type": [ + "array", + "null" + ] + } + }, + "type": "object" +}
- Removed
list_bank_recipients - Changed
list_banking_accounts2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "type": "object" +}
- Changed
list_banking_recipients2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "type": "object" +}
- Changed
list_banking_transactions2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "type": "object" +}
- Changed
list_card_transactions2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "note": { + "description": "Present only when no card issuer account is linked.", + "type": [ + "string", + "null" + ] + }, + "transactions": { + "items": { + "properties": { + "amount": { + "description": "Transaction amount in US dollars.", + "type": [ + "number", + "null" + ] + }, + "card_id": { + "type": [ + "string", + "null" + ] + }, + "created_at": { + "description": "Milliseconds since the epoch.", + "type": [ + "number", + "null" + ] + }, + "issuer_status": { + "description": "The issuer's own status string, kept verbatim for support.", + "type": [ + "string", + "null" + ] + }, + "merchant": { + "description": "Merchant name, when the issuer reports one.", + "type": [ + "string", + "null" + ] + }, + "status": { + "description": "Lowercased status, e.g. `settled`.", + "type": [ + "string", + "null" + ] + }, + "transaction_id": { + "type": [ + "string", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + "type": [ + "array", + "null" + ] + } + }, + "type": "object" +}
- Changed
list_payment_recipients2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "platform": { + "description": "One of: venmo, paypal.", + "type": [ + "string", + "null" + ] + }, + "recipients": { + "items": { + "properties": { + "display_name": { + "description": "The label the account owner chose. Prefer it when confirming a payment back to a human.", + "type": [ + "string", + "null" + ] + }, + "handle": { + "description": "What to pay them at: a 10-digit phone number for Venmo, an email address for PayPal. Pass this as `recipient_id` to `GET /send-payment`.", + "type": [ + "string", + "null" + ] + }, + "last_sent_timestamp": { + "description": "Milliseconds since the epoch.", + "type": [ + "number", + "null" + ] + }, + "name": { + "description": "The recipient's own name on the platform.", + "type": [ + "string", + "null" + ] + }, + "recipient_id": { + "description": "Opaque id of this saved entry (for example `aQ3xK9mZpL2vB7nR4tYw`). Pass it as `recipient_id` to `POST` and `DELETE /payment-recipients`. It is not what `GET /send-payment` takes; use `handle` there.", + "type": [ + "string", + "null" + ] + }, + "send_count": { + "type": [ + "number", + "null" + ] + }, + "status": { + "type": [ + "string", + "null" + ] + }, + "total_sent": { + "description": "Total dollars sent to this recipient from this account.", + "type": [ + "number", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + "type": [ + "array", + "null" + ] + }, + "user_id": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" +}
- Added
order_card - Changed
order_gift_card2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "auth": { + "properties": { + "expires_in": { + "description": "Token lifetime in seconds", + "type": [ + "string", + "null" + ] + }, + "id_token": { + "description": "ID token — use as Bearer token for Laso Finance APIs", + "type": [ + "string", + "null" + ] + }, + "refresh_token": { + "description": "Use with POST /auth (grant_type=refresh_token) to get a new id_token when it expires", + "type": [ + "string", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + "callable_base_url": { + "type": [ + "string", + "null" + ] + }, + "gift_card": { + "description": "Gift card order result with redemption details.", + "properties": { + "amount": { + "description": "Gift card face value, denominated in the product's own `currency` (not USD)", + "type": [ + "number", + "null" + ] + }, + "card_id": { + "type": [ + "string", + "null" + ] + }, + "country": { + "type": [ + "string", + "null" + ] + }, + "currency": { + "description": "ISO 4217 code the `amount` is denominated in, e.g. `USD`, `SAR`, `EUR`", + "type": [ + "string", + "null" + ] + }, + "laso_server_id": { + "type": [ + "string", + "null" + ] + }, + "pin_code": { + "description": "PIN code for the gift card (if applicable)", + "type": [ + "string", + "null" + ] + }, + "redemption_code": { + "description": "Code to redeem the gift card (if applicable)", + "type": [ + "string", + "null" + ] + }, + "redemption_url": { + "description": "URL to redeem the gift card (if applicable)", + "type": [ + "string", + "null" + ] + }, + "status": { + "description": "One of: completed.", + "type": [ + "string", + "null" + ] + }, + "timestamp": { + "type": [ + "number", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + "user_id": { + "description": "The user's ID (lowercase wallet address)", + "type": [ + "string", + "null" + ] + } + }, + "type": "object" +}
- Changed
order_intl_card2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "auth": { + "properties": { + "expires_in": { + "description": "Token lifetime in seconds", + "type": [ + "string", + "null" + ] + }, + "id_token": { + "description": "ID token — use as Bearer token for Laso Finance APIs", + "type": [ + "string", + "null" + ] + }, + "refresh_token": { + "description": "Use with POST /auth (grant_type=refresh_token) to get a new id_token when it expires", + "type": [ + "string", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + "callable_base_url": { + "type": [ + "string", + "null" + ] + }, + "intl_card_order": { + "properties": { + "charged_usd_amount": { + "type": [ + "number", + "null" + ] + }, + "on_card_usd_amount": { + "type": [ + "number", + "null" + ] + }, + "status": { + "type": [ + "string", + "null" + ] + }, + "timestamp": { + "type": [ + "number", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + "message": { + "type": [ + "string", + "null" + ] + }, + "user_id": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" +}
- Changed
pay_x402_endpoint2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "type": "object" +}
- Changed
push_to_card2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "amount": { + "description": "The face value sent to the debit card, in the requested `currency`", + "type": [ + "number", + "null" + ] + }, + "auth": { + "properties": { + "expires_in": { + "description": "Token lifetime in seconds", + "type": [ + "string", + "null" + ] + }, + "id_token": { + "description": "ID token — use as Bearer token for Laso Finance APIs", + "type": [ + "string", + "null" + ] + }, + "refresh_token": { + "description": "Use with POST /auth (grant_type=refresh_token) to get a new id_token when it expires", + "type": [ + "string", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + "callable_base_url": { + "type": [ + "string", + "null" + ] + }, + "currency": { + "description": "The target currency of the debit card transfer One of: USD, EUR, GBP.", + "type": [ + "string", + "null" + ] + }, + "message": { + "type": [ + "string", + "null" + ] + }, + "note": { + "description": "Important information about the currency's regional restriction and required form fields", + "type": [ + "string", + "null" + ] + }, + "redemption_url": { + "description": "URL to open and complete the push-to-card transfer. The form requires: sender name, debit card number, and cardholder name.", + "type": [ + "string", + "null" + ] + }, + "success": { + "type": [ + "boolean", + "null" + ] + }, + "user_id": { + "description": "The user's ID (lowercase wallet address)", + "type": [ + "string", + "null" + ] + } + }, + "type": "object" +}
- Changed
refresh_card_data2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "message": { + "type": [ + "string", + "null" + ] + }, + "success": { + "type": [ + "boolean", + "null" + ] + } + }, + "type": "object" +}
- Changed
refresh_token1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "expires_in": { + "description": "Token lifetime in seconds", + "type": [ + "string", + "null" + ] + }, + "id_token": { + "description": "New ID token — use as Bearer token for Laso Finance APIs", + "type": [ + "string", + "null" + ] + }, + "refresh_token": { + "description": "New refresh token — use for the next refresh", + "type": [ + "string", + "null" + ] + }, + "user_id": { + "description": "The user's ID (lowercase wallet address)", + "type": [ + "string", + "null" + ] + } + }, + "type": "object" +}
- Changed
register_webhook2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "registered": { + "type": [ + "boolean", + "null" + ] + }, + "secret": { + "description": "Standard Webhooks signing secret (`whsec_...`). Shown only in this response — store it now. Rotate by re-registering.", + "type": [ + "string", + "null" + ] + }, + "signing": { + "description": "Always `standard-webhooks`.", + "type": [ + "string", + "null" + ] + }, + "url": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" +}
- Changed
save_address_book_entry2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "address": { + "type": [ + "string", + "null" + ] + }, + "name": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" +}
- Changed
search_docs1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "note": { + "description": "Where to read the full docs when nothing matched.", + "type": "string" + }, + "results": { + "description": "Best-matching doc sections, most relevant first.", + "items": { + "properties": { + "content": { + "description": "Section text, truncated to 2500 characters.", + "type": "string" + }, + "heading": { + "description": "Section heading.", + "type": "string" + }, + "source": { + "description": "Document the section came from.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + } + }, + "type": "object" +}
- Changed
search_gift_cards2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "count": { + "description": "Number of results returned", + "type": [ + "number", + "null" + ] + }, + "facets": { + "description": "Valid filter values, computed from the full catalog. Use these to discover what you can pass to the `category`, `currency`, and `country` query parameters.", + "properties": { + "categories": { + "description": "All valid `category` filter values.", + "items": { + "type": [ + "string", + "null" + ] + }, + "type": [ + "array", + "null" + ] + }, + "countries": { + "description": "All valid `country` filter values (ISO 3166-1 alpha-2 codes).", + "items": { + "type": [ + "string", + "null" + ] + }, + "type": [ + "array", + "null" + ] + }, + "currencies": { + "description": "All valid `currency` filter values.", + "items": { + "type": [ + "string", + "null" + ] + }, + "type": [ + "array", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + "filters": { + "properties": { + "category": { + "type": [ + "string", + "null" + ] + }, + "country": { + "type": [ + "string", + "null" + ] + }, + "currency": { + "type": [ + "string", + "null" + ] + }, + "query": { + "type": [ + "string", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + "gift_cards": { + "items": { + "description": "A gift card product from the catalog.", + "properties": { + "catalog_info": { + "properties": { + "brand_description": { + "type": [ + "string", + "null" + ] + }, + "redemption_instructions": { + "type": [ + "string", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + "category": { + "description": "Catalog category for the gift card (e.g. \"ecommerce\", \"travel\").", + "type": [ + "string", + "null" + ] + }, + "country": { + "description": "ISO 3166-1 alpha-2 country the gift card belongs to. Null for borderless products available in more than one country.", + "type": [ + "string", + "null" + ] + }, + "currency": { + "description": "Currency code for the gift card", + "type": [ + "string", + "null" + ] + }, + "denominations": { + "description": "If set, only these exact amounts can be ordered. Null for range-based products.", + "items": { + "type": [ + "string", + "null" + ] + }, + "type": [ + "array", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "increment": { + "description": "Minimum order increment", + "type": [ + "string", + "null" + ] + }, + "laso_server_id": { + "description": "Product identifier to use when ordering via GET /order-gift-card", + "type": [ + "string", + "null" + ] + }, + "max": { + "description": "Maximum order amount", + "type": [ + "number", + "null" + ] + }, + "min": { + "description": "Minimum order amount", + "type": [ + "number", + "null" + ] + }, + "name": { + "description": "Gift card brand name", + "type": [ + "string", + "null" + ] + }, + "product_image_url": { + "description": "URL of the gift card image", + "type": [ + "string", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + "type": [ + "array", + "null" + ] + } + }, + "type": "object" +}
- Changed
search_merchants2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "card_type": { + "description": "The card type results are filtered for", + "type": [ + "string", + "null" + ] + }, + "count": { + "description": "Number of merchants returned", + "type": [ + "number", + "null" + ] + }, + "merchants": { + "items": { + "description": "A merchant from the spend data database with its acceptance status for the Non-Reloadable U.S. card.", + "properties": { + "description": { + "description": "Brief description of the merchant", + "type": [ + "string", + "null" + ] + }, + "name": { + "description": "Merchant name", + "type": [ + "string", + "null" + ] + }, + "notes": { + "description": "Additional notes about using the card at this merchant", + "type": [ + "string", + "null" + ] + }, + "restriction_note": { + "description": "Present when the merchant is restricted rather than merely untested. Banking and money-transfer merchants are always reported as `not_accepted`, because spending there counts as a transfer of value. Approvals do occur at these merchants, so acceptance cannot be read off the transaction history. `null` for every other merchant.", + "type": [ + "string", + "null" + ] + }, + "status": { + "description": "Whether the Non-Reloadable U.S. card is accepted at this merchant. `accepted` = confirmed working, `not_accepted` = confirmed failing or restricted, `unknown` = card type not yet tried at this merchant. One of: accepted, not_accepted, unknown.", + "type": [ + "string", + "null" + ] + }, + "url": { + "description": "Merchant website URL", + "type": [ + "string", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + "type": [ + "array", + "null" + ] + }, + "note": { + "description": "Important caveat about the data — this database only includes merchants where users have previously attempted transactions", + "type": [ + "string", + "null" + ] + }, + "query": { + "description": "The search query that was used", + "type": [ + "string", + "null" + ] + } + }, + "type": "object" +}
- Changed
send_bank_payment2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "auth": { + "properties": { + "expires_in": { + "description": "Token lifetime in seconds", + "type": [ + "string", + "null" + ] + }, + "id_token": { + "description": "ID token — use as Bearer token for Laso Finance APIs", + "type": [ + "string", + "null" + ] + }, + "refresh_token": { + "description": "Use with POST /auth (grant_type=refresh_token) to get a new id_token when it expires", + "type": [ + "string", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + "bank_payment": { + "properties": { + "amount": { + "description": "USD delivered to the bank account.", + "type": [ + "number", + "null" + ] + }, + "charged_amount": { + "description": "amount + fee_amount, the total debited.", + "type": [ + "number", + "null" + ] + }, + "destination": { + "description": "The bank account being paid, summarized. The account number is masked to its last four digits.", + "properties": { + "account_holder_name": { + "type": [ + "string", + "null" + ] + }, + "account_number_last4": { + "type": [ + "string", + "null" + ] + }, + "bank_name": { + "type": [ + "string", + "null" + ] + }, + "name": { + "type": [ + "string", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + "destination_id": { + "type": [ + "string", + "null" + ] + }, + "fee_amount": { + "description": "Transfer fee charged on top of the amount.", + "type": [ + "number", + "null" + ] + }, + "payout_id": { + "type": [ + "string", + "null" + ] + }, + "state": { + "type": [ + "string", + "null" + ] + }, + "timestamp": { + "type": [ + "number", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + "callable_base_url": { + "type": [ + "string", + "null" + ] + }, + "message": { + "type": [ + "string", + "null" + ] + }, + "success": { + "type": [ + "boolean", + "null" + ] + }, + "user_id": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" +}
- Changed
send_feedback2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "ok": { + "type": [ + "boolean", + "null" + ] + } + }, + "type": "object" +}
- Changed
send_payment2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "anyOf": [ + { + "properties": { + "amount": { + "type": [ + "number", + "null" + ] + }, + "auth": { + "properties": { + "expires_in": { + "description": "Token lifetime in seconds", + "type": [ + "string", + "null" + ] + }, + "id_token": { + "description": "ID token — use as Bearer token for Laso Finance APIs", + "type": [ + "string", + "null" + ] + }, + "refresh_token": { + "description": "Use with POST /auth (grant_type=refresh_token) to get a new id_token when it expires", + "type": [ + "string", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + "callable_base_url": { + "type": [ + "string", + "null" + ] + }, + "message": { + "type": [ + "string", + "null" + ] + }, + "platform": { + "description": "One of: venmo, paypal.", + "type": [ + "string", + "null" + ] + }, + "recipient_id": { + "type": [ + "string", + "null" + ] + }, + "state": { + "description": "Payment lifecycle state (e.g. `in-process`, `queued`).", + "type": [ + "string", + "null" + ] + }, + "success": { + "type": [ + "boolean", + "null" + ] + }, + "user_id": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "properties": { + "amount": { + "type": [ + "number", + "null" + ] + }, + "auth": { + "properties": { + "expires_in": { + "description": "Token lifetime in seconds", + "type": [ + "string", + "null" + ] + }, + "id_token": { + "description": "ID token — use as Bearer token for Laso Finance APIs", + "type": [ + "string", + "null" + ] + }, + "refresh_token": { + "description": "Use with POST /auth (grant_type=refresh_token) to get a new id_token when it expires", + "type": [ + "string", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + "callable_base_url": { + "type": [ + "string", + "null" + ] + }, + "kyc_required": { + "description": "One of: true.", + "type": [ + "boolean", + "null" + ] + }, + "kyc_url": { + "description": "URL the wallet owner must open to complete identity verification. No payout was sent, but the x402 payment you made was still credited to your Laso account balance. After verifying, retry /send-payment to dispatch the payout, or call POST /withdraw to pull the credited USDC back to your wallet.", + "type": [ + "string", + "null" + ] + }, + "message": { + "description": "Human-readable explanation of the KYC requirement and how to recover the credited funds via retry or POST /withdraw.", + "type": [ + "string", + "null" + ] + }, + "platform": { + "description": "One of: venmo, paypal.", + "type": [ + "string", + "null" + ] + }, + "recipient_id": { + "type": [ + "string", + "null" + ] + }, + "user_id": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + } + ], + "type": "object" +}
- Changed
start_signup1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "claim_code": { + "description": "The code inside claim_url. Pass it back to /signup-status alongside claim_token.", + "type": [ + "string", + "null" + ] + }, + "claim_token": { + "description": "Your receipt for this signup. Shown once; store it. Exchanged at /signup-status for your API key.", + "type": [ + "string", + "null" + ] + }, + "claim_url": { + "description": "Give this to your human verbatim. Never open it yourself.", + "type": [ + "string", + "null" + ] + }, + "expires_at": { + "description": "Epoch ms when the claim link expires.", + "type": [ + "number", + "null" + ] + }, + "expires_in": { + "description": "Seconds until the claim link expires (86400).", + "type": [ + "number", + "null" + ] + }, + "message_for_human": { + "description": "A ready-to-send reply containing the link. Send this as your next message.", + "type": [ + "string", + "null" + ] + }, + "next_steps": { + "items": { + "type": [ + "string", + "null" + ] + }, + "type": [ + "array", + "null" + ] + } + }, + "type": "object" +}
- Changed
submit_banking_application2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "type": "object" +}
- Changed
update_banking_application_details2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "type": "object" +}
- Changed
update_banking_destination2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "type": "object" +}
- Changed
update_payment_recipient2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "archived": { + "type": [ + "boolean", + "null" + ] + }, + "display_name": { + "type": [ + "string", + "null" + ] + }, + "platform": { + "type": [ + "string", + "null" + ] + }, + "recipient_id": { + "type": [ + "string", + "null" + ] + }, + "user_id": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" +}
- Changed
upload_banking_document2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "documentId": { + "type": [ + "string", + "null" + ] + }, + "status": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" +}
- Changed
withdraw2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "success": { + "type": [ + "boolean", + "null" + ] + }, + "withdrawal": { + "description": "A withdrawal record.", + "properties": { + "amount": { + "type": [ + "number", + "null" + ] + }, + "id": { + "type": [ + "string", + "null" + ] + }, + "solana_address": { + "description": "The Solana address the USDC will be sent to.", + "type": [ + "string", + "null" + ] + }, + "state": { + "description": "One of: pending.", + "type": [ + "string", + "null" + ] + }, + "timestamp": { + "type": [ + "number", + "null" + ] + }, + "timestamp_readable": { + "type": [ + "string", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + } + }, + "type": "object" +}
- Changed
withdraw_card_balance2 fields changed- removed
Input schema / properties / auth_tokenRemoved value: -{ - "description": "Laso credential. Only if the MCP connection has no Authorization header.", - "type": "string" -} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "amount": { + "description": "USD the issuer will pay out.", + "type": [ + "number", + "null" + ] + }, + "asset": { + "type": [ + "string", + "null" + ] + }, + "destination_address": { + "description": "The Base address the USDC goes to.", + "type": [ + "string", + "null" + ] + }, + "network": { + "type": [ + "string", + "null" + ] + }, + "note": { + "description": "Timing and where to see the request afterwards.", + "type": [ + "string", + "null" + ] + }, + "status": { + "description": "Always `requested`: the issuer has accepted the request and will pay it out manually.", + "type": [ + "string", + "null" + ] + }, + "withdrawal_id": { + "description": "The card issuer's reference for this payout request. Quote it to support; it also appears on the matching `withdrawal` card event.", + "type": [ + "string", + "null" + ] + } + }, + "type": "object" +}
6 tool updates
- Removed
agent_auth - Added
exchange_api_key - Removed
feedback - Changed
list_payment_recipients1 field changed- added
Input schema / properties / platform / descriptionAdded value: +"Payment platform whose saved recipients to list."
- Added
send_feedback - Changed
update_payment_recipient1 field changed- added
Input schema / properties / platform / descriptionAdded value: +"Payment platform the recipient is saved under."
64 tool updates
- Changed
add_banking_destination1 field changed- changed
Output schema / (root)Previous value: -{ - "type": "object" -}New value: +null
- Added
agent_auth - Changed
agent_wallet_transfer1 field changed- changed
Output schema / (root)Previous value: -{ - "type": "object" -}New value: +null
- Changed
announce_connection1 field changed- changed
Output schema / (root)Previous value: -{ - "type": "object" -}New value: +null
- Changed
cancel_intl_order1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "card_id": { - "type": [ - "string", - "null" - ] - }, - "message": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" -}New value: +null
- Changed
create_agent_api_key1 field changed- changed
Output schema / (root)Previous value: -{ - "type": "object" -}New value: +null
- Changed
create_agent_wallet1 field changed- changed
Output schema / (root)Previous value: -{ - "type": "object" -}New value: +null
- Changed
create_banking_account1 field changed- changed
Output schema / (root)Previous value: -{ - "type": "object" -}New value: +null
- Changed
create_banking_profile1 field changed- changed
Output schema / (root)Previous value: -{ - "type": "object" -}New value: +null
- Changed
create_banking_recipient1 field changed- changed
Output schema / (root)Previous value: -{ - "type": "object" -}New value: +null
- Changed
create_reloadable_card1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "card": { - "properties": { - "balance": { - "description": "Card balance in US dollars.", - "type": [ - "number", - "null" - ] - }, - "card_id": { - "type": [ - "string", - "null" - ] - }, - "card_type": { - "type": [ - "string", - "null" - ] - }, - "expiry": { - "type": [ - "string", - "null" - ] - }, - "last4": { - "type": [ - "string", - "null" - ] - }, - "reusable": { - "type": [ - "boolean", - "null" - ] - }, - "spend_limit": { - "type": [ - "number", - "null" - ] - }, - "status": { - "type": [ - "string", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - } - }, - "type": "object" -}New value: +null
- Changed
delete_address_book_entry1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "address": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" -}New value: +null
- Changed
delete_banking_recipient1 field changed- changed
Output schema / (root)Previous value: -{ - "type": "object" -}New value: +null
- Changed
delete_payment_recipient1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "deleted": { - "type": [ - "boolean", - "null" - ] - }, - "recipient_id": { - "type": [ - "string", - "null" - ] - }, - "user_id": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" -}New value: +null
- Changed
delete_webhook1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "deleted": { - "description": "False when there was no registration to delete.", - "type": [ - "boolean", - "null" - ] - } - }, - "type": "object" -}New value: +null
- Removed
exchange_api_key - Added
feedback - Changed
fund_card_balance1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "asset": { - "type": [ - "string", - "null" - ] - }, - "deposit_address": { - "description": "The account holder's own deposit address at the card issuer, on Base.", - "type": [ - "string", - "null" - ] - }, - "funded_usd": { - "description": "USD loaded onto the card balance.", - "type": [ - "number", - "null" - ] - }, - "network": { - "type": [ - "string", - "null" - ] - }, - "note": { - "type": [ - "string", - "null" - ] - }, - "payment_network": { - "description": "The chain the payment settled on: `solana` (bridged to Base over CCTP) or `base` (forwarded directly).", - "type": [ - "string", - "null" - ] - }, - "status": { - "description": "Always `paid` here: the payment settled and delivery to the card balance has started. Follow the later states in `GET /list-card-transactions`.", - "type": [ - "string", - "null" - ] - }, - "top_up_id": { - "description": "Identifies this top-up under `top_ups` in `GET /list-card-transactions`.", - "type": [ - "string", - "null" - ] - } - }, - "type": "object" -}New value: +null
- Changed
get_account_balance1 field changed- changed
Output schema / (root)Previous value: -{ - "description": "Account balance information.", - "properties": { - "balance": { - "description": "Current available balance in USD", - "type": [ - "number", - "null" - ] - }, - "created_timestamp": { - "type": [ - "number", - "null" - ] - }, - "created_timestamp_readable": { - "type": [ - "string", - "null" - ] - }, - "total_deposits": { - "description": "Total lifetime deposits in USD", - "type": [ - "number", - "null" - ] - }, - "user_id": { - "description": "The user's ID (lowercase wallet address)", - "type": [ - "string", - "null" - ] - } - }, - "type": "object" -}New value: +null
- Changed
get_agent_spend_limit1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "default": { - "description": "The limit that applies when the owner has never set one.", - "type": [ - "number", - "null" - ] - }, - "max": { - "description": "The highest value the owner can set.", - "type": [ - "number", - "null" - ] - }, - "maxPerPaymentUsdc": { - "description": "The most a single payment may total, fees included.", - "type": [ - "number", - "null" - ] - }, - "min": { - "description": "The lowest value the owner can set.", - "type": [ - "number", - "null" - ] - } - }, - "type": "object" -}New value: +null
- Changed
get_agent_wallet1 field changed- changed
Output schema / (root)Previous value: -{ - "type": "object" -}New value: +null
- Changed
get_auth_link1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "auth_url": { - "description": "URL to open in a browser to log in to the Laso Finance dashboard. Carries a short single-use login code.", - "type": [ - "string", - "null" - ] - }, - "expires_in": { - "description": "Seconds until the login code expires", - "type": [ - "number", - "null" - ] - }, - "user_id": { - "description": "The authenticated user's ID (wallet address)", - "type": [ - "string", - "null" - ] - } - }, - "type": "object" -}New value: +null
- Changed
get_banking_application1 field changed- changed
Output schema / (root)Previous value: -{ - "type": "object" -}New value: +null
- Changed
get_banking_profile_status1 field changed- changed
Output schema / (root)Previous value: -{ - "type": "object" -}New value: +null
- Changed
get_banking_transaction1 field changed- changed
Output schema / (root)Previous value: -{ - "type": "object" -}New value: +null
- Changed
get_card1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "auth": { - "properties": { - "expires_in": { - "description": "Token lifetime in seconds", - "type": [ - "string", - "null" - ] - }, - "id_token": { - "description": "ID token — use as Bearer token for Laso Finance APIs", - "type": [ - "string", - "null" - ] - }, - "refresh_token": { - "description": "Use with POST /auth (grant_type=refresh_token) to get a new id_token when it expires", - "type": [ - "string", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - }, - "callable_base_url": { - "type": [ - "string", - "null" - ] - }, - "card": { - "description": "Card order info returned by /get-card. Status is always `pending` initially — poll `/get-card-data` to check when card details are ready.", - "properties": { - "card_id": { - "type": [ - "string", - "null" - ] - }, - "country": { - "type": [ - "string", - "null" - ] - }, - "status": { - "description": "Always `pending` at order time. Poll `/get-card-data` to check for `ready`. One of: pending.", - "type": [ - "string", - "null" - ] - }, - "timestamp": { - "type": [ - "number", - "null" - ] - }, - "timestamp_readable": { - "type": [ - "string", - "null" - ] - }, - "usd_amount": { - "type": [ - "number", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - }, - "user_id": { - "description": "The user's ID (lowercase wallet address)", - "type": [ - "string", - "null" - ] - } - }, - "type": "object" -}New value: +null
- Changed
get_card_data1 field changed- changed
Output schema / (root)Previous value: -{ - "anyOf": [ - { - "description": "Response from `/get-card-data`. Three card types share this shape and each populates a different subset.\n\n**Non-reloadable (U.S. and International):** when `status` is `ready`, `card_details` carries the number, CVV, and expiry. International cards add `label`, `charged_usd_amount`, `fees_paid`, `state`, `balance_update_requested_timestamp`, and `queued_order_card_id`.\n\n**Reloadable:** returns `last4`, `expiry`, `balance`, `spend_limit`, `reusable`, `issuer_status`, `created_at`, and `expires_at` instead of the `usd_amount`/`timestamp` fields above. Reading its number and CVV is gated by the card issuer, so exactly one of `card_details`, `details_approval`, or `details_error` is present on a single-card lookup.", - "properties": { - "balance": { - "description": "Reloadable cards only. Spendable balance in dollars.", - "type": [ - "number", - "null" - ] - }, - "balance_update_requested_timestamp": { - "description": "International cards only. Unix timestamp (ms) of an outstanding admin balance update request, or null if none is pending.", - "type": [ - "number", - "null" - ] - }, - "card_details": { - "description": "Only present when status is `ready` (U.S.) or `complete` (international).", - "properties": { - "available_balance": { - "type": [ - "number", - "null" - ] - }, - "billing_address": { - "description": "The card billing address to enter when a merchant asks for one at checkout. The billing name is always `Laso Finance`. For USA non-reloadable cards `required` is `false` (any valid U.S. billing address works; this is a known-good default). For international non-reloadable cards `required` is `true` and the merchant AVS check is validated against exactly this address. On reloadable cards this is always null: the card issuer holds no billing address for a card, and they are AVS-checked against the address the account holder gave at their own identity verification. Ask the holder for it; do not substitute Laso's address.", - "properties": { - "city": { - "type": [ - "string", - "null" - ] - }, - "country": { - "type": [ - "string", - "null" - ] - }, - "line_1": { - "type": [ - "string", - "null" - ] - }, - "line_2": { - "type": [ - "string", - "null" - ] - }, - "name": { - "description": "Always `Laso Finance`.", - "type": [ - "string", - "null" - ] - }, - "note": { - "type": [ - "string", - "null" - ] - }, - "required": { - "description": "`true` if the card enforces AVS against this exact address (international cards); `false` if any valid U.S. address works (USA cards).", - "type": [ - "boolean", - "null" - ] - }, - "state": { - "type": [ - "string", - "null" - ] - }, - "zip": { - "type": [ - "string", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - }, - "card_number": { - "type": [ - "string", - "null" - ] - }, - "cvv": { - "type": [ - "string", - "null" - ] - }, - "exp_month": { - "type": [ - "string", - "null" - ] - }, - "exp_year": { - "type": [ - "string", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - }, - "card_id": { - "type": [ - "string", - "null" - ] - }, - "card_type": { - "description": "One of: Non-Reloadable U.S., Non-Reloadable International, Reloadable.", - "type": [ - "string", - "null" - ] - }, - "charged_usd_amount": { - "description": "International cards only. Amount the user was charged including fees.", - "type": [ - "number", - "null" - ] - }, - "country": { - "description": "U.S. cards only.", - "type": [ - "string", - "null" - ] - }, - "created_at": { - "description": "Reloadable cards only. Epoch milliseconds.", - "type": [ - "number", - "null" - ] - }, - "details_approval": { - "description": "Reloadable cards only, and only for a card the holder created in ANOTHER app. The issuer has emailed them an approve/deny link; retry with `approval_id` once they approve. Cards created through `/create-reloadable-card` are Laso-issued and never take this path.", - "properties": { - "approval_id": { - "type": [ - "string", - "null" - ] - }, - "note": { - "type": [ - "string", - "null" - ] - }, - "status": { - "description": "One of: pending.", - "type": [ - "string", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - }, - "details_error": { - "description": "Reloadable cards only. Present when the issuer could not return the number, so a card with no `card_details` is never silently indistinguishable from one whose details are pending.", - "type": [ - "string", - "null" - ] - }, - "expires_at": { - "description": "Reloadable cards only. Epoch milliseconds, or null when the card does not expire.", - "type": [ - "number", - "null" - ] - }, - "expiry": { - "description": "Reloadable cards only. MM/YY.", - "type": [ - "string", - "null" - ] - }, - "fees_paid": { - "description": "International cards only. Fees paid for this card.", - "type": [ - "number", - "null" - ] - }, - "issuer_status": { - "description": "Reloadable cards only. The issuer's own status string, kept verbatim.", - "type": [ - "string", - "null" - ] - }, - "label": { - "description": "International cards only. User-supplied label, may be empty.", - "type": [ - "string", - "null" - ] - }, - "last4": { - "description": "Reloadable cards only. Last four digits.", - "type": [ - "string", - "null" - ] - }, - "last_updated_timestamp": { - "description": "U.S. cards only. Unix timestamp (ms) of the last time card data was refreshed.", - "type": [ - "number", - "null" - ] - }, - "queued_order_card_id": { - "description": "International cards only. The original `card_id` returned by `/order-intl-card`. After admin fulfillment the card is reissued with a new `card_id` (the issuer's transaction id); querying `/get-card-data?card_id=<original>` continues to resolve to the fulfilled card via this field.", - "type": [ - "string", - "null" - ] - }, - "reusable": { - "description": "Reloadable cards only. True for a multi-use card.", - "type": [ - "boolean", - "null" - ] - }, - "spend_limit": { - "description": "Reloadable cards only. Spend cap in dollars.", - "type": [ - "number", - "null" - ] - }, - "state": { - "description": "International cards only. Raw card state. One of: queued, redeemable, complete, refund-requested, refund-requested-approved-for-queue, archived, refunded.", - "type": [ - "string", - "null" - ] - }, - "status": { - "description": "One of: pending, ready, queued, complete, refund-requested, refunded, archived.", - "type": [ - "string", - "null" - ] - }, - "timestamp": { - "type": [ - "number", - "null" - ] - }, - "timestamp_readable": { - "type": [ - "string", - "null" - ] - }, - "transactions": { - "description": "Card transaction history. U.S. and international cards use slightly different shapes — see `CardTransaction` and `IntlCardTransaction`.", - "items": { - "anyOf": [ - { - "description": "U.S. prepaid card transaction.", - "properties": { - "amount": { - "type": [ - "number", - "null" - ] - }, - "date": { - "type": [ - "string", - "null" - ] - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "is_credit": { - "type": [ - "boolean", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - }, - { - "description": "International prepaid card transaction.", - "properties": { - "amount": { - "description": "Transaction amount in USD.", - "type": [ - "number", - "null" - ] - }, - "date": { - "description": "Unix timestamp (ms) of the transaction.", - "type": [ - "number", - "null" - ] - }, - "merchant": { - "type": [ - "string", - "null" - ] - }, - "status": { - "description": "Optional status, e.g. `pending`.", - "type": [ - "string", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - } - ] - }, - "type": [ - "array", - "null" - ] - }, - "usd_amount": { - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - }, - { - "properties": { - "cards": { - "items": { - "description": "Response from `/get-card-data`. Three card types share this shape and each populates a different subset.\n\n**Non-reloadable (U.S. and International):** when `status` is `ready`, `card_details` carries the number, CVV, and expiry. International cards add `label`, `charged_usd_amount`, `fees_paid`, `state`, `balance_update_requested_timestamp`, and `queued_order_card_id`.\n\n**Reloadable:** returns `last4`, `expiry`, `balance`, `spend_limit`, `reusable`, `issuer_status`, `created_at`, and `expires_at` instead of the `usd_amount`/`timestamp` fields above. Reading its number and CVV is gated by the card issuer, so exactly one of `card_details`, `details_approval`, or `details_error` is present on a single-card lookup.", - "properties": { - "balance": { - "description": "Reloadable cards only. Spendable balance in dollars.", - "type": [ - "number", - "null" - ] - }, - "balance_update_requested_timestamp": { - "description": "International cards only. Unix timestamp (ms) of an outstanding admin balance update request, or null if none is pending.", - "type": [ - "number", - "null" - ] - }, - "card_details": { - "description": "Only present when status is `ready` (U.S.) or `complete` (international).", - "properties": { - "available_balance": { - "type": [ - "number", - "null" - ] - }, - "billing_address": { - "description": "The card billing address to enter when a merchant asks for one at checkout. The billing name is always `Laso Finance`. For USA non-reloadable cards `required` is `false` (any valid U.S. billing address works; this is a known-good default). For international non-reloadable cards `required` is `true` and the merchant AVS check is validated against exactly this address. On reloadable cards this is always null: the card issuer holds no billing address for a card, and they are AVS-checked against the address the account holder gave at their own identity verification. Ask the holder for it; do not substitute Laso's address.", - "properties": { - "city": { - "type": [ - "string", - "null" - ] - }, - "country": { - "type": [ - "string", - "null" - ] - }, - "line_1": { - "type": [ - "string", - "null" - ] - }, - "line_2": { - "type": [ - "string", - "null" - ] - }, - "name": { - "description": "Always `Laso Finance`.", - "type": [ - "string", - "null" - ] - }, - "note": { - "type": [ - "string", - "null" - ] - }, - "required": { - "description": "`true` if the card enforces AVS against this exact address (international cards); `false` if any valid U.S. address works (USA cards).", - "type": [ - "boolean", - "null" - ] - }, - "state": { - "type": [ - "string", - "null" - ] - }, - "zip": { - "type": [ - "string", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - }, - "card_number": { - "type": [ - "string", - "null" - ] - }, - "cvv": { - "type": [ - "string", - "null" - ] - }, - "exp_month": { - "type": [ - "string", - "null" - ] - }, - "exp_year": { - "type": [ - "string", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - }, - "card_id": { - "type": [ - "string", - "null" - ] - }, - "card_type": { - "description": "One of: Non-Reloadable U.S., Non-Reloadable International, Reloadable.", - "type": [ - "string", - "null" - ] - }, - "charged_usd_amount": { - "description": "International cards only. Amount the user was charged including fees.", - "type": [ - "number", - "null" - ] - }, - "country": { - "description": "U.S. cards only.", - "type": [ - "string", - "null" - ] - }, - "created_at": { - "description": "Reloadable cards only. Epoch milliseconds.", - "type": [ - "number", - "null" - ] - }, - "details_approval": { - "description": "Reloadable cards only, and only for a card the holder created in ANOTHER app. The issuer has emailed them an approve/deny link; retry with `approval_id` once they approve. Cards created through `/create-reloadable-card` are Laso-issued and never take this path.", - "properties": { - "approval_id": { - "type": [ - "string", - "null" - ] - }, - "note": { - "type": [ - "string", - "null" - ] - }, - "status": { - "description": "One of: pending.", - "type": [ - "string", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - }, - "details_error": { - "description": "Reloadable cards only. Present when the issuer could not return the number, so a card with no `card_details` is never silently indistinguishable from one whose details are pending.", - "type": [ - "string", - "null" - ] - }, - "expires_at": { - "description": "Reloadable cards only. Epoch milliseconds, or null when the card does not expire.", - "type": [ - "number", - "null" - ] - }, - "expiry": { - "description": "Reloadable cards only. MM/YY.", - "type": [ - "string", - "null" - ] - }, - "fees_paid": { - "description": "International cards only. Fees paid for this card.", - "type": [ - "number", - "null" - ] - }, - "issuer_status": { - "description": "Reloadable cards only. The issuer's own status string, kept verbatim.", - "type": [ - "string", - "null" - ] - }, - "label": { - "description": "International cards only. User-supplied label, may be empty.", - "type": [ - "string", - "null" - ] - }, - "last4": { - "description": "Reloadable cards only. Last four digits.", - "type": [ - "string", - "null" - ] - }, - "last_updated_timestamp": { - "description": "U.S. cards only. Unix timestamp (ms) of the last time card data was refreshed.", - "type": [ - "number", - "null" - ] - }, - "queued_order_card_id": { - "description": "International cards only. The original `card_id` returned by `/order-intl-card`. After admin fulfillment the card is reissued with a new `card_id` (the issuer's transaction id); querying `/get-card-data?card_id=<original>` continues to resolve to the fulfilled card via this field.", - "type": [ - "string", - "null" - ] - }, - "reusable": { - "description": "Reloadable cards only. True for a multi-use card.", - "type": [ - "boolean", - "null" - ] - }, - "spend_limit": { - "description": "Reloadable cards only. Spend cap in dollars.", - "type": [ - "number", - "null" - ] - }, - "state": { - "description": "International cards only. Raw card state. One of: queued, redeemable, complete, refund-requested, refund-requested-approved-for-queue, archived, refunded.", - "type": [ - "string", - "null" - ] - }, - "status": { - "description": "One of: pending, ready, queued, complete, refund-requested, refunded, archived.", - "type": [ - "string", - "null" - ] - }, - "timestamp": { - "type": [ - "number", - "null" - ] - }, - "timestamp_readable": { - "type": [ - "string", - "null" - ] - }, - "transactions": { - "description": "Card transaction history. U.S. and international cards use slightly different shapes — see `CardTransaction` and `IntlCardTransaction`.", - "items": { - "anyOf": [ - { - "description": "U.S. prepaid card transaction.", - "properties": { - "amount": { - "type": [ - "number", - "null" - ] - }, - "date": { - "type": [ - "string", - "null" - ] - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "is_credit": { - "type": [ - "boolean", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - }, - { - "description": "International prepaid card transaction.", - "properties": { - "amount": { - "description": "Transaction amount in USD.", - "type": [ - "number", - "null" - ] - }, - "date": { - "description": "Unix timestamp (ms) of the transaction.", - "type": [ - "number", - "null" - ] - }, - "merchant": { - "type": [ - "string", - "null" - ] - }, - "status": { - "description": "Optional status, e.g. `pending`.", - "type": [ - "string", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - } - ] - }, - "type": [ - "array", - "null" - ] - }, - "usd_amount": { - "type": [ - "number", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - }, - "type": [ - "array", - "null" - ] - } - }, - "type": "object" - } - ], - "type": "object" -}New value: +null
- Changed
get_card_deposit_address1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "address": { - "description": "The holder's own USDC receiving address at the card issuer.", - "type": [ - "string", - "null" - ] - }, - "asset": { - "description": "The asset the address accepts. Always `USDC`.", - "type": [ - "string", - "null" - ] - }, - "balance": { - "description": "Dollars currently on the card balance, or `null` when the issuer cannot read it (which is not the same as zero).", - "type": [ - "number", - "null" - ] - }, - "network": { - "description": "The chain the address accepts. Always `base`.", - "type": [ - "string", - "null" - ] - }, - "note": { - "description": "Chain warning and the next step.", - "type": [ - "string", - "null" - ] - } - }, - "type": "object" -}New value: +null
- Changed
get_kyc_link1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "kyc_url": { - "description": "One-time URL to open to complete identity verification.", - "type": [ - "string", - "null" - ] - }, - "user_id": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" -}New value: +null
- Changed
get_kyc_status1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "kyc_last_reviewed_at": { - "description": "Epoch milliseconds of the last review, or null if never reviewed.", - "type": [ - "number", - "null" - ] - }, - "kyc_review_answer": { - "description": "Latest review answer (e.g. GREEN for approved, RED for rejected), or null if never reviewed.", - "type": [ - "string", - "null" - ] - }, - "kyc_review_status": { - "description": "Latest review status from the verification provider, or null if never reviewed.", - "type": [ - "string", - "null" - ] - }, - "kyc_verified": { - "description": "Whether the wallet has completed identity verification. When true, /send-payment dispatches the payout. When false, /send-payment does not send: it returns kyc_required and the USDC paid lands in account balance (recoverable via POST /withdraw). Verify before calling /send-payment.", - "type": [ - "boolean", - "null" - ] - }, - "user_id": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" -}New value: +null
- Changed
get_payment_status1 field changed- changed
Output schema / (root)Previous value: -{ - "anyOf": [ - { - "properties": { - "payment": { - "description": "One Venmo or PayPal payout sent from this account.", - "properties": { - "amount_pre_fees": { - "description": "Dollars the recipient receives.", - "type": [ - "number", - "null" - ] - }, - "amount_with_fees": { - "description": "Dollars debited from the account balance, fee included.", - "type": [ - "number", - "null" - ] - }, - "fees_paid": { - "type": [ - "number", - "null" - ] - }, - "id": { - "description": "Pass as `payment_id` to fetch this payout on its own.", - "type": [ - "string", - "null" - ] - }, - "platform": { - "description": "One of: venmo, paypal.", - "type": [ - "string", - "null" - ] - }, - "recipient_first_name": { - "type": [ - "string", - "null" - ] - }, - "recipient_id": { - "description": "The saved recipient this went to, as returned by `GET /payment-recipients`.", - "type": [ - "string", - "null" - ] - }, - "recipient_last_name": { - "type": [ - "string", - "null" - ] - }, - "state": { - "description": "`queued` and `in-process` are still in flight. Absent on payouts sent before state tracking existed. One of: queued, in-process, complete, failed, cancelled.", - "type": [ - "string", - "null" - ] - }, - "state_updated_at": { - "description": "Milliseconds since the epoch when `state` last changed.", - "type": [ - "number", - "null" - ] - }, - "timestamp": { - "description": "Milliseconds since the epoch when the payout was sent.", - "type": [ - "number", - "null" - ] - }, - "timestamp_readable": { - "type": [ - "string", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - } - }, - "type": "object" - }, - { - "properties": { - "payments": { - "items": { - "description": "One Venmo or PayPal payout sent from this account.", - "properties": { - "amount_pre_fees": { - "description": "Dollars the recipient receives.", - "type": [ - "number", - "null" - ] - }, - "amount_with_fees": { - "description": "Dollars debited from the account balance, fee included.", - "type": [ - "number", - "null" - ] - }, - "fees_paid": { - "type": [ - "number", - "null" - ] - }, - "id": { - "description": "Pass as `payment_id` to fetch this payout on its own.", - "type": [ - "string", - "null" - ] - }, - "platform": { - "description": "One of: venmo, paypal.", - "type": [ - "string", - "null" - ] - }, - "recipient_first_name": { - "type": [ - "string", - "null" - ] - }, - "recipient_id": { - "description": "The saved recipient this went to, as returned by `GET /payment-recipients`.", - "type": [ - "string", - "null" - ] - }, - "recipient_last_name": { - "type": [ - "string", - "null" - ] - }, - "state": { - "description": "`queued` and `in-process` are still in flight. Absent on payouts sent before state tracking existed. One of: queued, in-process, complete, failed, cancelled.", - "type": [ - "string", - "null" - ] - }, - "state_updated_at": { - "description": "Milliseconds since the epoch when `state` last changed.", - "type": [ - "number", - "null" - ] - }, - "timestamp": { - "description": "Milliseconds since the epoch when the payout was sent.", - "type": [ - "number", - "null" - ] - }, - "timestamp_readable": { - "type": [ - "string", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - }, - "type": [ - "array", - "null" - ] - } - }, - "type": "object" - } - ], - "type": "object" -}New value: +null
- Changed
get_signup_status1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "api_key": { - "description": "Your lasoak_ key. Delivered EXACTLY ONCE — null on any later poll.", - "type": [ - "string", - "null" - ] - }, - "api_key_note": { - "description": "Present only when api_key is null, explaining that it was already delivered.", - "type": [ - "string", - "null" - ] - }, - "auth": { - "description": "An id_token / refresh_token bundle you can use immediately.", - "type": [ - "object", - "null" - ] - }, - "callable_base_url": { - "type": [ - "string", - "null" - ] - }, - "next_steps": { - "items": { - "type": [ - "string", - "null" - ] - }, - "type": [ - "array", - "null" - ] - }, - "status": { - "type": [ - "string", - "null" - ] - }, - "user_id": { - "description": "The Laso user id of the new account.", - "type": [ - "string", - "null" - ] - } - }, - "type": "object" -}New value: +null
- Changed
get_version1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "api_catalog_url": { - "description": "URL of the RFC 9727 API catalog (`application/linkset+json`) indexing the OpenAPI description, the agent docs, and this status route.", - "type": [ - "string", - "null" - ] - }, - "docs": { - "description": "Per-file entries, each with a `url` and a stable `sha256` content identifier. Compare against the values you last saw to tell which file changed.", - "type": [ - "object", - "null" - ] - }, - "docs_manifest_url": { - "description": "URL of the authoritative freshness beacon, served with no-cache.", - "type": [ - "string", - "null" - ] - }, - "docs_version": { - "description": "12-character content hash of the agent docs. Changes only when the docs change.", - "type": [ - "string", - "null" - ] - }, - "note": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" -}New value: +null
- Changed
get_webhook1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "consecutive_failures": { - "type": [ - "number", - "null" - ] - }, - "disabled": { - "description": "True when auto-disabled after repeated delivery failures. Re-register to re-enable.", - "type": [ - "boolean", - "null" - ] - }, - "disabled_reason": { - "type": [ - "string", - "null" - ] - }, - "last_delivery_detail": { - "description": "`HTTP <status>` of the last attempt, or the error message.", - "type": [ - "string", - "null" - ] - }, - "last_delivery_message_id": { - "description": "The `webhook-id` header of the last delivery.", - "type": [ - "string", - "null" - ] - }, - "last_delivery_status": { - "description": "`delivered` or `failed`, or null before the first delivery.", - "type": [ - "string", - "null" - ] - }, - "last_delivery_timestamp": { - "description": "Epoch milliseconds of the last delivery attempt.", - "type": [ - "number", - "null" - ] - }, - "registered": { - "type": [ - "boolean", - "null" - ] - }, - "url": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" -}New value: +null
- Changed
get_withdrawal_status1 field changed- changed
Output schema / (root)Previous value: -{ - "anyOf": [ - { - "properties": { - "withdrawal": { - "description": "A withdrawal status record.", - "properties": { - "address": { - "description": "The wallet address the withdrawal is sent to", - "type": [ - "string", - "null" - ] - }, - "amount": { - "type": [ - "number", - "null" - ] - }, - "asset": { - "type": [ - "string", - "null" - ] - }, - "id": { - "type": [ - "string", - "null" - ] - }, - "network": { - "type": [ - "string", - "null" - ] - }, - "state": { - "type": [ - "string", - "null" - ] - }, - "timestamp": { - "type": [ - "number", - "null" - ] - }, - "timestamp_readable": { - "type": [ - "string", - "null" - ] - }, - "tx_hash": { - "description": "On-chain transaction hash, present once the withdrawal is processed", - "type": [ - "string", - "null" - ] - }, - "tx_url": { - "description": "Block explorer URL for the transaction, present when tx_hash exists", - "type": [ - "string", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - } - }, - "type": "object" - }, - { - "properties": { - "withdrawals": { - "items": { - "description": "A withdrawal status record.", - "properties": { - "address": { - "description": "The wallet address the withdrawal is sent to", - "type": [ - "string", - "null" - ] - }, - "amount": { - "type": [ - "number", - "null" - ] - }, - "asset": { - "type": [ - "string", - "null" - ] - }, - "id": { - "type": [ - "string", - "null" - ] - }, - "network": { - "type": [ - "string", - "null" - ] - }, - "state": { - "type": [ - "string", - "null" - ] - }, - "timestamp": { - "type": [ - "number", - "null" - ] - }, - "timestamp_readable": { - "type": [ - "string", - "null" - ] - }, - "tx_hash": { - "description": "On-chain transaction hash, present once the withdrawal is processed", - "type": [ - "string", - "null" - ] - }, - "tx_url": { - "description": "Block explorer URL for the transaction, present when tx_hash exists", - "type": [ - "string", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - }, - "type": [ - "array", - "null" - ] - } - }, - "type": "object" - } - ], - "type": "object" -}New value: +null
- Changed
list_address_book1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "entries": { - "items": { - "properties": { - "address": { - "description": "The recipient's Solana address. This is the entry's key.", - "type": [ - "string", - "null" - ] - }, - "last_used_at": { - "description": "When a transfer last went to this address, in milliseconds since epoch. Absent if never sent to.", - "type": [ - "number", - "null" - ] - }, - "name": { - "description": "The name your human gave this recipient.", - "type": [ - "string", - "null" - ] - }, - "saved_at": { - "description": "When the entry was last saved or renamed, in milliseconds since epoch.", - "type": [ - "number", - "null" - ] - }, - "send_count": { - "description": "How many transfers have gone to this address.", - "type": [ - "number", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - }, - "type": [ - "array", - "null" - ] - } - }, - "type": "object" -}New value: +null
- Changed
list_bank_recipients1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "recipients": { - "items": { - "properties": { - "address": { - "description": "The payee's postal address, when one is set.", - "type": [ - "object", - "null" - ] - }, - "destinations": { - "items": { - "properties": { - "account_holder_name": { - "type": [ - "string", - "null" - ] - }, - "account_number_last4": { - "type": [ - "string", - "null" - ] - }, - "bank_name": { - "type": [ - "string", - "null" - ] - }, - "crypto_address": { - "type": [ - "string", - "null" - ] - }, - "destination_id": { - "description": "Pass this as `destination_id` to `GET /send-bank-payment`.", - "type": [ - "string", - "null" - ] - }, - "destination_type": { - "description": "One of: fiat_us, fiat_iban, crypto.", - "type": [ - "string", - "null" - ] - }, - "name": { - "type": [ - "string", - "null" - ] - }, - "network_id": { - "type": [ - "string", - "null" - ] - }, - "nickname": { - "description": "User-chosen label, present when one is set. The only editable field on a destination: set it at creation with `addBankingDestination` or later with `updateBankingDestination`.", - "type": [ - "string", - "null" - ] - }, - "routing_number": { - "type": [ - "string", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - }, - "type": [ - "array", - "null" - ] - }, - "name": { - "type": [ - "string", - "null" - ] - }, - "recipient_id": { - "type": [ - "string", - "null" - ] - }, - "status": { - "type": [ - "string", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - }, - "type": [ - "array", - "null" - ] - }, - "user_id": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" -}New value: +null
- Changed
list_banking_accounts1 field changed- changed
Output schema / (root)Previous value: -{ - "type": "object" -}New value: +null
- Changed
list_banking_recipients1 field changed- changed
Output schema / (root)Previous value: -{ - "type": "object" -}New value: +null
- Changed
list_banking_transactions1 field changed- changed
Output schema / (root)Previous value: -{ - "type": "object" -}New value: +null
- Changed
list_card_transactions1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "note": { - "description": "Present only when no card issuer account is linked.", - "type": [ - "string", - "null" - ] - }, - "transactions": { - "items": { - "properties": { - "amount": { - "description": "Transaction amount in US dollars.", - "type": [ - "number", - "null" - ] - }, - "card_id": { - "type": [ - "string", - "null" - ] - }, - "created_at": { - "description": "Milliseconds since the epoch.", - "type": [ - "number", - "null" - ] - }, - "issuer_status": { - "description": "The issuer's own status string, kept verbatim for support.", - "type": [ - "string", - "null" - ] - }, - "merchant": { - "description": "Merchant name, when the issuer reports one.", - "type": [ - "string", - "null" - ] - }, - "status": { - "description": "Lowercased status, e.g. `settled`.", - "type": [ - "string", - "null" - ] - }, - "transaction_id": { - "type": [ - "string", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - }, - "type": [ - "array", - "null" - ] - } - }, - "type": "object" -}New value: +null
- Changed
list_payment_recipients2 fields changed- removed
Input schema / properties / platform / descriptionRemoved value: -"Payment platform whose saved recipients to list." - changed
Output schema / (root)Previous value: -{ - "properties": { - "platform": { - "description": "One of: venmo, paypal.", - "type": [ - "string", - "null" - ] - }, - "recipients": { - "items": { - "properties": { - "display_name": { - "description": "The label the account owner chose. Prefer it when confirming a payment back to a human.", - "type": [ - "string", - "null" - ] - }, - "handle": { - "description": "What to pay them at: a 10-digit phone number for Venmo, an email address for PayPal. Pass this as `recipient_id` to `GET /send-payment`.", - "type": [ - "string", - "null" - ] - }, - "last_sent_timestamp": { - "description": "Milliseconds since the epoch.", - "type": [ - "number", - "null" - ] - }, - "name": { - "description": "The recipient's own name on the platform.", - "type": [ - "string", - "null" - ] - }, - "recipient_id": { - "description": "Opaque id of this saved entry (for example `aQ3xK9mZpL2vB7nR4tYw`). Pass it as `recipient_id` to `POST` and `DELETE /payment-recipients`. It is not what `GET /send-payment` takes; use `handle` there.", - "type": [ - "string", - "null" - ] - }, - "send_count": { - "type": [ - "number", - "null" - ] - }, - "status": { - "type": [ - "string", - "null" - ] - }, - "total_sent": { - "description": "Total dollars sent to this recipient from this account.", - "type": [ - "number", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - }, - "type": [ - "array", - "null" - ] - }, - "user_id": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" -}New value: +null
- Changed
order_gift_card1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "auth": { - "properties": { - "expires_in": { - "description": "Token lifetime in seconds", - "type": [ - "string", - "null" - ] - }, - "id_token": { - "description": "ID token — use as Bearer token for Laso Finance APIs", - "type": [ - "string", - "null" - ] - }, - "refresh_token": { - "description": "Use with POST /auth (grant_type=refresh_token) to get a new id_token when it expires", - "type": [ - "string", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - }, - "callable_base_url": { - "type": [ - "string", - "null" - ] - }, - "gift_card": { - "description": "Gift card order result with redemption details.", - "properties": { - "amount": { - "description": "Gift card face value, denominated in the product's own `currency` (not USD)", - "type": [ - "number", - "null" - ] - }, - "card_id": { - "type": [ - "string", - "null" - ] - }, - "country": { - "type": [ - "string", - "null" - ] - }, - "currency": { - "description": "ISO 4217 code the `amount` is denominated in, e.g. `USD`, `SAR`, `EUR`", - "type": [ - "string", - "null" - ] - }, - "laso_server_id": { - "type": [ - "string", - "null" - ] - }, - "pin_code": { - "description": "PIN code for the gift card (if applicable)", - "type": [ - "string", - "null" - ] - }, - "redemption_code": { - "description": "Code to redeem the gift card (if applicable)", - "type": [ - "string", - "null" - ] - }, - "redemption_url": { - "description": "URL to redeem the gift card (if applicable)", - "type": [ - "string", - "null" - ] - }, - "status": { - "description": "One of: completed.", - "type": [ - "string", - "null" - ] - }, - "timestamp": { - "type": [ - "number", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - }, - "user_id": { - "description": "The user's ID (lowercase wallet address)", - "type": [ - "string", - "null" - ] - } - }, - "type": "object" -}New value: +null
- Changed
order_intl_card1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "auth": { - "properties": { - "expires_in": { - "description": "Token lifetime in seconds", - "type": [ - "string", - "null" - ] - }, - "id_token": { - "description": "ID token — use as Bearer token for Laso Finance APIs", - "type": [ - "string", - "null" - ] - }, - "refresh_token": { - "description": "Use with POST /auth (grant_type=refresh_token) to get a new id_token when it expires", - "type": [ - "string", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - }, - "callable_base_url": { - "type": [ - "string", - "null" - ] - }, - "intl_card_order": { - "properties": { - "charged_usd_amount": { - "type": [ - "number", - "null" - ] - }, - "on_card_usd_amount": { - "type": [ - "number", - "null" - ] - }, - "status": { - "type": [ - "string", - "null" - ] - }, - "timestamp": { - "type": [ - "number", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - }, - "message": { - "type": [ - "string", - "null" - ] - }, - "user_id": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" -}New value: +null
- Changed
pay_x402_endpoint1 field changed- changed
Output schema / (root)Previous value: -{ - "type": "object" -}New value: +null
- Changed
push_to_card1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "amount": { - "description": "The face value sent to the debit card, in the requested `currency`", - "type": [ - "number", - "null" - ] - }, - "auth": { - "properties": { - "expires_in": { - "description": "Token lifetime in seconds", - "type": [ - "string", - "null" - ] - }, - "id_token": { - "description": "ID token — use as Bearer token for Laso Finance APIs", - "type": [ - "string", - "null" - ] - }, - "refresh_token": { - "description": "Use with POST /auth (grant_type=refresh_token) to get a new id_token when it expires", - "type": [ - "string", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - }, - "callable_base_url": { - "type": [ - "string", - "null" - ] - }, - "currency": { - "description": "The target currency of the debit card transfer One of: USD, EUR, GBP.", - "type": [ - "string", - "null" - ] - }, - "message": { - "type": [ - "string", - "null" - ] - }, - "note": { - "description": "Important information about the currency's regional restriction and required form fields", - "type": [ - "string", - "null" - ] - }, - "redemption_url": { - "description": "URL to open and complete the push-to-card transfer. The form requires: sender name, debit card number, and cardholder name.", - "type": [ - "string", - "null" - ] - }, - "success": { - "type": [ - "boolean", - "null" - ] - }, - "user_id": { - "description": "The user's ID (lowercase wallet address)", - "type": [ - "string", - "null" - ] - } - }, - "type": "object" -}New value: +null
- Changed
refresh_card_data1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "message": { - "type": [ - "string", - "null" - ] - }, - "success": { - "type": [ - "boolean", - "null" - ] - } - }, - "type": "object" -}New value: +null
- Changed
refresh_token1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "expires_in": { - "description": "Token lifetime in seconds", - "type": [ - "string", - "null" - ] - }, - "id_token": { - "description": "New ID token — use as Bearer token for Laso Finance APIs", - "type": [ - "string", - "null" - ] - }, - "refresh_token": { - "description": "New refresh token — use for the next refresh", - "type": [ - "string", - "null" - ] - }, - "user_id": { - "description": "The user's ID (lowercase wallet address)", - "type": [ - "string", - "null" - ] - } - }, - "type": "object" -}New value: +null
- Changed
register_webhook1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "registered": { - "type": [ - "boolean", - "null" - ] - }, - "secret": { - "description": "Standard Webhooks signing secret (`whsec_...`). Shown only in this response — store it now. Rotate by re-registering.", - "type": [ - "string", - "null" - ] - }, - "signing": { - "description": "Always `standard-webhooks`.", - "type": [ - "string", - "null" - ] - }, - "url": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" -}New value: +null
- Changed
save_address_book_entry1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "address": { - "type": [ - "string", - "null" - ] - }, - "name": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" -}New value: +null
- Changed
search_docs1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "note": { - "description": "Where to read the full docs when nothing matched.", - "type": "string" - }, - "results": { - "description": "Best-matching doc sections, most relevant first.", - "items": { - "properties": { - "content": { - "description": "Section text, truncated to 2500 characters.", - "type": "string" - }, - "heading": { - "description": "Section heading.", - "type": "string" - }, - "source": { - "description": "Document the section came from.", - "type": "string" - } - }, - "type": "object" - }, - "type": "array" - } - }, - "type": "object" -}New value: +null
- Changed
search_gift_cards1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "count": { - "description": "Number of results returned", - "type": [ - "number", - "null" - ] - }, - "facets": { - "description": "Valid filter values, computed from the full catalog. Use these to discover what you can pass to the `category`, `currency`, and `country` query parameters.", - "properties": { - "categories": { - "description": "All valid `category` filter values.", - "items": { - "type": [ - "string", - "null" - ] - }, - "type": [ - "array", - "null" - ] - }, - "countries": { - "description": "All valid `country` filter values (ISO 3166-1 alpha-2 codes).", - "items": { - "type": [ - "string", - "null" - ] - }, - "type": [ - "array", - "null" - ] - }, - "currencies": { - "description": "All valid `currency` filter values.", - "items": { - "type": [ - "string", - "null" - ] - }, - "type": [ - "array", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - }, - "filters": { - "properties": { - "category": { - "type": [ - "string", - "null" - ] - }, - "country": { - "type": [ - "string", - "null" - ] - }, - "currency": { - "type": [ - "string", - "null" - ] - }, - "query": { - "type": [ - "string", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - }, - "gift_cards": { - "items": { - "description": "A gift card product from the catalog.", - "properties": { - "catalog_info": { - "properties": { - "brand_description": { - "type": [ - "string", - "null" - ] - }, - "redemption_instructions": { - "type": [ - "string", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - }, - "category": { - "description": "Catalog category for the gift card (e.g. \"ecommerce\", \"travel\").", - "type": [ - "string", - "null" - ] - }, - "country": { - "description": "ISO 3166-1 alpha-2 country the gift card belongs to. Null for borderless products available in more than one country.", - "type": [ - "string", - "null" - ] - }, - "currency": { - "description": "Currency code for the gift card", - "type": [ - "string", - "null" - ] - }, - "denominations": { - "description": "If set, only these exact amounts can be ordered. Null for range-based products.", - "items": { - "type": [ - "string", - "null" - ] - }, - "type": [ - "array", - "null" - ] - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "increment": { - "description": "Minimum order increment", - "type": [ - "string", - "null" - ] - }, - "laso_server_id": { - "description": "Product identifier to use when ordering via GET /order-gift-card", - "type": [ - "string", - "null" - ] - }, - "max": { - "description": "Maximum order amount", - "type": [ - "number", - "null" - ] - }, - "min": { - "description": "Minimum order amount", - "type": [ - "number", - "null" - ] - }, - "name": { - "description": "Gift card brand name", - "type": [ - "string", - "null" - ] - }, - "product_image_url": { - "description": "URL of the gift card image", - "type": [ - "string", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - }, - "type": [ - "array", - "null" - ] - } - }, - "type": "object" -}New value: +null
- Changed
search_merchants1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "card_type": { - "description": "The card type results are filtered for", - "type": [ - "string", - "null" - ] - }, - "count": { - "description": "Number of merchants returned", - "type": [ - "number", - "null" - ] - }, - "merchants": { - "items": { - "description": "A merchant from the spend data database with its acceptance status for the Non-Reloadable U.S. card.", - "properties": { - "description": { - "description": "Brief description of the merchant", - "type": [ - "string", - "null" - ] - }, - "name": { - "description": "Merchant name", - "type": [ - "string", - "null" - ] - }, - "notes": { - "description": "Additional notes about using the card at this merchant", - "type": [ - "string", - "null" - ] - }, - "restriction_note": { - "description": "Present when the merchant is restricted rather than merely untested. Banking and money-transfer merchants are always reported as `not_accepted`, because spending there counts as a transfer of value. Approvals do occur at these merchants, so acceptance cannot be read off the transaction history. `null` for every other merchant.", - "type": [ - "string", - "null" - ] - }, - "status": { - "description": "Whether the Non-Reloadable U.S. card is accepted at this merchant. `accepted` = confirmed working, `not_accepted` = confirmed failing or restricted, `unknown` = card type not yet tried at this merchant. One of: accepted, not_accepted, unknown.", - "type": [ - "string", - "null" - ] - }, - "url": { - "description": "Merchant website URL", - "type": [ - "string", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - }, - "type": [ - "array", - "null" - ] - }, - "note": { - "description": "Important caveat about the data — this database only includes merchants where users have previously attempted transactions", - "type": [ - "string", - "null" - ] - }, - "query": { - "description": "The search query that was used", - "type": [ - "string", - "null" - ] - } - }, - "type": "object" -}New value: +null
- Changed
send_bank_payment1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "auth": { - "properties": { - "expires_in": { - "description": "Token lifetime in seconds", - "type": [ - "string", - "null" - ] - }, - "id_token": { - "description": "ID token — use as Bearer token for Laso Finance APIs", - "type": [ - "string", - "null" - ] - }, - "refresh_token": { - "description": "Use with POST /auth (grant_type=refresh_token) to get a new id_token when it expires", - "type": [ - "string", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - }, - "bank_payment": { - "properties": { - "amount": { - "description": "USD delivered to the bank account.", - "type": [ - "number", - "null" - ] - }, - "charged_amount": { - "description": "amount + fee_amount, the total debited.", - "type": [ - "number", - "null" - ] - }, - "destination": { - "description": "The bank account being paid, summarized. The account number is masked to its last four digits.", - "properties": { - "account_holder_name": { - "type": [ - "string", - "null" - ] - }, - "account_number_last4": { - "type": [ - "string", - "null" - ] - }, - "bank_name": { - "type": [ - "string", - "null" - ] - }, - "name": { - "type": [ - "string", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - }, - "destination_id": { - "type": [ - "string", - "null" - ] - }, - "fee_amount": { - "description": "Transfer fee charged on top of the amount.", - "type": [ - "number", - "null" - ] - }, - "payout_id": { - "type": [ - "string", - "null" - ] - }, - "state": { - "type": [ - "string", - "null" - ] - }, - "timestamp": { - "type": [ - "number", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - }, - "callable_base_url": { - "type": [ - "string", - "null" - ] - }, - "message": { - "type": [ - "string", - "null" - ] - }, - "success": { - "type": [ - "boolean", - "null" - ] - }, - "user_id": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" -}New value: +null
- Removed
send_feedback - Changed
send_payment1 field changed- changed
Output schema / (root)Previous value: -{ - "anyOf": [ - { - "properties": { - "amount": { - "type": [ - "number", - "null" - ] - }, - "auth": { - "properties": { - "expires_in": { - "description": "Token lifetime in seconds", - "type": [ - "string", - "null" - ] - }, - "id_token": { - "description": "ID token — use as Bearer token for Laso Finance APIs", - "type": [ - "string", - "null" - ] - }, - "refresh_token": { - "description": "Use with POST /auth (grant_type=refresh_token) to get a new id_token when it expires", - "type": [ - "string", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - }, - "callable_base_url": { - "type": [ - "string", - "null" - ] - }, - "message": { - "type": [ - "string", - "null" - ] - }, - "platform": { - "description": "One of: venmo, paypal.", - "type": [ - "string", - "null" - ] - }, - "recipient_id": { - "type": [ - "string", - "null" - ] - }, - "state": { - "description": "Payment lifecycle state (e.g. `in-process`, `queued`).", - "type": [ - "string", - "null" - ] - }, - "success": { - "type": [ - "boolean", - "null" - ] - }, - "user_id": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - { - "properties": { - "amount": { - "type": [ - "number", - "null" - ] - }, - "auth": { - "properties": { - "expires_in": { - "description": "Token lifetime in seconds", - "type": [ - "string", - "null" - ] - }, - "id_token": { - "description": "ID token — use as Bearer token for Laso Finance APIs", - "type": [ - "string", - "null" - ] - }, - "refresh_token": { - "description": "Use with POST /auth (grant_type=refresh_token) to get a new id_token when it expires", - "type": [ - "string", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - }, - "callable_base_url": { - "type": [ - "string", - "null" - ] - }, - "kyc_required": { - "description": "One of: true.", - "type": [ - "boolean", - "null" - ] - }, - "kyc_url": { - "description": "URL the wallet owner must open to complete identity verification. No payout was sent, but the x402 payment you made was still credited to your Laso account balance. After verifying, retry /send-payment to dispatch the payout, or call POST /withdraw to pull the credited USDC back to your wallet.", - "type": [ - "string", - "null" - ] - }, - "message": { - "description": "Human-readable explanation of the KYC requirement and how to recover the credited funds via retry or POST /withdraw.", - "type": [ - "string", - "null" - ] - }, - "platform": { - "description": "One of: venmo, paypal.", - "type": [ - "string", - "null" - ] - }, - "recipient_id": { - "type": [ - "string", - "null" - ] - }, - "user_id": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - } - ], - "type": "object" -}New value: +null
- Changed
start_signup1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "claim_code": { - "description": "The code inside claim_url. Pass it back to /signup-status alongside claim_token.", - "type": [ - "string", - "null" - ] - }, - "claim_token": { - "description": "Your receipt for this signup. Shown once; store it. Exchanged at /signup-status for your API key.", - "type": [ - "string", - "null" - ] - }, - "claim_url": { - "description": "Give this to your human verbatim. Never open it yourself.", - "type": [ - "string", - "null" - ] - }, - "expires_at": { - "description": "Epoch ms when the claim link expires.", - "type": [ - "number", - "null" - ] - }, - "expires_in": { - "description": "Seconds until the claim link expires (86400).", - "type": [ - "number", - "null" - ] - }, - "message_for_human": { - "description": "A ready-to-send reply containing the link. Send this as your next message.", - "type": [ - "string", - "null" - ] - }, - "next_steps": { - "items": { - "type": [ - "string", - "null" - ] - }, - "type": [ - "array", - "null" - ] - } - }, - "type": "object" -}New value: +null
- Changed
submit_banking_application1 field changed- changed
Output schema / (root)Previous value: -{ - "type": "object" -}New value: +null
- Changed
update_banking_application_details1 field changed- changed
Output schema / (root)Previous value: -{ - "type": "object" -}New value: +null
- Changed
update_banking_destination1 field changed- changed
Output schema / (root)Previous value: -{ - "type": "object" -}New value: +null
- Changed
update_payment_recipient2 fields changed- removed
Input schema / properties / platform / descriptionRemoved value: -"Payment platform the recipient is saved under." - changed
Output schema / (root)Previous value: -{ - "properties": { - "archived": { - "type": [ - "boolean", - "null" - ] - }, - "display_name": { - "type": [ - "string", - "null" - ] - }, - "platform": { - "type": [ - "string", - "null" - ] - }, - "recipient_id": { - "type": [ - "string", - "null" - ] - }, - "user_id": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" -}New value: +null
- Changed
upload_banking_document1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "documentId": { - "type": [ - "string", - "null" - ] - }, - "status": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" -}New value: +null
- Changed
withdraw1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "success": { - "type": [ - "boolean", - "null" - ] - }, - "withdrawal": { - "description": "A withdrawal record.", - "properties": { - "amount": { - "type": [ - "number", - "null" - ] - }, - "id": { - "type": [ - "string", - "null" - ] - }, - "solana_address": { - "description": "The Solana address the USDC will be sent to.", - "type": [ - "string", - "null" - ] - }, - "state": { - "description": "One of: pending.", - "type": [ - "string", - "null" - ] - }, - "timestamp": { - "type": [ - "number", - "null" - ] - }, - "timestamp_readable": { - "type": [ - "string", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - } - }, - "type": "object" -}New value: +null
- Changed
withdraw_card_balance1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "amount": { - "description": "USD the issuer will pay out.", - "type": [ - "number", - "null" - ] - }, - "asset": { - "type": [ - "string", - "null" - ] - }, - "destination_address": { - "description": "The Base address the USDC goes to.", - "type": [ - "string", - "null" - ] - }, - "network": { - "type": [ - "string", - "null" - ] - }, - "note": { - "description": "Timing and where to see the request afterwards.", - "type": [ - "string", - "null" - ] - }, - "status": { - "description": "Always `requested`: the issuer has accepted the request and will pay it out manually.", - "type": [ - "string", - "null" - ] - }, - "withdrawal_id": { - "description": "The card issuer's reference for this payout request. Quote it to support; it also appears on the matching `withdrawal` card event.", - "type": [ - "string", - "null" - ] - } - }, - "type": "object" -}New value: +null
62 tool updates
- First observed
add_banking_destination - First observed
agent_wallet_transfer - First observed
announce_connection - First observed
cancel_intl_order - First observed
create_agent_api_key - First observed
create_agent_wallet - First observed
create_banking_account - First observed
create_banking_profile - First observed
create_banking_recipient - First observed
create_reloadable_card - First observed
delete_address_book_entry - First observed
delete_banking_recipient - First observed
delete_payment_recipient - First observed
delete_webhook - First observed
exchange_api_key - First observed
fund_card_balance - First observed
get_account_balance - First observed
get_agent_spend_limit - First observed
get_agent_wallet - First observed
get_auth_link - First observed
get_banking_application - First observed
get_banking_profile_status - First observed
get_banking_transaction - First observed
get_card - First observed
get_card_data - First observed
get_card_deposit_address - First observed
get_kyc_link - First observed
get_kyc_status - First observed
get_payment_status - First observed
get_signup_status - First observed
get_version - First observed
get_webhook - First observed
get_withdrawal_status - First observed
list_address_book - First observed
list_bank_recipients - First observed
list_banking_accounts - First observed
list_banking_recipients - First observed
list_banking_transactions - First observed
list_card_transactions - First observed
list_payment_recipients - First observed
order_gift_card - First observed
order_intl_card - First observed
pay_x402_endpoint - First observed
push_to_card - First observed
refresh_card_data - First observed
refresh_token - First observed
register_webhook - First observed
save_address_book_entry - First observed
search_docs - First observed
search_gift_cards - First observed
search_merchants - First observed
send_bank_payment - First observed
send_feedback - First observed
send_payment - First observed
start_signup - First observed
submit_banking_application - First observed
update_banking_application_details - First observed
update_banking_destination - First observed
update_payment_recipient - First observed
upload_banking_document - First observed
withdraw - First observed
withdraw_card_balance
Publisher details
- Operator
- Laso Finance LLC · Publisher source
- Operator website
- https://laso.finance · Publisher source
- Vendor relationship
- First-party · Publisher source
- Documentation
- https://docs.laso.finance/guides/mcp-server · Publisher source
- Trust center
- Not available
- Restrictions
- Requires a Laso Finance account, connected by OAuth sign-in or a Laso API key. get_version and search_docs work without one. Paid tools settle in USDC from the agent's funded wallet, and some products require the human account owner to complete identity verification. · Publisher source
Related MCP Connectors
Issue and top up x402 virtual cards or buy Freeland travel eSIMs with Base USDC.
USDC invoicing on Base: send invoices, share pay links, track payments and customers.
1Non-custodial stablecoin bill-pay rails on Celo & Base for AI agents, settled on-chain via MCP.
Private stablecoin payments for people and AI agents, hosted or local with spending limits.
Related MCP Servers
AlicenseAqualityFmaintenancePrepare custody-separated Base USDC cash-out plans, list supported fiat rails, and track settlement state through Peer Cash.936 npmMIT- AlicenseNot gradedqualityCmaintenanceEnables agents to spend funds on Visa/MasterCard prepaid cards, travel eSIMs, and gift cards, with paid KYT address screening and USDT TRC-20 funding.MIT
- AlicenseAqualityCmaintenanceEnables AI agents to spend with the user's own key by paying via USDT TRC-20 and buying Visa/Mastercard prepaid cards, travel eSIMs, and gift cards, and also provides access to policy and how-to documentation.6MIT

fiatdock-mcpofficial
AlicenseAqualityCmaintenanceNon-custodial USDC <-> bank for AI agents. Free quotes; $0.05 USDC per session via x402; 1% commission itemised in every quote. Own funds only. PT + EU/EEA (not UK). 18+.4341 npm1MIT
Glama MCP Gateway
Add one secure layer between your agents and this server.