Some payments require supporting documentation before they can continue. When a payment enters REQUIRES_REVIEW, your integration should show the user or operator what is needed, attach the document, and wait for review resolution events.
Note If a customer already has an approved document on record, future payments from that customer can bypass the review gate.
01 Receive event `payment.requiresReview` tells your system the payment is blocked.
02 Collect document Ask for the specific document type needed by the review.
03 Attach document Register the uploaded file against the payment.
04 Wait for decision Mirror approved or rejected events in your product.
Request HTTP curl JavaScript Python Go Rust
POST /sandbox/payments/{PAYMENT_ID}/documents HTTP / 1.1
Host: api.conomyhq.com
x-api-key: {YOUR_API_KEY}
Authorization: Bearer {ACCESS_TOKEN}
conomyhq-api-version: 24-04-2025
User-Agent: MyApp/1.0
Content-Type: application/json
Accept: application/json
{
" type " : " SOURCE_OF_FUNDS " ,
" url " : " https://documents.yourapp.com/payments/payment-1001/source-of-funds.pdf " ,
" metadata " : {
" fileName " : " source-of-funds.pdf " ,
" uploadedBy " : " operator@example.com "
}
} curl -X POST ' https://api.conomyhq.com/sandbox/payments/{PAYMENT_ID}/documents ' \
-H ' x-api-key: {YOUR_API_KEY} ' \
-H ' Authorization: Bearer {ACCESS_TOKEN} ' \
-H ' conomyhq-api-version: 24-04-2025 ' \
-H ' User-Agent: MyApp/1.0 ' \
-H ' Content-Type: application/json ' \
-H ' Accept: application/json ' \
-d ' {
"type": "SOURCE_OF_FUNDS",
"url": "https://documents.yourapp.com/payments/payment-1001/source-of-funds.pdf",
"metadata": {
"fileName": "source-of-funds.pdf",
"uploadedBy": "operator@example.com"
}
} ' const response = await fetch ( ' https://api.conomyhq.com/sandbox/payments/{PAYMENT_ID}/documents ' , {
method : ' POST ' ,
headers : {
' x-api-key ' : ' {YOUR_API_KEY} ' ,
' Authorization ' : ' Bearer {ACCESS_TOKEN} ' ,
' conomyhq-api-version ' : ' 24-04-2025 ' ,
' User-Agent ' : ' MyApp/1.0 ' ,
' Content-Type ' : ' application/json ' ,
' Accept ' : ' application/json ' ,
},
body : JSON . stringify ({
" type " : " SOURCE_OF_FUNDS " ,
" url " : " https://documents.yourapp.com/payments/payment-1001/source-of-funds.pdf " ,
" metadata " : {
" fileName " : " source-of-funds.pdf " ,
" uploadedBy " : " operator@example.com "
}
}),
});
const data = await response . json (); import requests
payload = {
" type " : " SOURCE_OF_FUNDS " ,
" url " : " https://documents.yourapp.com/payments/payment-1001/source-of-funds.pdf " ,
" metadata " : {
" fileName " : " source-of-funds.pdf " ,
" uploadedBy " : " operator@example.com "
}
}
response = requests . post (
' https://api.conomyhq.com/sandbox/payments/ {PAYMENT_ID} /documents ' ,
headers ={
' x-api-key ' : ' {YOUR_API_KEY} ' ,
' Authorization ' : ' Bearer {ACCESS_TOKEN} ' ,
' conomyhq-api-version ' : ' 24-04-2025 ' ,
' User-Agent ' : ' MyApp/1.0 ' ,
' Content-Type ' : ' application/json ' ,
' Accept ' : ' application/json ' ,
},
json = payload ,
)
data = response . json () package main
import (
" bytes "
" net/http "
)
func main () {
payload := [] byte ( ` {
"type": "SOURCE_OF_FUNDS",
"url": "https://documents.yourapp.com/payments/payment-1001/source-of-funds.pdf",
"metadata": {
"fileName": "source-of-funds.pdf",
"uploadedBy": "operator@example.com"
}
} ` )
body := bytes . NewReader ( payload )
req , _ := http . NewRequest ( " POST " , " https://api.conomyhq.com/sandbox/payments/{PAYMENT_ID}/documents " , body )
req . Header . Set ( " x-api-key " , " {YOUR_API_KEY} " )
req . Header . Set ( " Authorization " , " Bearer {ACCESS_TOKEN} " )
req . Header . Set ( " conomyhq-api-version " , " 24-04-2025 " )
req . Header . Set ( " User-Agent " , " MyApp/1.0 " )
req . Header . Set ( " Content-Type " , " application/json " )
req . Header . Set ( " Accept " , " application/json " )
client := & http . Client {}
resp , _ := client . Do ( req )
defer resp . Body . Close ()
} use reqwest :: Client ;
use serde_json :: json ;
#[ tokio :: main ]
async fn main () -> Result <(), Box < dyn std :: error :: Error >> {
let client = Client :: new ();
let payload = json! ({
" type " : " SOURCE_OF_FUNDS " ,
" url " : " https://documents.yourapp.com/payments/payment-1001/source-of-funds.pdf " ,
" metadata " : {
" fileName " : " source-of-funds.pdf " ,
" uploadedBy " : " operator@example.com "
}
});
let response = client
. post ( " https://api.conomyhq.com/sandbox/payments/ { PAYMENT_ID } /documents " )
. header ( " x-api-key " , " { YOUR_API_KEY } " )
. header ( " Authorization " , " Bearer { ACCESS_TOKEN } " )
. header ( " conomyhq-api-version " , " 24-04-2025 " )
. header ( " User-Agent " , " MyApp/1.0 " )
. header ( " Content-Type " , " application/json " )
. header ( " Accept " , " application/json " )
. json ( & payload )
. send ()
. await ? ;
let data : serde_json :: Value = response . json () . await ? ;
Ok (())
} {
" id " : " <DOCUMENT_ID> " ,
" paymentId " : " <PAYMENT_ID> " ,
" type " : " SOURCE_OF_FUNDS " ,
" status " : " UPLOADED "
}
Request HTTP curl JavaScript Python Go Rust
GET /sandbox/payments/{PAYMENT_ID} HTTP / 1.1
Host: api.conomyhq.com
x-api-key: {YOUR_API_KEY}
Authorization: Bearer {ACCESS_TOKEN}
conomyhq-api-version: 24-04-2025
User-Agent: MyApp/1.0
Accept: application/json curl -X GET ' https://api.conomyhq.com/sandbox/payments/{PAYMENT_ID} ' \
-H ' x-api-key: {YOUR_API_KEY} ' \
-H ' Authorization: Bearer {ACCESS_TOKEN} ' \
-H ' conomyhq-api-version: 24-04-2025 ' \
-H ' User-Agent: MyApp/1.0 ' \
-H ' Accept: application/json ' const response = await fetch ( ' https://api.conomyhq.com/sandbox/payments/{PAYMENT_ID} ' , {
method : ' GET ' ,
headers : {
' x-api-key ' : ' {YOUR_API_KEY} ' ,
' Authorization ' : ' Bearer {ACCESS_TOKEN} ' ,
' conomyhq-api-version ' : ' 24-04-2025 ' ,
' User-Agent ' : ' MyApp/1.0 ' ,
' Accept ' : ' application/json ' ,
},
});
const data = await response . json (); import requests
response = requests . get (
' https://api.conomyhq.com/sandbox/payments/ {PAYMENT_ID} ' ,
headers ={
' x-api-key ' : ' {YOUR_API_KEY} ' ,
' Authorization ' : ' Bearer {ACCESS_TOKEN} ' ,
' conomyhq-api-version ' : ' 24-04-2025 ' ,
' User-Agent ' : ' MyApp/1.0 ' ,
' Accept ' : ' application/json ' ,
},
)
data = response . json () package main
import (
" net/http "
)
func main () {
req , _ := http . NewRequest ( " GET " , " https://api.conomyhq.com/sandbox/payments/{PAYMENT_ID} " , nil )
req . Header . Set ( " x-api-key " , " {YOUR_API_KEY} " )
req . Header . Set ( " Authorization " , " Bearer {ACCESS_TOKEN} " )
req . Header . Set ( " conomyhq-api-version " , " 24-04-2025 " )
req . Header . Set ( " User-Agent " , " MyApp/1.0 " )
req . Header . Set ( " Accept " , " application/json " )
client := & http . Client {}
resp , _ := client . Do ( req )
defer resp . Body . Close ()
} use reqwest :: Client ;
#[ tokio :: main ]
async fn main () -> Result <(), Box < dyn std :: error :: Error >> {
let client = Client :: new ();
let response = client
. get ( " https://api.conomyhq.com/sandbox/payments/ { PAYMENT_ID } " )
. header ( " x-api-key " , " { YOUR_API_KEY } " )
. header ( " Authorization " , " Bearer { ACCESS_TOKEN } " )
. header ( " conomyhq-api-version " , " 24-04-2025 " )
. header ( " User-Agent " , " MyApp/1.0 " )
. header ( " Accept " , " application/json " )
. send ()
. await ? ;
let data : serde_json :: Value = response . json () . await ? ;
Ok (())
} {
" id " : " <PAYMENT_ID> " ,
" status " : " REQUIRES_REVIEW " ,
" documentationStatus " : " UPLOADED " ,
" reviewReason " : " SOURCE_OF_FUNDS_REQUIRED "
}
Listen for payment.reviewApproved and payment.reviewRejected. Approved payments resume from the point where they were blocked. Rejected payments transition to FAILED, and refund handling may apply when funds were already received.