After creating an intent, check if compliance is required. If onboardingUrl is present in the response, you need to show the compliance iframe to the user.
Decision Tree
Auto-Complete Scenarios
The intent may skip compliance (no iframe needed) when:
Returning Customer — User completed compliance for a previous intent with the same provider
KYC Sharing — User authenticated via external auth and their Gnosispay KYC is shared
When auto-completed, the response has:
onboardingUrl: null
transaction object present
intent.status is COMPLIANCE_APPROVED or later
Iframe Integration
Embedding the Iframe
< iframe
id = "gnosis-ramp-onboarding"
src = "${onboardingUrl}"
style = "width: 100%; height: 600px; border: none;"
allow = "camera"
></ iframe >
The allow="camera" attribute is required for KYC document verification that may require camera access.
Listening for Events
The iframe communicates completion via postMessage:
window . addEventListener ( 'message' , ( event ) => {
// Verify origin
if ( ! event . origin . includes ( 'ramp.gnosis.io' )) return ;
const { type , payload } = event . data ;
switch ( type ) {
case 'INTENT_COMPLETED' :
// Compliance finished successfully
console . log ( 'Intent completed:' , payload . intentId );
removeIframe ();
// Proceed to execute transaction or monitor
break ;
case 'INTENT_DISMISSED' :
// User closed or cancelled
console . log ( 'User dismissed onboarding' );
removeIframe ();
// Handle cancellation
break ;
}
});
function removeIframe () {
const iframe = document . getElementById ( 'gnosis-ramp-onboarding' );
iframe ?. remove ();
}
Event Payloads
INTENT_COMPLETED
{
"type" : "INTENT_COMPLETED" ,
"payload" : {
"intentId" : "int_abc123def456"
}
}
INTENT_DISMISSED
{
"type" : "INTENT_DISMISSED" ,
"payload" : {
"intentId" : "int_abc123def456"
}
}
Complete Example
async function handleCompliance ( intentResponse ) {
const { intent , onboardingUrl , transaction } = intentResponse ;
// Check if auto-completed
if ( ! onboardingUrl && transaction ) {
console . log ( 'Auto-completed! Monitoring transaction...' );
return monitorTransaction ( intent . id );
}
// Check if no compliance needed
if ( ! onboardingUrl ) {
console . log ( 'Waiting for compliance...' );
return pollIntentStatus ( intent . id );
}
// Show iframe
return new Promise (( resolve , reject ) => {
const iframe = document . createElement ( 'iframe' );
iframe . id = 'gnosis-ramp-onboarding' ;
iframe . src = onboardingUrl ;
iframe . style . cssText = 'width:100%;height:600px;border:none;' ;
iframe . allow = 'camera' ;
document . getElementById ( 'onboarding-container' ). appendChild ( iframe );
const handler = ( event ) => {
if ( ! event . origin . includes ( 'ramp.gnosis.io' )) return ;
const { type , payload } = event . data ;
if ( type === 'INTENT_COMPLETED' ) {
window . removeEventListener ( 'message' , handler );
iframe . remove ();
resolve ( payload . intentId );
}
if ( type === 'INTENT_DISMISSED' ) {
window . removeEventListener ( 'message' , handler );
iframe . remove ();
reject ( new Error ( 'User dismissed onboarding' ));
}
};
window . addEventListener ( 'message' , handler );
});
}
Polling Fallback
If postMessage events aren’t received (e.g., browser restrictions), poll the intent status:
async function pollIntentStatus ( intentId ) {
const response = await fetch (
`https://api.ramp.gnosis.io/v1/intent/ ${ intentId } ` ,
{ headers: { 'Authorization' : `Bearer ${ accessToken } ` } }
);
const { intent } = await response . json ();
if ( intent . status === 'COMPLIANCE_APPROVED' ) {
return intent ;
}
if ( intent . status === 'COMPLIANCE_FAILED' ) {
throw new Error ( intent . failureReason );
}
// Still in progress - poll again
await new Promise ( r => setTimeout ( r , 2000 ));
return pollIntentStatus ( intentId );
}
Next Steps
Execute Transaction Trigger the money movement.
Intent Overview Understand all intent states.