Frictionless Sign-up Flow
In the frictionless flow, your existing customers are automatically signed up to Coinify in the background — no Coinify sign-up screen, no password creation, no email verification code. The transition from your platform to the Trade Widget is invisible to the user.
Before diving in:The complete frictionless flow for both individual and corporate customers is visually mapped here — look for the Frictionless Flow sections in the diagram.
The setup involves three steps: generating a key pair, creating a signed JWT token, and passing it in the sign-up request.
Please find the steps for setting up the Frictionless Sign-up flow below:
1. Generate Private/Public key pair
The following code samples contain file names which you can adjust according to your needs. Of course, you are welcome to use your own code for the same use case.
You'll use RSA-SHA256 asymmetric cryptography to sign sign-up requests. Generate your key pair using OpenSSL:
# Generate a 2048-bit RSA private key
openssl genrsa -out key.pem 2048
# Extract the public key
openssl rsa -in key.pem -outform PEM -pubout -out public.pem
Get thePublic keyand deliver it to Conify via your dedicated channel of communication. Once the Public key is set on the Coinify side, you can start the Frictionless Sign-up process by following the next steps.
2. Generate the JWT token
The JWT token is passed in the trustedEmailValidation field on the customer Sign-up API request. It confirms that the request is coming from your trusted system and that customer with the correct email is being signed up.
Below, you can find a couple of code examples on how to generate the JWT token. In this example, the only thing you need to make sure is that you are passing the correct email of the customer you want to sign up and that you are using the correct path to the file with the Private key.
const base64 = require('base64url'); // Import the 'base64url' library to handle Base64Url encoding
const crypto = require('crypto'); // Import the 'crypto' module to perform cryptographic operations
const signatureFunction = crypto.createSign('RSA-SHA256'); // Create a cryptographic signature object using the RSA-SHA256 algorithm
const fs = require('fs'); // Import the 'fs' module to read the private key from a file
// Define the header object for the JWT, specifying the algorithm and token type
const headerObj = {
alg: 'RS256',
typ: 'JWT'
};
// Define the payload object with the email of the customer that's being signed-up
const payloadObj = {
email: '[email protected]'
//exp: 1467331200 // Optional: Use the "exp" parameter IF you want the JWT token to expire at a specific time. UNIX Timestamp format.
};
const headerObjString = JSON.stringify(headerObj); // Convert the header object to a JSON string
const payloadObjString = JSON.stringify(payloadObj); // Convert the payload object to a JSON string
// Encode the header JSON as Base64Url
const base64UrlHeader = base64(headerObjString);
// Encode the payload JSON as Base64Url
const base64UrlPayload = base64(payloadObjString);
// Concatenate the Base64Url-encoded header and payload
signatureFunction.write(base64UrlHeader + '.' + base64UrlPayload);
signatureFunction.end();
const PRIV_KEY = fs.readFileSync(__dirname + '/id_rsa_priv.pem', 'utf8');// Read the Private key from a file (in this example file name is 'id_rsa_priv.pem')
const signatureBase64 = signatureFunction.sign(PRIV_KEY, 'base64');// Sign the concatenated data using the private key and get a Base64 signature
const signatureBase64Url = base64.fromBase64(signatureBase64); // Convert the Base64 signature to Base64Url encoding
console.log(base64UrlHeader + '.' + base64UrlPayload + '.' + signatureBase64Url);// Combine the Base64Url-encoded header, payload, and signature to form the JWT
import jwt # Import the 'jwt' library for JSON Web Token operations
import json # Import the 'json' library for JSON data handling
# Define the header with the token type (JWT) and the signing algorithm (RS256 in this case)
header = {
"typ": "JWT",
"alg": "RS256"
}
# Define the payload with the email of the customer that's being signed up
payload = {
"email": "[email protected]"
# "exp": 1467331200 #Optional: Use the "exp" parameter IF you want the JWT token to expire at a specific time. UNIX Timestamp format.
}
# Load your RSA private key
# Replace 'your_private_key.pem' with your actual private key file
with open('id_rsa_priv.pem', 'rb') as key_file:
private_key = key_file.read()
# Generate the JWT token by encoding the payload with the private key and algorithm
token = jwt.encode(payload, private_key, algorithm='RS256', headers=header)
# Print the JWT token after decoding it from bytes to a UTF-8 string
print(token.decode('utf-8'))
As visible in the code examples above, the payload for generating the JWT token is the email address of the customer signing-up:
//Example JWT payload for email address [email protected]
{
"email": "[email protected]"
}
The output of this code is passed to thetrustedEmailValidationTokenin the Sign-up request.
Alternatively, if you want to reset or create a newoffline_tokenfor an existing end-user, the output of the above code is used in theAuthorizationheader of the Reset Offline Token request.
TestingUse the Online JWT tool to verify your token's header, payload, and signature during development.
3. Frictionless Sign-up API request
Important:You must ensure that the address
country(andstatewhere applicable) are provided from the end-user's direct input, in case you are not already collecting this data point on your end.
Pass the generated JWT in the trustedEmailValidationToken field, along with generateOfflineToken: true to receive an offline token for authenticating the user going forward.
curl --location 'https://app-api.sandbox.coinify.com/signup/trader' \
--header 'Content-Type: application/json' \
--data-raw '{
"email": "[email protected]",
"partnerId":"your-partner-id-here",
"accountType":"individual"
"profile": {
"address": {
"country": "DK"
}
},
"trustedEmailValidationToken": "<your-generated-jwt>"
"generateOfflineToken": true
}'
country(andstatefor US users) must come from the end-user's direct input — never pre-filled or inferred on their behalf.
A successful response returns a trader object and an offlineToken. Store the offlineToken securely — it is used to authenticate this user silently on all future sessions without them needing to provide credentials.
Resetting an offline token: If you need to generate a newofflineTokenfor an existing user, use the same JWT generation from Step 2 in theAuthorizationheader of the Reset Offline Token → endpoint.
For the full endpoint spec, see Frictionless Email Verification →.
Next Steps
Frictionless Sign-in → — use the offlineToken to authenticate the user and load the Trade Widget
Updated 3 days ago
