Sending Money with alfred
Alfred API Overview
Alfred APIs are lego blocks to build delightful payment experiences for your customers. The guides in this section will walk you through the following APIs:
Product | Description |
---|---|
Payments | One-time fiat or stablecoin transfers. Supports onramps, offramps, and crypto-to-crypto flows as well as traditional fiat-to-fiat flows. |
Virtual Accounts | Unique fiat deposit addresses issued to your customers so they can receive fiat deposits (ACH, Wire, SPEI, COELSA, PIX, NEQUI, etc.) |
Liquidation Address | Permanent on-chain address that auto-forwards incoming crypto to a fiat or crypto destination. |
OTC Trading | Access to premier pricing for high-volume trades. Available upon request. |
Before you begin integrating the Alfred's API, it's important to understand some core concepts to ensure a smooth building process.
Customers
Alfred Customers represent the individual users of our partners. KYC checks are done with the provided information and files on the user to verify that they can safely and compliantly use our services. Once the Customer KYC has been completed, you add connect the user's payment method and begin transacting.
KYC Onboarding
KYC onboarding refers to the process of collecting information about your customers necessary to enable them transact. Once submitted, the information is reviewed and their KYC status is updated. Requirements vary based on the country in which the customer resides.
Payment Methods
Payment Methods refer to the bank account of the customer, to which deposits and withdrawals will be made in the local currency.
Quotes
Quotes provide real-time exchange rates and fees for transactions.
Transactions
Alfred supports two types of transactions - onramps and offramps.
An onramp transaction represents a deposit of fiat from a user's bank account to crypto in their digital wallet.
An offramp transaction represents a withdrawal of crypto from a user's digital wallet to fiat in their bank account.
alfred supports both first-party and third-party payments for customers:
First-party payments involve moving funds on behalf of the same individual or business. Matching the information of the KYC/B that was approved in screening. — for example, a business converting USD to USDC for its own treasury. Or an individual converting their USDC into their local peso ARS for example.
Third-party payments involve sending or receiving funds on behalf of another party — such as a platform disbursing wages to a worker, or collecting payments from consumers on behalf of a merchant.
alfred allows you to:
Pay a vendor in fiat, even if the original funds are in stablecoins.
Collect fiat from a merchant and deliver stablecoins to a consumer.
Peer-to-peer (P2P) transfers between individuals are supported, subject to applicable limits.
alfred may, at its discretion, request additional information or documentation to support a third-party payment.
ON Ramp:
alfred ON Ramp allows your users to purchase digital assets with local currency in supported countries and payment methods.
OFF Ramp:
alfred OFF Ramp allows your users to sell digital assets for local currency in supported countries and payment methods. (Third party payment is executed as an offramp with additional details in order to understand who that third party is).
Our payment rails solution allows users to buy or sell digital assets in a simple, secure, and efficient way. Connect to their bank account or allow them to cash out at one of our Retail/ATM locations across LATAM.
Checkout Widget:
With our Widget, integrate a supported iFrame onto your app or web platform giving you a plug and play solution to all of our supported capabilities and geographies. Eliminate the need to build your own KYC process or checkout UI. Seamlessly offer compliant deposits and withdrawals with only a few lines of code.
KYC/KYB Compliant Services:
An API that offers a compliance as a service and user management system. This is the gateway that unlocks all of Alfred's powerful offerings ensuring a quick and seamless integration.
Example Workflow execution
Script to give visibility into an example workflow integration**_
alfred Transaction
Description
This Node.js script is used to interact with a third-party API. It performs several operations such as initiating a transaction, logging in, uploading documents, verifying the phone, and sending a transaction.
Configuration
The script uses environment variables to configure various aspects of its operation. These variables can be set in a .env file in the root directory of the project.
URL=<https://api-dev-services.alfredpay.app/api/v1>
API_KEY=your_api_key
API_SECRET=your_api_secret
COUNTRY_WITHDRAWAL=MEX
BUSINESS_TO=your_business_to
METHOD_WITHDRAWAL=BANK
TYPE=your_type
ID_CARD_FRONT_PATH=path_to_id_card_front
ID_CARD_BACK_PATH=path_to_id_card_back
SELFIE_PATH=path_to_selfie
DRIVER_DOC_FRONT_PATH=path_to_driver_doc_front
DRIVER_DOC_BACK_PATH=path_to_driver_doc_back
Functions
getHeaders(token)
Generates and returns the necessary headers for requests to the API.
makeRequest(method, url, body, token)
Makes a request to the API with the provided method, URL, body, and token.
getInitTransaction()
Initiates a transaction with the API and returns the transaction ID.
loginSofKyc(initialTransaction)
Logs in to the API using the provided initial transaction.
uploadDocument(token, docPath, docType)
Uploads a document to the API using the provided token, document path, and document type.
paymentMethod(initTransaction)
Sets the payment method using the provided initial transaction.
verificationPhone()
Verifies the phone number with the API.
submitTransaction(initTransaction, exchangeFactor)
Submits a transaction to the API using the provided initial transaction and exchange factor.
updateBankUser()
Updates the user's bank information in the API.
updateInvoice(invoice)
Updates the status of the invoice in the API. The invoice status can only be changed to 'approved'.
getInvoice(invoice)
Gets the invoice information from the API.
main()
Main function that coordinates all the above operations.
Usage
To run the script, first install the dependencies with npm install and then run the script with node script.js.
Dependencies
dotenv: To load environment variables from a .env file
axios: To make HTTP requests.
fs: To read files from the file system.
form-data: To create multipart/form-data forms.
Package.Json
Copy
{
"name": "alfred",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node index.js"
},
"dependencies": {
"dotenv": "^10.0.0",
"axios": "^0.24.0",
"form-data": "^4.0.0"
},
"devDependencies": {},
"keywords": [],
"author": "",
"license": "ISC"
}
Index.js
Copy
require('dotenv').config();
const axios = require('axios');
const fs = require('fs');
const FormData = require('form-data');
const KycDocTypes = {
idCardFront: 'idCardFront',
idCardBack: 'idCardBack',
selfie: 'selfie',
driverDocFront: 'driverDocFront',
driverDocBack: 'driverDocBack',
};
const URL = process.env.URL || 'https://api-dev-services.alfredpay.app/api/v1';
const API_KEY = process.env.API_KEY;
const API_SECRET = process.env.API_SECRET;
const COUNTRY_WITHDRAWAL = process.env.COUNTRY_WITHDRAWAL || 'ARG';
const BUSINESS_TO = process.env.BUSINESS_TO;
const METHOD_WITHDRAWAL = process.env.METHOD_WITHDRAWAL || 'BANK';
const TYPE = process.env.TYPE;
const files = {
[KycDocTypes.idCardFront]: process.env.ID_CARD_FRONT_PATH,
[KycDocTypes.idCardBack]: process.env.ID_CARD_BACK_PATH,
[KycDocTypes.selfie]: process.env.SELFIE_PATH,
[KycDocTypes.driverDocFront]: process.env.DRIVER_DOC_FRONT_PATH,
[KycDocTypes.driverDocBack]: process.env.DRIVER_DOC_BACK_PATH,
};
let token = '';
function getHeaders(token) {
return {
Authorization: Bearer ${token}
,
'Content-Type': 'application/json',
'api-key': API_KEY,
'api-secret': API_SECRET,
};
}
async function makeRequest(method, url, body, token) {
try {
const response = await axios({
method,
url,
data: body,
headers: getHeaders(token),
});
return response.data;
} catch (error) {
console.error(Failed to make request: ${error?.response?.data?.message}
);
throw error?.response?.data?.message ?? error.message;
}
}
async function getInitTransaction() {
const body = {
type: TYPE,
balance: 11,
currency: 'USDC',
user: '@JohnDoe',
chain: 'stellar',
};
const response = await makeRequest(
'POST',
${URL}/third-party-service/my-info
,
body,
token,
);
const url = response.data.url;
const urlSplit = url.split('/');
const urlParam = urlSplit[urlSplit.length - 1];
return urlParam;
}
async function loginSofKyc(initialTransaction) {
const body = {
initial_transaction: initialTransaction,
phonenumber: '+4915156889665',
email: '[email protected]',
firstname: 'John',
lastname: 'Doe',
address: 'Muinura 33(5',
country: 'MEX',
city: 'Ciudad de México',
zipcode: 11650,
birthday: '1984-07-07',
};
const response = await makeRequest(
'POST',
${URL}/third-party-service/login-sof-kyc
,
body,
token,
);
token = response.data.token;
return token;
}
async function uploadDocument(token, docPath, docType) {
try {
const url = ${URL}/third-party-service/kyc/upload-document
;
const formData = new FormData();
formData.append('doc', await fs.createReadStream(docPath), {
filename: docPath.split('/').pop(),
});
formData.append('docType', docType);
const config = {
method: 'PUT',
url: url,
headers: {
...formData.getHeaders(),
Authorization: `Bearer ${token}`,
'api-key': API_KEY,
'api-secret': API_SECRET,
},
data: formData,
};
console.log('upload document docType:', docType);
const response = await axios(config);
return response.data;
} catch (error) {
console.error(
Failed to update document: ${error?.response?.data?.message}
,
);
throw error?.response?.data?.message ?? error.message;
}
}
async function paymentMethod(initTransaction) {
const body = {
initial_transaction: initTransaction,
phonenumber: '+4915100089665',
email: '[email protected]',
fullname: 'John Doe',
address: 'Muinurax 35',
country: 'MEX',
city: 'Ciudad de México',
countrywithdraw: COUNTRY_WITHDRAWAL,
};
const response = await makeRequest(
'POST',
${URL}/third-party-service/payment-method
,
body,
token,
);
return response.data;
}
async function verificationPhone() {
const body = {
ref: userData.phoneNumber,
};
const data = await makeRequest(
'POST',
${URL_CORE}/transacction/phone/withdrawl
,
body,
token,
);
return data;
}
async function submitTransaction(initTransaction, exchangeFactor) {
const body = {
amount: 10,
withdrawlPhone: '+4915156889665',
businessInitTx: initTransaction,
BusinessTo: BUSINESS_TO,
exchangeId: exchangeFactor,
typeProcesor: METHOD_WITHDRAWAL,
};
const response = await makeRequest(
'POST',
${URL}/third-party-service/submit-transaction
,
body,
token,
);
return response.data;
}
async function updateBankUser() {
const body = {
id: '323',
bankName: 'Banco Ciudad',
bankNumber: '020000110000520139425',
bankAccountOwner: 'John',
countryCode: 'ARG',
DNI: '41586849',
typeId: 'NONE',
};
const response = await makeRequest(
'POST',
${URL}/third-party-service/update-bank
,
body,
token,
);
return response.data;
}
async function updateInvoice(invoice) {
const body = {
status: 'approved',
};
// change the status of the invoice only to 'approve'
const response = await makeRequest(
'PUT',
${URL}/third-party-service/invoice/${invoice}
,
body,
token,
);
return response.data;
}
async function getInvoice(invoice) {
const response = await makeRequest(
'GET',
${URL}/third-party-service/invoice/${invoice}
,
);
return response.data;
}
async function main() {
try {
const initTransaction = await getInitTransaction();
console.log('Init Transaction:', initTransaction);
const loginSofKycResult = await loginSofKyc(initTransaction);
console.log('Login Sof Kyc:', loginSofKycResult);
const paymentMethodResult = await paymentMethod(initTransaction);
console.log('Payment Method Result:', paymentMethodResult);
const uploadDocuments = Object.keys(files).map((docType) =>
uploadDocument(token, files[docType], docType),
);
await Promise.all(uploadDocuments);
if (METHOD_WITHDRAWAL === 'ATM') {
await verificationPhone(initTransaction);
}
const submitTransactionResult = await submitTransaction(
initTransaction,
paymentMethodResult?.exchangeFactor?.id,
);
console.log('Submit Transaction Result:', submitTransactionResult);
const updateBank = await updateBankUser();
console.log('updateBank', updateBank);
const updateInvoiceUser = await updateInvoice(
submitTransactionResult?.invoice?.id,
);
console.log('updateInvoiceUser', updateInvoiceUser);
const invoice = await getInvoice(submitTransactionResult?.invoice?.id);
console.log('Invoice', invoice);
} catch (error) {
console.error('Error:', error);
throw error;
}
}
main();
Updated 28 days ago