Upload files to Coinflow storage

Overview

This endpoint generates a secure, temporary upload URL that allows merchants to upload files directly to Coinflow’s storage. The presigned URL is valid for 1 hour.

Endpoint

POST /api/merchant/files/upload-url

Accepted File Types

File TypeContent Type
PDFapplication/pdf
PNGimage/png
JPEGimage/jpeg
GIFimage/gif
ZIPapplication/zip
Word (.docx)application/vnd.openxmlformats-officedocument.wordprocessingml.document
Excel (.xlsx)application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
CSVtext/csv

Request Body

FieldTypeRequiredDescription
fileNamestringYesName of the file to upload (e.g., "evidence.pdf")
contentTypestringYesMIME type of the file (e.g., "application/pdf")

Response

FieldTypeDescription
uploadUrlstringPresigned S3-style URL for uploading the file (expires in 1 hour)
fileKeystringIdentifier stored as: merchants/{merchantId}/{uuid}.{extension}

Usage Flow

Step 1: Request Upload URL

$curl --request POST \
> --url https://api-sandbox.coinflow.cash/api/merchant/files/upload-url \
> --header 'Authorization: YOUR_MERCHANT_API_KEY' \
> --header 'Content-Type: application/json' \
> --data '{
> "fileName": "chargeback-evidence.pdf",
> "contentType": "application/pdf"
> }'
>
>**Response**
>{
> "uploadUrl": "https://abc123.r2.cloudflarestorage.com/...&X-Amz-Credential=...",
> "fileKey": "merchants/your-merchant-id/550e8400-e29b-41d4-a716-446655440000.pdf"
>}

Step 2: Upload File to Presigned URL

$curl --request PUT \
> --url "PASTE_UPLOAD_URL_HERE" \
> --header 'Content-Type: application/pdf' \
> --data-binary @/path/to/your/file.pdf

Step 3: Reference the Uploaded File in your API Calls

Example: Submit chargeback response with the uploaded file

$curl --request POST \
> --url https://api-sandbox.coinflow.cash/api/merchant/chargebacks/PAYMENT_ID/respond \
> --header 'Authorization: YOUR_MERCHANT_API_KEY' \
> --header 'Content-Type: application/json' \
> --data '{
> "fileKey": "merchants/your-merchant-id/550e8400-e29b-41d4-a716-446655440000.pdf"
> }'

Example: JavaScript / TypeScript

1 // Step 1: Get presigned upload URL
2 const getUploadUrl = async (fileName: string, file: File) => {
3 const response = await fetch(
4 'https://api-sandbox.coinflow.cash/api/merchant/files/upload-url',
5 {
6 method: 'POST',
7 headers: {
8 Authorization: `${YOUR_API_KEY}`,
9 'Content-Type': 'application/json',
10 },
11 body: JSON.stringify({
12 fileName,
13 contentType: file.type,
14 }),
15 }
16 );
17
18 return response.json();
19 };
20
21 // Step 2: Upload file to Cloudflare R2
22 const uploadFile = async (uploadUrl: string, file: File) => {
23 await fetch(uploadUrl, {
24 method: 'PUT',
25 headers: { 'Content-Type': file.type },
26 body: file,
27 });
28 };
29
30 // Step 3: Submit chargeback response using the uploaded file
31 const submitChargebackResponse = async (paymentId: string, fileKey: string) => {
32 const response = await fetch(
33 `https://api-sandbox.coinflow.cash/api/merchant/chargebacks/${paymentId}/respond`,
34 {
35 method: 'POST',
36 headers: {
37 Authorization: `${YOUR_API_KEY}`,
38 'Content-Type': 'application/json',
39 },
40 body: JSON.stringify({ fileKey }),
41 }
42 );
43
44 if (!response.ok) {
45 throw new Error(`Failed to submit chargeback response: ${response.statusText}`);
46 }
47
48 return response.json();
49 };
50
51 // Complete flow
52 const handleFileUploadAndSubmit = async (file: File, paymentId: string) => {
53 // Step 1: Get presigned URL
54 const { uploadUrl, fileKey } = await getUploadUrl(file.name, file);
55
56 // Step 2: Upload file
57 await uploadFile(uploadUrl, file);
58
59 console.log('File uploaded successfully! FileKey:', fileKey);
60
61 // Step 3: Submit chargeback response
62 const result = await submitChargebackResponse(paymentId, fileKey);
63
64 return result;
65 };