After discovering supported currency pairs, the next step is fetching the field requirements for the intent’s source and destination accounts. Gnosis Ramp exposes dynamic JSON Schemas so you can render or validate account forms without reverse-engineering provider requirements.
Query Parameters
Call GET /intent/requirements with these parameters:
| Parameter | Required | Description |
|---|
srcCurrencyCode | Yes | Source currency code (e.g., USD, EUR, BRL) |
destCurrencyCode | Yes | Destination currency code (e.g., USDC_GNO, USDC_ETH) |
rail | No | Filter by payment rail (e.g., ACH, PIX, WIRE) |
providerId | No | Filter by provider ID (from quote response) |
The optional rail and providerId filters simplify the schema response. Use them after getting a quote to fetch requirements specific to the user’s selection.
Example Request
curl "https://api.ramp.gnosis.io/v1/intent/requirements?srcCurrencyCode=USD&destCurrencyCode=USDC_GNO" \
-u "${CLIENT_ID}:${CLIENT_SECRET}"
This endpoint uses Basic Auth (project credentials), not a customer JWT.
Example Response
{
"src": {
"currencyCode": "USD",
"schema": {
"type": "object",
"required": ["countryCode", "currency", "rail"],
"properties": {
"countryCode": { "const": "US" },
"currency": { "const": "USD" },
"rail": {
"type": "string",
"enum": ["ACH", "WIRE"]
},
"providerId": {
"type": "string",
"oneOf": [
{ "const": "bridge", "title": "Bridge" }
]
}
},
"additionalProperties": true
}
},
"dest": {
"currencyCode": "USDC_GNO",
"schema": {
"type": "object",
"required": ["address", "currency"],
"properties": {
"address": {
"pattern": "^0x[a-fA-F0-9]{40}$",
"description": "Wallet address"
},
"currency": {
"const": "USDC_GNO"
}
}
}
}
}
The response contains two requirement entries:
src — Contains currencyCode and schema for the source account
dest — Contains currencyCode and schema for the destination account
Each schema is a JSON Schema that defines the fields needed for that account type.
Source schemas are minimal. The source schema returns only routing fields (countryCode, currency, rail). Account identifiers and beneficiary details are not required for source accounts — only the destination account requires full details. The providerId field is included for form rendering but is passed at the top level of the intent, not inside src.details.
OFFRAMP Example
For OFFRAMP (crypto → fiat), swap the source and destination:
curl "https://api.ramp.gnosis.io/v1/intent/requirements?srcCurrencyCode=USDC_GNO&destCurrencyCode=USD" \
-u "${CLIENT_ID}:${CLIENT_SECRET}"
Response:
{
"src": {
"currencyCode": "USDC_GNO",
"schema": {
"type": "object",
"required": ["address", "currency"],
"properties": {
"address": {
"pattern": "^0x[a-fA-F0-9]{40}$",
"description": "Wallet address"
},
"currency": {
"const": "USDC_GNO"
}
}
}
},
"dest": {
"currencyCode": "USD",
"schema": {
"type": "object",
"required": ["countryCode", "currency", "rail"],
"properties": {
"countryCode": { "const": "US" },
"currency": { "const": "USD" },
"rail": {
"type": "string",
"enum": ["ACH", "WIRE"]
}
},
"additionalProperties": true
}
}
}
For OFFRAMP, the source schema requires wallet details and the destination schema requires bank routing fields.
How Schemas Connect to Provider Selection
The schemas returned here reflect the combined capabilities of all active providers for your project. Key points:
- Rail choice — the
rail field (e.g., ACH, WIRE, PIX) determines which set of account fields are required. Different rails have different schema shapes.
- Provider-specific fields — some providers require additional metadata. The schema’s
dependencies section may include oneOf branches per provider with extra fields.
- Downstream filtering — the rail and metadata you submit when creating an intent are used by Gnosis Ramp to filter which providers can handle the payment. Choosing
ACH here means only providers supporting ACH will be eligible candidates.
Why Provider Choice Affects Compliance Requirements
Different providers have different compliance configurations. For example:
| Provider | Compliance Flow | User Experience |
|---|
| Provider A (with SumSub integration) | SumSub token share → onboarding | User completes SumSub KYC widget |
| Provider B (own KYC) | Provider-native KYC → onboarding | User completes provider’s own KYC flow |
This is why providerId matters beyond just routing — it determines the compliance steps your users will see.
Using Schemas in Intent Creation
The schemas define what to pass in the details field when creating an intent. For example, if the schema requires countryCode and rail, your intent request would include:
{
"src": {
"currencyCode": "USD",
"details": {
"countryCode": "US",
"rail": "ACH"
}
},
"dest": {
"currencyCode": "USDC_GNO",
"details": {
"address": "0x742d35Cc6634C0532925a3b84cF2f7c7f3B2f5f8"
}
},
"srcAmount": "100.50",
"autoExecute": true,
"providerId": "bridge"
}
The providerId is passed at the top level of the intent request, not inside src.details. It specifies which provider to use for the transaction. The values match the lowercase IDs returned by GET /providers and the providerId options in the requirements schema.
See the Creating an Intent guide for complete intent creation details.
Quote-First Flow with Filtering
The recommended integration pattern is quote first → filtered requirements. After a user selects a quote, pass the rail and providerId from that quote to get a simplified schema.
Step 1: Get Quotes
curl "https://api.ramp.gnosis.io/v1/intent/quote?srcCurrencyCode=USD&destCurrencyCode=USDC_GNO&srcAmount=100&countryCode=US" \
-u "${CLIENT_ID}:${CLIENT_SECRET}"
Response:
{
"quotes": [
{
"providerId": "bridge",
"rail": "ACH",
"destAmount": "98.50",
"exchangeRate": "0.9850",
"hasIndicativePrice": true,
"fees": { "totalFee": "1.50", "currencyCode": "USD" }
},
{
"providerId": "bridge",
"rail": "WIRE",
"destAmount": "97.00",
"exchangeRate": "0.9700",
"hasIndicativePrice": true,
"fees": { "totalFee": "3.00", "currencyCode": "USD" }
}
]
}
Step 2: User Selects a Quote
User picks: Bridge via ACH (providerId: "bridge", rail: "ACH")
Step 3: Fetch Filtered Requirements
curl "https://api.ramp.gnosis.io/v1/intent/requirements?srcCurrencyCode=USD&destCurrencyCode=USDC_GNO&rail=ACH&providerId=bridge" \
-u "${CLIENT_ID}:${CLIENT_SECRET}"
Filtered Response (Flat Schema)
{
"src": {
"currencyCode": "USD",
"schema": {
"type": "object",
"required": ["countryCode", "currency", "rail"],
"properties": {
"countryCode": { "const": "US" },
"currency": { "const": "USD" },
"rail": { "const": "ACH" },
"providerId": { "const": "bridge", "title": "Bridge" }
},
"additionalProperties": true
}
},
"dest": {
"currencyCode": "USDC_GNO",
"schema": {
"type": "object",
"required": ["currency", "address"],
"properties": {
"currency": { "const": "USDC_GNO" },
"address": {
"type": "string",
"pattern": "^0x[a-fA-F0-9]{40}$",
"description": "Wallet address"
}
}
}
}
}
Notice the difference: With filters, rail and providerId use const (fixed values) instead of enum or oneOf. There’s no dependencies block — the schema is flat and simple to render.
Schema Comparison: With vs Without Filters
Without Filters (Multiple Options)
When multiple rails or providers are available:
{
"src": {
"currencyCode": "USD",
"schema": {
"properties": {
"rail": {
"type": "string",
"enum": ["ACH", "WIRE"]
},
"providerId": {
"type": "string",
"oneOf": [
{ "const": "bridge", "title": "Bridge" },
{ "const": "other", "title": "Other Provider" }
]
}
},
"dependencies": {
"rail": {
"oneOf": [
{ "properties": { "rail": { "const": "ACH" } }, "required": ["routingNumber"] },
{ "properties": { "rail": { "const": "WIRE" } }, "required": ["swiftCode"] }
]
}
}
}
}
}
With Filters (Single Selection)
Same currency pair with rail=ACH&providerId=bridge:
{
"src": {
"currencyCode": "USD",
"schema": {
"properties": {
"rail": { "const": "ACH" },
"providerId": { "const": "bridge", "title": "Bridge" },
"routingNumber": { "type": "string" }
}
}
}
}
| Aspect | Without Filters | With Filters |
|---|
rail field | enum: ["ACH", "WIRE"] | const: "ACH" |
providerId field | oneOf: [...] | const: "bridge" |
dependencies block | Present (complex) | Absent |
| Form rendering | Conditional logic needed | Simple flat form |
Error Handling
Invalid filters return 400 Bad Request with descriptive messages:
| Scenario | Error Message |
|---|
| Invalid rail | Rail 'SEPA' not available for USD → USDC_GNO |
| Invalid provider | Provider not found or doesn't support USD → USDC_GNO |
| Provider doesn’t support rail | Provider doesn't support rail 'WIRE' for USD → USDC_GNO |
{
"error": "Bad Request",
"message": "Rail 'SEPA' not available for USD → USDC_GNO"
}
Best Practices
- Use filters after quotes — Once a user selects a quote, pass
rail and providerId to get a simplified schema for form rendering.
- Always fetch the schema at runtime — providers can add new rails or metadata without requiring an API change.
- Use the schemas to power both client-side validation and your own backend sanitization before creating intents.
- The currency code format follows: fiat codes like
USD, EUR, BRL and crypto codes like USDC_GNO, USDC_ETH (format: {ticker}_{blockchain}).