curl --request POST \
--url https://api-sandbox.finogates.com/v1/platform/card-processing \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: multipart/form-data' \
--form 'payload=<string>' \
--form voided_check='@example-file' \
--form bank_statements='@example-file' \
--form 'processing_statements=<string>' \
--form processing_statements.0='@example-file'import requests
url = "https://api-sandbox.finogates.com/v1/platform/card-processing"
files = {
"voided_check": ("example-file", open("example-file", "rb")),
"bank_statements": ("example-file", open("example-file", "rb")),
"processing_statements.0": ("example-file", open("example-file", "rb"))
}
payload = {
"payload": "<string>",
"processing_statements": "<string>"
}
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, data=payload, files=files, headers=headers)
print(response.text)const form = new FormData();
form.append('payload', '<string>');
form.append('voided_check', '<string>');
form.append('bank_statements', '<string>');
form.append('processing_statements', '<string>');
form.append('processing_statements.0', '{
"fileName": "example-file"
}');
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
options.body = form;
fetch('https://api-sandbox.finogates.com/v1/platform/card-processing', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api-sandbox.finogates.com/v1/platform/card-processing",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"payload\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"voided_check\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"bank_statements\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"processing_statements\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"processing_statements.0\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: multipart/form-data"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api-sandbox.finogates.com/v1/platform/card-processing"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"payload\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"voided_check\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"bank_statements\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"processing_statements\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"processing_statements.0\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api-sandbox.finogates.com/v1/platform/card-processing")
.header("Authorization", "Bearer <token>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"payload\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"voided_check\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"bank_statements\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"processing_statements\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"processing_statements.0\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-sandbox.finogates.com/v1/platform/card-processing")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"payload\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"voided_check\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"bank_statements\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"processing_statements\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"processing_statements.0\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"status_code": 201,
"data": {
"user_id": "228e4b03-6831-4b63-ad8e-2250d01f6d64",
"kyb_id": "69b336da-331c-4ddf-8ac5-0a0557c7f279",
"card_acquiring_id": "07f78e86-b3c6-4761-84ae-22176ca015c1"
},
"query_generated_time": 1712847600000
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>"
}
]
}Apply for Card Processing
Apply for card processing for one of your users, so that user can accept card payments.
Send this as multipart/form-data: the payload field carries the details as JSON text, and the documents are separate file parts.
payload fields:
user_id— the user this application is for.kyb_id— the business verification to apply against.merchant_info.average_ticket— average transaction amount.merchant_info.monthly_volume— expected monthly processing volume.merchant_info.max_ticket— maximum expected transaction amount. Cannot be lower thanaverage_ticket.merchant_info.website— normally omit it. It defaults to the website on the business verification named bykyb_id. Send it only when that verification carries no website — in that case it is required, and leaving it out is rejected.
Amounts are plain currency amounts — "50.00", not 5000 — with at most two decimal places.
File parts:
voided_check— required.bank_statements— required. Last 3 months, one file.processing_statements— optional; send it only if the business already processes cards elsewhere.
Each file must be a PNG, JPG, JPEG or PDF, at most 10 MB, and no two files may be identical.
The application is created awaiting review. The merchant cannot accept card payments until it is approved.
The response is three ids — user_id, kyb_id and card_acquiring_id — the same shape POST /v1/platform/merchant-onboarding returns. Keep card_acquiring_id: it is the key for reading the application and for matching the webhooks below.
Webhooks
You are told the outcome by webhook — subscribe rather than poll.
card_acquiring.application.status_changed — the application moved. This is the one to act on.
{
"card_acquiring_id": "07f78e86-b3c6-4761-84ae-22176ca015c1",
"status": "approved"
}
status is one of:
processing— under review. No action needed.approved— the merchant can now accept card payments.rejected— turned down. The event also carries arejection_reasonstring when one was recorded.
card_acquiring.application.updated — the application’s details changed, without its status moving.
{
"card_acquiring_id": "07f78e86-b3c6-4761-84ae-22176ca015c1",
"updated_fields": { "monthly_volume_minor": 3000000 }
}
updated_fields holds only what changed. Use it to keep your own copy in step; nothing here means the application was approved or rejected.
Both events arrive in the standard webhook envelope, signed with your endpoint secret. Deliveries are retried, so treat them as at-least-once and key on card_acquiring_id.
curl --request POST \
--url https://api-sandbox.finogates.com/v1/platform/card-processing \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: multipart/form-data' \
--form 'payload=<string>' \
--form voided_check='@example-file' \
--form bank_statements='@example-file' \
--form 'processing_statements=<string>' \
--form processing_statements.0='@example-file'import requests
url = "https://api-sandbox.finogates.com/v1/platform/card-processing"
files = {
"voided_check": ("example-file", open("example-file", "rb")),
"bank_statements": ("example-file", open("example-file", "rb")),
"processing_statements.0": ("example-file", open("example-file", "rb"))
}
payload = {
"payload": "<string>",
"processing_statements": "<string>"
}
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, data=payload, files=files, headers=headers)
print(response.text)const form = new FormData();
form.append('payload', '<string>');
form.append('voided_check', '<string>');
form.append('bank_statements', '<string>');
form.append('processing_statements', '<string>');
form.append('processing_statements.0', '{
"fileName": "example-file"
}');
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
options.body = form;
fetch('https://api-sandbox.finogates.com/v1/platform/card-processing', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api-sandbox.finogates.com/v1/platform/card-processing",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"payload\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"voided_check\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"bank_statements\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"processing_statements\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"processing_statements.0\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: multipart/form-data"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api-sandbox.finogates.com/v1/platform/card-processing"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"payload\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"voided_check\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"bank_statements\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"processing_statements\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"processing_statements.0\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api-sandbox.finogates.com/v1/platform/card-processing")
.header("Authorization", "Bearer <token>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"payload\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"voided_check\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"bank_statements\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"processing_statements\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"processing_statements.0\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-sandbox.finogates.com/v1/platform/card-processing")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"payload\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"voided_check\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"bank_statements\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"processing_statements\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"processing_statements.0\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"status_code": 201,
"data": {
"user_id": "228e4b03-6831-4b63-ad8e-2250d01f6d64",
"kyb_id": "69b336da-331c-4ddf-8ac5-0a0557c7f279",
"card_acquiring_id": "07f78e86-b3c6-4761-84ae-22176ca015c1"
},
"query_generated_time": 1712847600000
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>"
}
]
}Authorizations
The access token received from the authorization server in the OAuth 2.0 flow.
Body
The application details, sent as JSON text. See the endpoint description for the object's shape.
Voided check for the account settlements should land in.
Last 3 months of business bank statements, one file.
Last 3 months of merchant processing statements. Optional — it only applies when the business already processes with another provider.

