Every API here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for apis
7 MCP tools reach this
find_apisBrowse and filter every API in the catalog.
get_api_artifactsOne API's artifacts, grouped by type.
get_openapiThe primary OpenAPI for this API.
find_similar_apisAPIs that look like this one.
apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
resolveTurn a domain, URL or GitHub org into the provider it belongs to.
find_cohortsEvery scored population of providers in the catalog.
All 92 tools →
Call it yourself
curl for this page
This API
curl "https://apis.io/api/v1/apis/lightspark:lightspark-exchange-rates-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we
store it to create your key and to recognise you if you sign in with another
provider. See our Privacy Policy and
Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: Grid Exchange Rates API
description: API for managing global payments on the open Money Grid. Built by Lightspark. See the full documentation at https://docs.lightspark.com/.
version: '2025-10-13'
contact:
name: Lightspark Support
email: support@lightspark.com
license:
name: Proprietary
url: https://lightspark.com/terms
servers:
- url: https://api.lightspark.com/grid/2025-10-13
description: Production server
security:
- BasicAuth: []
- AgentAuth: []
tags:
- name: Exchange Rates
description: Endpoints for retrieving cached foreign exchange rates. Rates are cached for approximately 5 minutes and include platform-specific fees.
paths:
/exchange-rates:
get:
summary: Get exchange rates
description: 'Retrieve cached exchange rates for currency corridors. Returns FX rates that are cached
for approximately 5 minutes. Rates include fees specific to your platform for authenticated requests.
**Filtering Options:**
- Filter by source currency to get all available destination corridors
- Filter by specific destination currency or currencies
- Provide a sending amount to get calculated receiving amounts'
operationId: getExchangeRates
tags:
- Exchange Rates
security:
- BasicAuth: []
parameters:
- name: sourceCurrency
in: query
description: Filter by source currency code (e.g., USD)
required: false
schema:
type: string
example: USD
- name: destinationCurrency
in: query
description: Filter by destination currency code(s). Can be repeated for multiple currencies (e.g., &destinationCurrency=INR&destinationCurrency=GBP)
required: false
style: form
explode: true
schema:
type: array
items:
type: string
example:
- INR
- name: sendingAmount
in: query
description: Sending amount in the smallest unit of the source currency (e.g., cents for USD). If omitted, USD and USD-pegged currencies default to $100 (10000 USD cents, scaled to the source currency's precision; e.g., 100000000 for USDC, which is 100 USDC). Other currencies default to 10000 in the source currency's smallest unit.
required: false
schema:
type: integer
format: int64
exclusiveMinimum: 0
default: 10000
example: 10000
responses:
'200':
description: Successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/ExchangeRateListResponse'
examples:
allRatesFromUSD:
summary: All exchange rates from USD
value:
data:
- sourceCurrency:
code: USD
decimals: 2
name: US Dollar
symbol: $
sendingAmount: 10000
minSendingAmount: 100
maxSendingAmount: 10000000
destinationCurrency:
code: INR
decimals: 2
name: Indian Rupee
symbol: ₹
destinationPaymentRail: UPI
receivingAmount: 825000
exchangeRate: 0.012121
fees:
fixed: 100
total: 150
updatedAt: '2025-02-05T12:00:00Z'
- sourceCurrency:
code: USD
decimals: 2
name: US Dollar
symbol: $
sendingAmount: 10000
minSendingAmount: 100
maxSendingAmount: 10000000
destinationCurrency:
code: EUR
decimals: 2
name: Euro
symbol: €
destinationPaymentRail: SEPA_INSTANT
receivingAmount: 9250
exchangeRate: 1.081081
fees:
fixed: 10
total: 15
updatedAt: '2025-02-05T12:00:00Z'
'400':
description: Bad request - Invalid parameters
content:
application/json:
schema:
$ref: '#/components/schemas/Error400'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error401'
'500':
description: Internal service error
content:
application/json:
schema:
$ref: '#/components/schemas/Error500'
components:
schemas:
ExchangeRateListResponse:
type: object
required:
- data
properties:
data:
type: array
description: List of exchange rates matching the filter criteria
items:
$ref: '#/components/schemas/ExchangeRate'
PaymentDocumentRequirementId:
type: string
description: 'A stable identifier for one required document within a purpose''s requirements. The same ID means the same requirement across quotes. It is separate from `PaymentDocumentType`. The requirement ID names the document to supply, and the document type names what a file is. The two differ where a requirement accepts alternatives. For example, a file declared as either `PURCHASE_ORDER` or `DELIVERY_SLIP` fills the `SUPPORTING_PROOF` requirement.
[Supporting Documents](https://docs.lightspark.com/payouts-and-b2b/payment-flow/send-payment#supporting-documents) lists the IDs each purpose requires.
Treat the ID as an opaque value, not a member of a fixed list. Grid may add new IDs as requirements change.'
example: SUPPORTING_PROOF
FieldError:
type: object
required:
- field
description: One field-level validation failure. Field-validation errors on submit endpoints (e.g. `POST /customers`, `PATCH /customers/{id}`) emit an array of these under `details.errors` so platforms can render form-field-level UX for every failure in a single round-trip.
properties:
field:
type: string
description: Dot-notation path to the offending field.
example: identifier
constraint:
$ref: '#/components/schemas/FieldConstraint'
message:
type: string
description: Human-readable explanation of what's wrong with this field.
example: Value is not one of the allowed enum members.
ExchangeRate:
type: object
description: Exchange rate information for a currency corridor
required:
- sourceCurrency
- destinationCurrency
- destinationPaymentRail
- minSendingAmount
- maxSendingAmount
- sendingAmount
- receivingAmount
- exchangeRate
- fees
- updatedAt
properties:
sourceCurrency:
$ref: '#/components/schemas/Currency'
sendingAmount:
type: integer
format: int64
description: The sending amount in the smallest unit of the source currency (e.g., cents for USD). Echoed back from the request if provided.
minimum: 0
example: 10000
minSendingAmount:
type: integer
format: int64
description: The minimum supported sending amount in the smallest unit of the source currency.
minimum: 0
example: 100
maxSendingAmount:
type: integer
format: int64
description: The maximum supported sending amount in the smallest unit of the source currency.
minimum: 0
example: 10000000
destinationCurrency:
$ref: '#/components/schemas/Currency'
destinationPaymentRail:
allOf:
- $ref: '#/components/schemas/PaymentRail'
- description: The payment rail used for the destination (e.g., UPI, SEPA_INSTANT, MOBILE_MONEY, FASTER_PAYMENTS)
example: UPI
receivingAmount:
type: integer
format: int64
description: The receiving amount in the smallest unit of the destination currency
minimum: 0
example: 1650000
exchangeRate:
type: number
description: 'Number of sending currency units per receiving currency unit. The rate is fee-exclusive: it covers the currency conversion only, and Grid charges `fees` separately rather than pricing them into the rate.'
exclusiveMinimum: 0
example: 0.012121
fees:
$ref: '#/components/schemas/ExchangeRateFees'
updatedAt:
type: string
format: date-time
description: Timestamp when this exchange rate was last refreshed
example: '2025-02-05T12:00:00Z'
Error500:
type: object
required:
- reason
- code
properties:
code:
type: string
description: '| Error Code | Description |
|------------|-------------|
| GRID_SWITCH_ERROR | Grid switch error |
| INTERNAL_ERROR | Internal server or UMA error |
'
enum:
- GRID_SWITCH_ERROR
- INTERNAL_ERROR
reason:
type: string
description: Error message
details:
type: object
description: Additional error details
additionalProperties: true
PaymentRail:
type: string
enum:
- ACH
- ACH_COLOMBIA
- ACH_SAME_DAY
- BANK_TRANSFER
- BRE_B
- CIPS
- FAST
- FASTER_PAYMENTS
- FEDNOW
- INSTAPAY
- MOBILE_MONEY
- NEFT
- PAYNOW
- PESONET
- PIX
- RTGS
- RTP
- SEPA
- SEPA_INSTANT
- SPEI
- SWIFT
- UNIONPAY
- UPI
- WIRE
description: 'The payment rail used for the transfer. Payment rails represent the underlying payment network or system used to move funds between accounts.
`ACH_SAME_DAY` requests same-business-day settlement for a USD payout and is priced separately. It is subject to the NACHA per-entry same-day limit, which the network applies to every originator: $1,000,000 per entry, rising to $10,000,000 on 2027-09-17. A payout above that limit is rejected rather than slowed — check the amount before requesting this rail, or send it over `ACH`, which settles on the standard schedule and has no such limit.
`ACH` will settle on the standard next-business-day schedule. Until a date we announce in advance, `ACH` continues to settle same-business-day on production platforms; it already settles next-business-day on sandbox platforms. To guarantee same-day settlement after that date, request `ACH_SAME_DAY`.'
example: ACH
Error400:
type: object
required:
- reason
- code
properties:
code:
type: string
description: '| Error Code | Description |
|------------|-------------|
| INVALID_INPUT | Invalid input provided |
| END_USER_TERMS_VERSION_NOT_FOUND | The submitted version is not supported for the agreement it was sent for |
| MISSING_MANDATORY_USER_INFO | Required customer information is missing |
| INVITATION_ALREADY_CLAIMED | Invitation has already been claimed |
| INVITATIONS_NOT_CONFIGURED | Invitations are not configured |
| INVALID_UMA_ADDRESS | UMA address format is invalid |
| INVITATION_CANCELLED | Invitation has been cancelled |
| INVALID_RECEIVER | Receiver is invalid |
| PARSE_PAYREQ_RESPONSE_ERROR | Error parsing receiver PayReq response |
| CERT_CHAIN_INVALID | Counterparty certificate chain is invalid |
| CERT_CHAIN_EXPIRED | Counterparty certificate chain has expired |
| INVALID_PUBKEY_FORMAT | Counterparty Public key format is invalid |
| MISSING_REQUIRED_UMA_PARAMETERS | Counterparty required UMA parameters are missing |
| SENDER_NOT_ACCEPTED | The receiving institution declined this sender. Final; a retry returns the same answer |
| AMOUNT_OUT_OF_RANGE | Amount is out of range |
| INVALID_CURRENCY | Currency is invalid |
| INVALID_TIMESTAMP | Timestamp is invalid |
| INVALID_NONCE | Nonce is invalid |
| INVALID_REQUEST_FORMAT | Request format is invalid |
| INVALID_BANK_ACCOUNT | Bank account is invalid |
| SELF_PAYMENT | Self payment not allowed |
| PARSE_LNURLP_RESPONSE_ERROR | Error parsing LNURLP response |
| INVALID_AMOUNT | Amount is invalid |
| WEBHOOK_ENDPOINT_NOT_SET | Webhook endpoint is not set |
| WEBHOOK_DELIVERY_ERROR | Webhook delivery error |
| LOW_QUALITY | Document quality too low to process |
| DATA_MISMATCH | Document details don''t match provided information |
| EXPIRED | Document has expired |
| SUSPECTED_FRAUD | Document suspected of being forged or edited |
| UNSUITABLE_DOCUMENT | Document type is not accepted or not supported |
| INCOMPLETE | Document is missing pages or sides |
| EMAIL_OTP_CREDENTIAL_ALREADY_EXISTS | An EMAIL_OTP credential is already registered on the target internal account; only one email OTP credential is supported per internal account at this time |
| SMS_OTP_CREDENTIAL_ALREADY_EXISTS | An SMS_OTP credential is already registered on the target internal account; only one SMS OTP credential is supported per internal account at this time |
| PASSKEY_CREDENTIAL_ALREADY_EXISTS | A PASSKEY credential with the same WebAuthn credentialId is already registered on the target internal account |
| AUTH_CREDENTIAL_VERIFICATION_REQUIRED | The new email or phone number has no verified replacement credential |
| AUTH_CREDENTIAL_VERIFICATION_EXPIRED | The replacement credential''s verification has expired |
| STABLECOIN_PROVIDER_ACCOUNT_INVALID | The stablecoin provider account link is not usable |
| STABLECOIN_PROVIDER_ACCOUNT_REVOKED | The stablecoin provider account link has been revoked |
| STABLECOIN_PROVIDER_ACCOUNT_SELECTION_REQUIRED | Multiple active provider account links exist; pass `stablecoinProviderAccountId` to select one |
| CARDHOLDER_KYC_NOT_APPROVED | The cardholder''s KYC status is not `APPROVED`, so a card cannot be issued |
| ACCOUNTHOLDER_AGREEMENT_NOT_ACCEPTED | The customer create request omits an accountholder agreement its accounts require |
| TRANSACTION_SIZE_LIMIT_EXCEEDED | The requested amount exceeds the configured maximum single-transaction amount for this trade corridor or withdrawal currency |
| EXTERNAL_ACCOUNT_VERIFICATION_REQUIRED | The destination account''s ownership must be verified before this transfer can proceed |
| INSUFFICIENT_FUNDS | Insufficient funds for this operation |
| QUOTE_EXPIRED | The quote has expired; request a new quote |
| QUOTE_RATE_UNAVAILABLE | No exchange rate is available for this corridor right now |
| STABLECOIN_AMOUNT_NOT_REPRESENTABLE | The amount cannot be represented at the token''s precision |
| STABLECOIN_BURN_SOURCE_NOT_SUPPORTED | The burn source account cannot be used for this operation |
| STABLECOIN_EXTERNAL_ACCOUNT_LINK_FAILED | Linking the external account for stablecoin operations failed |
| STABLECOIN_EXTERNAL_ACCOUNT_LINK_METHOD_REQUIRED | The external account needs a link method before it can be used |
| STABLECOIN_EXTERNAL_ACCOUNT_NOT_LINKED | The external account is not linked for stablecoin operations |
| STABLECOIN_EXTERNAL_ACCOUNT_NOT_SUPPORTED | This external account type is not supported for stablecoin operations |
| STABLECOIN_EXTERNAL_ACCOUNT_PROVIDER_LINK_FAILED | The provider could not link the external account |
| STABLECOIN_EXTERNAL_ACCOUNT_PROVIDER_LINK_REQUIRED | The external account must be linked with the provider first |
| STABLECOIN_GRID_OPERATIONS_NOT_ENABLED | The stablecoin is not enabled for Grid operations |
| STABLECOIN_NOT_PROVISIONED | The stablecoin is not provisioned for issuer operations |
| STABLECOIN_OPERATION_NOT_SUPPORTED | The stablecoin does not support this operation |
| STABLECOIN_PROVIDER_ERROR | The stablecoin provider rejected the operation |
| STABLECOIN_PROVIDER_SOURCE_NOT_LINKED | The provider source account is not linked |
| STABLECOIN_VERIFICATION_FAILED | The stablecoin could not be verified with the provider |
| DOCUMENTS_REQUIRED | The destination requires supporting documents for the quote''s `purposeOfPayment` that the request did not supply. `details.missingRequirements` lists the requirement ID of each one |
'
enum:
- INVALID_INPUT
- END_USER_TERMS_VERSION_NOT_FOUND
- MISSING_MANDATORY_USER_INFO
- INVITATION_ALREADY_CLAIMED
- INVITATIONS_NOT_CONFIGURED
- INVALID_UMA_ADDRESS
- INVITATION_CANCELLED
- INVALID_RECEIVER
- PARSE_PAYREQ_RESPONSE_ERROR
- CERT_CHAIN_INVALID
- CERT_CHAIN_EXPIRED
- INVALID_PUBKEY_FORMAT
- MISSING_REQUIRED_UMA_PARAMETERS
- SENDER_NOT_ACCEPTED
- AMOUNT_OUT_OF_RANGE
- INVALID_CURRENCY
- INVALID_TIMESTAMP
- INVALID_NONCE
- INVALID_REQUEST_FORMAT
- INVALID_BANK_ACCOUNT
- SELF_PAYMENT
- PARSE_LNURLP_RESPONSE_ERROR
- INVALID_AMOUNT
- WEBHOOK_ENDPOINT_NOT_SET
- WEBHOOK_DELIVERY_ERROR
- LOW_QUALITY
- DATA_MISMATCH
- EXPIRED
- SUSPECTED_FRAUD
- UNSUITABLE_DOCUMENT
- INCOMPLETE
- EMAIL_OTP_CREDENTIAL_ALREADY_EXISTS
- SMS_OTP_CREDENTIAL_ALREADY_EXISTS
- PASSKEY_CREDENTIAL_ALREADY_EXISTS
- AUTH_CREDENTIAL_VERIFICATION_REQUIRED
- AUTH_CREDENTIAL_VERIFICATION_EXPIRED
- STABLECOIN_PROVIDER_ACCOUNT_INVALID
- STABLECOIN_PROVIDER_ACCOUNT_REVOKED
- STABLECOIN_PROVIDER_ACCOUNT_SELECTION_REQUIRED
- CARDHOLDER_KYC_NOT_APPROVED
- ACCOUNTHOLDER_AGREEMENT_NOT_ACCEPTED
- TRANSACTION_SIZE_LIMIT_EXCEEDED
- EXTERNAL_ACCOUNT_VERIFICATION_REQUIRED
- INSUFFICIENT_FUNDS
- QUOTE_EXPIRED
- QUOTE_RATE_UNAVAILABLE
- STABLECOIN_AMOUNT_NOT_REPRESENTABLE
- STABLECOIN_BURN_SOURCE_NOT_SUPPORTED
- STABLECOIN_EXTERNAL_ACCOUNT_LINK_FAILED
- STABLECOIN_EXTERNAL_ACCOUNT_LINK_METHOD_REQUIRED
- STABLECOIN_EXTERNAL_ACCOUNT_NOT_LINKED
- STABLECOIN_EXTERNAL_ACCOUNT_NOT_SUPPORTED
- STABLECOIN_EXTERNAL_ACCOUNT_PROVIDER_LINK_FAILED
- STABLECOIN_EXTERNAL_ACCOUNT_PROVIDER_LINK_REQUIRED
- STABLECOIN_GRID_OPERATIONS_NOT_ENABLED
- STABLECOIN_NOT_PROVISIONED
- STABLECOIN_OPERATION_NOT_SUPPORTED
- STABLECOIN_PROVIDER_ERROR
- STABLECOIN_PROVIDER_SOURCE_NOT_LINKED
- STABLECOIN_VERIFICATION_FAILED
- DOCUMENTS_REQUIRED
reason:
type: string
description: Error message
details:
type: object
description: Additional error details. Shape varies by `code`. For field-validation errors on submit endpoints (e.g. `POST /customers`, `PATCH /customers/{id}`), `details.errors[]` enumerates every invalid field so platforms can render form-field-level UX for the entire request in a single round-trip.
properties:
errors:
type: array
description: One entry per invalid field. Present on field-validation errors from submit endpoints.
items:
$ref: '#/components/schemas/FieldError'
missingRequirements:
type: array
description: The requirement ID of each required document that the quote request did not supply. Present on `DOCUMENTS_REQUIRED`.
items:
$ref: '#/components/schemas/PaymentDocumentRequirementId'
additionalProperties: true
ExchangeRateFees:
type: object
description: Fees associated with an exchange rate
properties:
fixed:
type: integer
format: int64
description: Fixed fee in the smallest unit of the sending currency (e.g., cents for USD)
minimum: 0
example: 100
total:
type: integer
format: int64
description: Total fees in the smallest unit of the sending currency (e.g., cents for USD). This value may change depending on the sending amount used; if no sending amount is specified, it falls back to the default.
minimum: 0
example: 100
Error401:
type: object
required:
- reason
- code
properties:
code:
type: string
description: '| Error Code | Description |
|------------|-------------|
| UNAUTHORIZED | Issue with API credentials |
| INVALID_SIGNATURE | Signature header is invalid |
| WALLET_SIGNATURE_MISSING | The `Grid-Wallet-Signature` header is required for this Embedded Wallet action but was not supplied |
| WALLET_SIGNATURE_MALFORMED | The `Grid-Wallet-Signature` header could not be parsed (bad encoding, structure, or fields) |
| WALLET_SIGNATURE_BODY_MISMATCH | The `Grid-Wallet-Signature` was computed over a different request body than the one received |
| WALLET_SIGNATURE_INVALID | The `Grid-Wallet-Signature` failed cryptographic verification against the registered credential |
| REQUEST_ID_MISSING | The `Request-Id` header is required on the signed retry but was not supplied (paired with `Grid-Wallet-Signature`) |
'
enum:
- UNAUTHORIZED
- INVALID_SIGNATURE
- WALLET_SIGNATURE_MISSING
- WALLET_SIGNATURE_MALFORMED
- WALLET_SIGNATURE_BODY_MISMATCH
- WALLET_SIGNATURE_INVALID
- REQUEST_ID_MISSING
reason:
type: string
description: Error message
details:
type: object
description: Additional error details
additionalProperties: true
Currency:
type: object
properties:
code:
type: string
description: Three-letter currency code (ISO 4217) for fiat currencies. Some cryptocurrencies may use their own ticker symbols (e.g. "BTC" for Bitcoin, "USDC" for USDC, etc.)
example: USD
name:
type: string
description: Full name of the currency
example: United States Dollar
symbol:
type: string
description: Symbol of the currency
example: $
decimals:
type: integer
description: Number of decimal places for the currency
minimum: 0
example: 2
FieldConstraint:
type: object
description: Machine-readable validator hint accompanying a 400 `INVALID_INPUT` error. Consumers use it to drive form UI (input types, dropdowns, masking, length limits) and to pre-validate the field client-side before re-submitting. Fields are additive.
properties:
format:
type: string
description: Named format the value must satisfy — HTML5 input type names (`email`, `tel`, `url`, `date`, ...) or semantic slugs (`iso3166-1-alpha-2`, `bcp47-language-tag`, `us-ssn`, `e.164`).
example: email
pattern:
type: string
description: Regular expression the value must match (JavaScript-flavor).
example: ^\d{5}(-\d{4})?$
enum:
type: array
items:
type: string
description: Allowed values when the field is drawn from a fixed set.
example:
- SSN
- ITIN
- NON_US_TAX_ID
minLength:
type: integer
description: Minimum length in characters.
example: 1
maxLength:
type: integer
description: Maximum length in characters.
example: 500
securitySchemes:
BasicAuth:
type: http
scheme: basic
description: API token authentication using format `<api token id>:<api client secret>`
AgentAuth:
type: http
scheme: bearer
description: 'Bearer token authentication for agent-scoped endpoints. The token is the `accessToken` returned when redeeming a device code via `POST /agents/device-codes/redeem`. Agent credentials are user-scoped: all requests are automatically bound to the agent''s associated customer and subject to the agent''s policy.'
WebhookSignature:
type: apiKey
in: header
name: X-Grid-Signature
description: 'Secp256r1 (P-256) asymmetric signature of the webhook payload, which can be used to verify that the webhook was sent by Grid.
To verify the signature:
1. Get the Grid public key provided to you during integration
2. Decode the base64 signature from the header
3. Create a SHA-256 hash of the request body
4. Verify the signature using the public key and the hash
If the signature verification succeeds, the webhook is authentic. If not, it should be rejected.
'
x-provenance:
method: harvested
publisher: Lightspark
source: https://docs.lightspark.com/openapi.yaml
note: split by refine-openapis from the provider's own published document, verified by fetch (openapi/_original/*.fetch.json);
stamped by stamp-openapi-provenance.py (roadmap#793)