Generates a presigned S3 URL that the caller can use to upload a file (e.g. a KYC document) directly to Afriex’s secure storage. The returned URL is time-limited and scoped to the requested operation. The file name is sanitised before it is used: any directory part is dropped, characters outside A-Z a-z 0-9 . _ - become _, and the result is cut to 200 characters. The object is stored as {businessId}/{sanitisedName}, so always use the returned key, not the name you sent, when you reference the file in a later request.
Use it for KYC documents on customers or for transaction-related files such as SWIFT invoices.
1
Request a URL
Call POST /api/v1/media/url with the target fileName and a type (user for identity documents, transaction for transaction files). The response contains a presigned url, the stable object key, and expiresIn (seconds the URL remains valid; typically 300).
2
Upload the file
Send an HTTP PUT to the url with the file bytes as the body within the expiresIn window. If the window elapses, request a fresh URL.
3
Reference the file
Attach the returned key to any follow-up request (for example, the invoice field on a SWIFT withdraw, or a document field in SME Registration). Downstream endpoints only accept the object key; the presigned url itself is never accepted.
Static business API key issued from the dashboard. A business can
provision multiple API keys, each scoped to a configurable set
of permissions (e.g. read transactions, create deposits, etc).
Permissions are chosen per key at creation time in the dashboard
and may be revoked by deleting the key. Manage your keys and
their permissions under Developer → API keys in the dashboard.
A request whose key does not carry the permission the target
endpoint requires is rejected with 401 Unauthorized, the same
response an unrecognised, malformed, revoked or disabled key
returns. The API does not distinguish the two cases on the wire.
API version in ISO 8601 format. The only supported version is 2026-05-18, which is also the default when the header is omitted. Any other value is rejected with a 400 Bad Request.
The name of the file to upload. It is sanitised (directory parts removed, characters outside A-Z a-z 0-9 . _ - replaced with _, cut to 200 characters), so the stored name can differ from this value; use the returned key.
The category of the file being uploaded. Use transaction for transaction-related files (e.g. a transactions CSV) and user for user identity documents. Defaults to user when omitted.
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"Afriex Business API","colors":{"primary":"#0075FF","light":"#0075FF","dark":"#0075FF"},"logo":{"light":"https://mintcdn.com/afriex-5d97ad2e/-0c2OtRvdHYWM-P9/logo/light.svg?fit=max\u0026auto=format\u0026n=-0c2OtRvdHYWM-P9\u0026q=85\u0026s=de5afeca786c40704f98e96da7d2b1b9","dark":"https://mintcdn.com/afriex-5d97ad2e/-0c2OtRvdHYWM-P9/logo/dark.png?fit=max\u0026auto=format\u0026n=-0c2OtRvdHYWM-P9\u0026q=85\u0026s=cdc436ca4fd0df7233a6e3db67941a84"},"favicon":"https://mintcdn.com/afriex-5d97ad2e/-0c2OtRvdHYWM-P9/favicon.png?fit=max\u0026auto=format\u0026n=-0c2OtRvdHYWM-P9\u0026q=85\u0026s=48a66687297df9128bf997d1ad6f10cd","api":{"openapi":"api-reference/openapi.json"},"navbar":{"links":[{"href":"https://afriex.statuspage.io","label":"Status"},{"href":"mailto:support@afriex.com","label":"Support"},{"icon":"/images/play.svg","href":"https://god.gw.postman.com/run-collection/36243325-4caa2575-18c9-4374-892d-ea0dc5a9ec48?action=collection%2Ffork\u0026source=rip_markdown\u0026collection-url=entityId%3D36243325-4caa2575-18c9-4374-892d-ea0dc5a9ec48%26entityType%3Dcollection%26workspaceId%3D05fc21e0-e07f-4bc9-bab5-55be8ed3082d","label":"Run in Postman"}],"primary":{"type":"button","label":"Dashboard","href":"https://business.afriex.com/"}},"footer":{"socials":{"x":"https://x.com/afriexapp","github":"https://github.com/Afri-exchange","linkedin":"https://linkedin.com/company/afriex"}},"contextual":{"options":["copy","view","chatgpt","claude","mcp",{"title":"LLMs.txt","description":"Provide information to help LLMs use the full API docs site","icon":"robot","href":"https://docs.afriex.com/llms.txt"}],"display":"header"},"styling":{"latex":false},"navigation":{"global":{"anchors":[{"anchor":"Status","icon":"wave-pulse","href":"https://afriex.statuspage.io"},{"anchor":"Support","icon":"envelope","href":"mailto:support@afriex.com"}]},"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"afriex-5d97ad2e","hasAudioNarration":false,"actualSubdomain":"afriex-5d97ad2e","customDomains":["docs.afriex.com"],"gitSource":{"type":"github","owner":"afri-exchange","repo":"docs","deployBranch":"main","contentDirectory":"","isPrivate":true,"mountPath":"","label":""},"chroma":{"liveDeploymentHistoryId":"6ae59bb6acf37ed506a0f8f5","collectionId":"490feb78-2920-4995-97be-af4ea87f5aed","schemaVersion":"v3","latestBuiltDeploymentHistoryId":"6ae59bb6acf37ed506a0f8f5"},"entitlements":{},"buildId":"6ae59bb6acf37ed506a0f8f5","clientVersion":"0.0.4044","searchFilterCounts":[{"language":"default","tag":"API reference","count":63},{"language":"default","tag":"Payment Batches","count":12},{"language":"default","tag":"Payment Methods","count":11},{"language":"default","tag":"Guides","count":8},{"language":"default","tag":"Customers","count":7},{"language":"default","tag":"Transactions","count":7},{"language":"default","tag":"Webhooks","count":6},{"language":"default","tag":"Requests and responses","count":5},{"language":"default","tag":"Overview","count":4},{"language":"default","tag":"Sandbox helpers","count":4}]},"assistantConfig":{"enableAskAiButton":false,"enableStarterQuestions":false,"enableContextualStarterQuestions":false,"enableAskAiSearchBar":true},"basePath":"","hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"byok-sep-25","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"vite-origin","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-updated-9-15","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":false},"customCss":[{"filePath":"style.css","content":".navbar-link a[href^=\"https://god.gw.postman.com/\"]{padding:.375rem .75rem;border-radius:.375rem;background-color:#ff6c37;color:#fff;font-weight:600}.navbar-link a[href^=\"https://god.gw.postman.com/\"]:hover{background-color:#e85a2a;color:#fff}#navbar div.flex-1:has(>nav .navbar-link){flex:none}"}],"page":{"pagePath":"api-reference/endpoint/media/generate-upload-url","slug":"/api-reference/endpoint/media/generate-upload-url","pageMetadata":{"title":"Generate Upload URL","openapi":"POST /api/v1/media/url","description":"Generates a presigned S3 URL that the caller can use to upload a file (e.g. a KYC document) directly to Afriex's secure storage. The returned URL is time-limited and scoped to the requested operation. The file name is sanitised before it is used: any directory part is dropped, characters outside `A-Z a-z 0-9 . _ -` become `_`, and the result is cut to 200 characters. The object is stored as `{businessId}/{sanitisedName}`, so always use the returned `key`, not the name you sent, when you reference the file in a later request.","href":"/api-reference/endpoint/media/generate-upload-url"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx, jsxs: _jsxs} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n code: \"code\",\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsxs(_components.p, {\n children: [\"Generates a presigned S3 URL that the caller can use to upload a file (e.g. a KYC document) directly to Afriex’s secure storage. The returned URL is time-limited and scoped to the requested operation. The file name is sanitised before it is used: any directory part is dropped, characters outside \", _jsx(_components.code, {\n children: \"A-Z a-z 0-9 . _ -\"\n }), \" become \", _jsx(_components.code, {\n children: \"_\"\n }), \", and the result is cut to 200 characters. The object is stored as \", _jsx(_components.code, {\n children: \"{businessId}/{sanitisedName}\"\n }), \", so always use the returned \", _jsx(_components.code, {\n children: \"key\"\n }), \", not the name you sent, when you reference the file in a later request.\"]\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={a:`a`,code:`code`,p:`p`,..._provideComponents(),...props.components},{Step,Steps}=_components;if(!Step)_missingMdxReference(`Step`,true);if(!Steps)_missingMdxReference(`Steps`,true);return _jsxs(_Fragment,{children:[_jsx(_components.p,{children:`Use it for KYC documents on customers or for transaction-related files such as SWIFT invoices.`}),`\n`,_jsxs(Steps,{children:[_jsx(Step,{title:`Request a URL`,children:_jsxs(_components.p,{children:[`Call `,_jsx(_components.code,{children:`POST /api/v1/media/url`}),` with the target `,_jsx(_components.code,{children:`fileName`}),` and a `,_jsx(_components.code,{children:`type`}),` (`,_jsx(_components.code,{children:`user`}),` for identity documents, `,_jsx(_components.code,{children:`transaction`}),` for transaction files). The response contains a presigned `,_jsx(_components.code,{children:`url`}),`, the stable object `,_jsx(_components.code,{children:`key`}),`, and `,_jsx(_components.code,{children:`expiresIn`}),` (seconds the URL remains valid; typically `,_jsx(_components.code,{children:`300`}),`).`]})}),_jsx(Step,{title:`Upload the file`,children:_jsxs(_components.p,{children:[`Send an HTTP `,_jsx(_components.code,{children:`PUT`}),` to the `,_jsx(_components.code,{children:`url`}),` with the file bytes as the body within the `,_jsx(_components.code,{children:`expiresIn`}),` window. If the window elapses, request a fresh URL.`]})}),_jsx(Step,{title:`Reference the file`,children:_jsxs(_components.p,{children:[`Attach the returned `,_jsx(_components.code,{children:`key`}),` to any follow-up request (for example, the `,_jsx(_components.code,{children:`invoice`}),` field on a SWIFT withdraw, or a document field in `,_jsx(_components.a,{href:`/api-reference/endpoint/sme-registration/register`,children:`SME Registration`}),`). Downstream endpoints only accept the object `,_jsx(_components.code,{children:`key`}),`; the presigned `,_jsx(_components.code,{children:`url`}),` itself is never accepted.`]})})]})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"Generate Upload URL","openapi":"POST /api/v1/media/url","description":"Generates a presigned S3 URL that the caller can use to upload a file (e.g. a KYC document) directly to Afriex's secure storage. The returned URL is time-limited and scoped to the requested operation. The file name is sanitised before it is used: any directory part is dropped, characters outside `A-Z a-z 0-9 . _ -` become `_`, and the result is cut to 200 characters. The object is stored as `{businessId}/{sanitisedName}`, so always use the returned `key`, not the name you sent, when you reference the file in a later request.","href":"/api-reference/endpoint/media/generate-upload-url"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[],"codeExamples":{}},"jsLinks":[],"openApiReferenceData":{"operation":{"operationId":"generatePresignedURL","summary":"Generate a presigned URL for file upload","description":"Generates a presigned S3 URL that the caller can use to upload a file (e.g. a KYC document) directly to Afriex's secure storage. The returned URL is time-limited and scoped to the requested operation. The file name is sanitised before it is used: any directory part is dropped, characters outside `A-Z a-z 0-9 . _ -` become `_`, and the result is cut to 200 characters. The object is stored as `{businessId}/{sanitisedName}`, so always use the returned `key`, not the name you sent, when you reference the file in a later request.","tags":["Media"],"requestBody":"c038d7de-4dd6-404d-80f5-3456d62aed26","responses":{"200":"57a4a7e2-e901-479f-bc80-5da6986c4149","400":"95a03523-5833-43b1-bd0f-abdff6f05f63","401":"5678f9c9-b4b5-4465-b577-e00c7b962178","500":"85f3e294-57a7-4845-b706-3a9627101066","503":"7638c697-b0e4-406d-8d12-ddedf768f71b"},"method":"post","type":"path","servers":["3298ae0b-7333-4b60-8d1b-b6d15dc0a1b5","9fc63886-0a83-446b-9588-6621dfbf98da"],"security":["c6e6cee1-f5cd-49d4-aecb-1d77573277f3"],"path":"/api/v1/media/url","baseUrlOptions":["https://sandbox.api.afriex.com","https://api.afriex.com"],"title":"Generate a presigned URL for file upload","codeSamples":[],"requiredOnlyExamples":false,"requestExampleType":"generated","responseExampleType":"generated"},"dependencies":{"parameters":{"82cfa39b-3104-4db2-bb4c-d0f51201adbf":{"name":"x-api-version","in":"header","required":false,"description":"API version in ISO 8601 format. The only supported version is `2026-05-18`, which is also the default when the header is omitted. Any other value is rejected with a `400 Bad Request`.","schema":{"type":"string","isRequired":false,"description":"API version in ISO 8601 format. The only supported version is `2026-05-18`, which is also the default when the header is omitted. Any other value is rejected with a `400 Bad Request`.","uniqueKey":"","typeLabel":"string"}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["fileName"],"properties":{"fileName":{"type":"string","minLength":1,"description":"The name of the file to upload. It is sanitised (directory parts removed, characters outside `A-Z a-z 0-9 . _ -` replaced with `_`, cut to 200 characters), so the stored name can differ from this value; use the returned `key`.","examples":["document.pdf"],"isRequired":true,"uniqueKey":"fileName","typeLabel":"string"},"type":{"type":"string","enum":["transaction","user"],"description":"The category of the file being uploaded. Use `transaction` for transaction-related files (e.g. a transactions CSV) and `user` for user identity documents. Defaults to `user` when omitted.\n","uniqueKey":"type","typeLabel":"enum\u003cstring>"}},"uniqueKey":"","typeLabel":"object"},"examples":{"upload-user":{"title":"upload-user","value":{"fileName":"passport.png","type":"user"}},"upload-transaction":{"title":"upload-transaction","value":{"fileName":"report.csv","type":"transaction"}}},"exampleType":"examples"}},"exampleType":"examples"},"responses":{"57a4a7e2-e901-479f-bc80-5da6986c4149":{"description":"Presigned URL generated successfully.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"url":{"type":"string","description":"The presigned URL for the requested upload operation.","examples":["https://s3.amazonaws.com/bucket/key?X-Amz-Algorithm=AWS4-HMAC-SHA256\u0026..."],"uniqueKey":"data.url","typeLabel":"string"},"key":{"type":"string","description":"A stable reference to the uploaded object, in the form `{businessId}/{sanitisedFileName}`. Attach this to a later request (e.g. a SWIFT payout invoice) rather than the presigned URL, which expires shortly after it is issued, and rather than the file name you sent, which may have been sanitised.\n","examples":["64f0c2a1e4b0a1b2c3d4e5f6/invoice.pdf"],"uniqueKey":"data.key","typeLabel":"string"},"expiresIn":{"type":"integer","description":"Number of seconds the presigned URL remains valid for the upload. Complete the PUT upload within this window; afterwards, request a fresh URL.\n","examples":[300],"uniqueKey":"data.expiresIn","typeLabel":"integer"}},"uniqueKey":"data","typeLabel":"object"}},"uniqueKey":"","typeLabel":"object"},"examples":{"url":{"title":"url","value":{"data":{"url":"https://s3.amazonaws.com/bucket/key?X-Amz-Algorithm=AWS4-HMAC-SHA256\u0026...","key":"64f0c2a1e4b0a1b2c3d4e5f6/invoice.pdf","expiresIn":300}}}},"exampleType":"examples"}},"exampleType":"examples"},"95a03523-5833-43b1-bd0f-abdff6f05f63":{"description":"Invalid request body, or a `fileName` that names no file once directory parts and unsafe characters are removed (for example `/`).","content":{"application/json":{"schema":{"type":"object","properties":{"code":{"type":"string","description":"Machine-readable error code.","uniqueKey":"code","typeLabel":"string"},"error":{"type":"string","description":"Human-readable error message.","uniqueKey":"error","typeLabel":"string"},"details":{"type":"object","properties":{"errorMessage":{"type":"string","description":"Detailed/technical error message.","uniqueKey":"details.errorMessage","typeLabel":"string"},"friendlyMessage":{"type":"string","description":"User-facing error message safe to display.","uniqueKey":"details.friendlyMessage","typeLabel":"string"},"data":{"type":"object","description":"Optional caller-safe context for the error. On a customer-create uniqueness conflict (EMAIL_ALREADY_EXISTS / PHONE_NUMBER_ALREADY_EXISTS) this carries the existing customer's id, so you can adopt it without a follow-up lookup.","properties":{"customerId":{"type":"string","description":"Id of the existing customer (on a create conflict).","uniqueKey":"details.data.customerId","typeLabel":"string"}},"uniqueKey":"details.data","typeLabel":"object"}},"uniqueKey":"details","typeLabel":"object"}},"uniqueKey":"","typeLabel":"object"},"examples":{"emptyFileName":{"title":"emptyFileName","value":{"code":"VALIDATION_ERROR","error":"Failed to parse request. Issues: 'fileName' is not allowed to be empty","details":{}}},"noFileName":{"title":"noFileName","value":{"code":"BAD_REQUEST_ERROR","error":"fileName must name a file","details":{}}}},"exampleType":"examples"}},"exampleType":"examples"},"5678f9c9-b4b5-4465-b577-e00c7b962178":{"description":"Unauthorized - Invalid business API key.","content":{"application/json":{"schema":{"type":"object","properties":{"code":{"type":"string","description":"Machine-readable error code.","uniqueKey":"code","typeLabel":"string"},"error":{"type":"string","description":"Human-readable error message.","uniqueKey":"error","typeLabel":"string"},"details":{"type":"object","properties":{"errorMessage":{"type":"string","description":"Detailed/technical error message.","uniqueKey":"details.errorMessage","typeLabel":"string"},"friendlyMessage":{"type":"string","description":"User-facing error message safe to display.","uniqueKey":"details.friendlyMessage","typeLabel":"string"},"data":{"type":"object","description":"Optional caller-safe context for the error. On a customer-create uniqueness conflict (EMAIL_ALREADY_EXISTS / PHONE_NUMBER_ALREADY_EXISTS) this carries the existing customer's id, so you can adopt it without a follow-up lookup.","properties":{"customerId":{"type":"string","description":"Id of the existing customer (on a create conflict).","uniqueKey":"details.data.customerId","typeLabel":"string"}},"uniqueKey":"details.data","typeLabel":"object"}},"uniqueKey":"details","typeLabel":"object"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"code":"\u003cstring>","error":"\u003cstring>","details":{"errorMessage":"\u003cstring>","friendlyMessage":"\u003cstring>","data":{"customerId":"\u003cstring>"}}}}},"exampleType":"generated"}},"exampleType":"generated"},"85f3e294-57a7-4845-b706-3a9627101066":{"description":"The upload URL could not be generated. Retry the request.","content":{"application/json":{"schema":{"type":"object","properties":{"code":{"type":"string","description":"Machine-readable error code.","uniqueKey":"code","typeLabel":"string"},"error":{"type":"string","description":"Human-readable error message.","uniqueKey":"error","typeLabel":"string"},"details":{"type":"object","properties":{"errorMessage":{"type":"string","description":"Detailed/technical error message.","uniqueKey":"details.errorMessage","typeLabel":"string"},"friendlyMessage":{"type":"string","description":"User-facing error message safe to display.","uniqueKey":"details.friendlyMessage","typeLabel":"string"},"data":{"type":"object","description":"Optional caller-safe context for the error. On a customer-create uniqueness conflict (EMAIL_ALREADY_EXISTS / PHONE_NUMBER_ALREADY_EXISTS) this carries the existing customer's id, so you can adopt it without a follow-up lookup.","properties":{"customerId":{"type":"string","description":"Id of the existing customer (on a create conflict).","uniqueKey":"details.data.customerId","typeLabel":"string"}},"uniqueKey":"details.data","typeLabel":"object"}},"uniqueKey":"details","typeLabel":"object"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"code":"\u003cstring>","error":"\u003cstring>","details":{"errorMessage":"\u003cstring>","friendlyMessage":"\u003cstring>","data":{"customerId":"\u003cstring>"}}}}},"exampleType":"generated"}},"exampleType":"generated"},"7638c697-b0e4-406d-8d12-ddedf768f71b":{"description":"Temporarily unavailable: an upstream service failed or timed out, or the API is momentarily offline. Retry with backoff and honour the Retry-After header when present.","content":{"application/json":{"schema":{"type":"object","properties":{"code":{"type":"string","description":"Machine-readable error code.","uniqueKey":"code","typeLabel":"string"},"error":{"type":"string","description":"Human-readable error message.","uniqueKey":"error","typeLabel":"string"},"details":{"type":"object","properties":{"errorMessage":{"type":"string","description":"Detailed/technical error message.","uniqueKey":"details.errorMessage","typeLabel":"string"},"friendlyMessage":{"type":"string","description":"User-facing error message safe to display.","uniqueKey":"details.friendlyMessage","typeLabel":"string"},"data":{"type":"object","description":"Optional caller-safe context for the error. On a customer-create uniqueness conflict (EMAIL_ALREADY_EXISTS / PHONE_NUMBER_ALREADY_EXISTS) this carries the existing customer's id, so you can adopt it without a follow-up lookup.","properties":{"customerId":{"type":"string","description":"Id of the existing customer (on a create conflict).","uniqueKey":"details.data.customerId","typeLabel":"string"}},"uniqueKey":"details.data","typeLabel":"object"}},"uniqueKey":"details","typeLabel":"object"}},"uniqueKey":"","typeLabel":"object"},"examples":{"serviceUnavailable":{"title":"serviceUnavailable","value":{"code":"EXTERNAL_REQUEST_ERROR","error":"External request error","details":{}}}},"exampleType":"examples"}},"exampleType":"examples"}},"security":{"c6e6cee1-f5cd-49d4-aecb-1d77573277f3":{"ApiKey":{"type":"apiKey","in":"header","name":"x-api-key","description":"Static business API key issued from the dashboard. A business can\nprovision **multiple API keys**, each scoped to a configurable set\nof **permissions** (e.g. read transactions, create deposits, etc).\nPermissions are chosen per key at creation time in the dashboard\nand may be revoked by deleting the key. Manage your keys and\ntheir permissions under **Developer → API keys** in the dashboard.\n\nA request whose key does not carry the permission the target\nendpoint requires is rejected with `401 Unauthorized`, the same\nresponse an unrecognised, malformed, revoked or disabled key\nreturns. The API does not distinguish the two cases on the wire.\n\nSee the [Permissions reference](https://docs.afriex.com/api-reference/permissions)\nfor the permission each endpoint requires.","scopes":[],"schemeName":"ApiKey"}}},"servers":{"3298ae0b-7333-4b60-8d1b-b6d15dc0a1b5":{"url":"https://sandbox.api.afriex.com","description":"Sandbox Base URL"},"9fc63886-0a83-446b-9588-6621dfbf98da":{"url":"https://api.afriex.com","description":"Production Base URL"}},"processedSecurityOptions":[{"schemes":[{"scheme":{"type":"apiKey","in":"header","name":"x-api-key","description":"Static business API key issued from the dashboard. A business can\nprovision **multiple API keys**, each scoped to a configurable set\nof **permissions** (e.g. read transactions, create deposits, etc).\nPermissions are chosen per key at creation time in the dashboard\nand may be revoked by deleting the key. Manage your keys and\ntheir permissions under **Developer → API keys** in the dashboard.\n\nA request whose key does not carry the permission the target\nendpoint requires is rejected with `401 Unauthorized`, the same\nresponse an unrecognised, malformed, revoked or disabled key\nreturns. The API does not distinguish the two cases on the wire.\n\nSee the [Permissions reference](https://docs.afriex.com/api-reference/permissions)\nfor the permission each endpoint requires.","scopes":[],"schemeName":"ApiKey"},"schema":{"title":"x-api-key","type":"string","description":"Static business API key issued from the dashboard. A business can\nprovision **multiple API keys**, each scoped to a configurable set\nof **permissions** (e.g. read transactions, create deposits, etc).\nPermissions are chosen per key at creation time in the dashboard\nand may be revoked by deleting the key. Manage your keys and\ntheir permissions under **Developer → API keys** in the dashboard.\n\nA request whose key does not carry the permission the target\nendpoint requires is rejected with `401 Unauthorized`, the same\nresponse an unrecognised, malformed, revoked or disabled key\nreturns. The API does not distinguish the two cases on the wire.\n\nSee the [Permissions reference](https://docs.afriex.com/api-reference/permissions)\nfor the permission each endpoint requires.","isRequired":true,"typeLabel":"string","deprecated":false},"schemeName":"ApiKey","name":"x-api-key"}],"title":"ApiKey"}]},"originalFileLocation":"api-reference/openapi.json"},"subdomain":"afriex-5d97ad2e","siteName":"Afriex Business API","title":"Generate Upload URL - Afriex Business API","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-10-16T09:09:40.691Z","originalFileLocation":"api-reference/endpoint/media/generate-upload-url.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Generates a presigned S3 URL that the caller can use to upload a file (e.g. a KYC document) directly to Afriex\u0026#x27;s secure storage. The returned URL is time-limited and scoped to the requested operation. The file name is sanitised before it is used: any directory part is dropped, characters outside A-Z a-z 0-9 . - become `, and the result is cut to 200 characters. The object is stored as {businessId}/{sanitisedName}, so always use the returned key`, not the name you sent, when you reference the file in a later request.\">\u003cmeta data-mint-head name=\"application-name\" content=\"Afriex Business API\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/afriex-5d97ad2e/ZexKAY-mYWAtBk6G/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/afriex-5d97ad2e/ZexKAY-mYWAtBk6G/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/afriex-5d97ad2e/ZexKAY-mYWAtBk6G/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/afriex-5d97ad2e/ZexKAY-mYWAtBk6G/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/afriex-5d97ad2e/ZexKAY-mYWAtBk6G/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/afriex-5d97ad2e/ZexKAY-mYWAtBk6G/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/afriex-5d97ad2e/ZexKAY-mYWAtBk6G/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/afriex-5d97ad2e/ZexKAY-mYWAtBk6G/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/afriex-5d97ad2e/ZexKAY-mYWAtBk6G/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Generate Upload URL - Afriex Business API\">\u003cmeta data-mint-head property=\"og:description\" content=\"Generates a presigned S3 URL that the caller can use to upload a file (e.g. a KYC document) directly to Afriex\u0026#x27;s secure storage. The returned URL is time-limited and scoped to the requested operation. The file name is sanitised before it is used: any directory part is dropped, characters outside A-Z a-z 0-9 . - become `, and the result is cut to 200 characters. The object is stored as {businessId}/{sanitisedName}, so always use the returned key`, not the name you sent, when you reference the file in a later request.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Afriex Business API\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.afriex.com/api-reference/endpoint/media/generate-upload-url\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://afriex-5d97ad2e.mintlify.app/_mintlify/api/og/v2?division=Media\u0026amp;title=Generate+Upload+URL\u0026amp;description=Generates+a+presigned+S3+URL+that+the+caller+can+use+to+upload+a+file+%28e.g.+a+KYC+document%29+directly+to+Afriex%27s+secure+storage.+The+returned+URL+is+time-limite\u0026amp;theme=c5e7ac6707206fe4b7db0208\u0026amp;signature=590d0c8a1fb9b2b4e405a5e42bb69dc424ea2fee44a2e57b72a94ee2ab364224\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Generate Upload URL - Afriex Business API\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Generates a presigned S3 URL that the caller can use to upload a file (e.g. a KYC document) directly to Afriex\u0026#x27;s secure storage. The returned URL is time-limited and scoped to the requested operation. The file name is sanitised before it is used: any directory part is dropped, characters outside A-Z a-z 0-9 . - become `, and the result is cut to 200 characters. The object is stored as {businessId}/{sanitisedName}, so always use the returned key`, not the name you sent, when you reference the file in a later request.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://afriex-5d97ad2e.mintlify.app/_mintlify/api/og/v2?division=Media\u0026amp;title=Generate+Upload+URL\u0026amp;description=Generates+a+presigned+S3+URL+that+the+caller+can+use+to+upload+a+file+%28e.g.+a+KYC+document%29+directly+to+Afriex%27s+secure+storage.+The+returned+URL+is+time-limite\u0026amp;theme=c5e7ac6707206fe4b7db0208\u0026amp;signature=590d0c8a1fb9b2b4e405a5e42bb69dc424ea2fee44a2e57b72a94ee2ab364224\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/afriex-5d97ad2e/ZexKAY-mYWAtBk6G/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Afriex Business API\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#0075FF\">\u003clink data-mint-head rel=\"canonical\" href=\"https://docs.afriex.com/api-reference/endpoint/media/generate-upload-url\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/api-reference/endpoint/media/generate-upload-url.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://docs.afriex.com/#organization\",\"name\":\"Afriex Business API\",\"url\":\"https://docs.afriex.com\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/afriex-5d97ad2e/-0c2OtRvdHYWM-P9/logo/light.svg?fit=max\u0026auto=format\u0026n=-0c2OtRvdHYWM-P9\u0026q=85\u0026s=de5afeca786c40704f98e96da7d2b1b9\"}},{\"@type\":\"WebSite\",\"@id\":\"https://docs.afriex.com#website\",\"name\":\"Afriex Business API\",\"url\":\"https://docs.afriex.com\",\"publisher\":{\"@id\":\"https://docs.afriex.com/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://docs.afriex.com/api-reference/endpoint/media/generate-upload-url#webpage\",\"url\":\"https://docs.afriex.com/api-reference/endpoint/media/generate-upload-url\",\"name\":\"Generate Upload URL\",\"description\":\"Generates a presigned S3 URL that the caller can use to upload a file (e.g. a KYC document) directly to Afriex's secure storage. The returned URL is time-limited and scoped to the requested operation. The file name is sanitised before it is used: any directory part is dropped, characters outside A-Z a-z 0-9 . - become `, and the result is cut to 200 characters. The object is stored as {businessId}/{sanitisedName}, so always use the returned key`, not the name you sent, when you reference the file in a later request.\",\"dateModified\":\"2026-10-16T09:09:40.691Z\",\"isPartOf\":{\"@id\":\"https://docs.afriex.com#website\"},\"breadcrumb\":{\"@id\":\"https://docs.afriex.com/api-reference/endpoint/media/generate-upload-url#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.afriex.com/api-reference/endpoint/media/generate-upload-url#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Afriex Business API\",\"item\":\"https://docs.afriex.com\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Generate Upload URL\",\"item\":\"https://docs.afriex.com/api-reference/endpoint/media/generate-upload-url\"}]},{\"@type\":[\"TechArticle\",\"APIReference\"],\"@id\":\"https://docs.afriex.com/api-reference/endpoint/media/generate-upload-url#apireference\",\"headline\":\"Generate Upload URL\",\"name\":\"Generate Upload URL\",\"description\":\"Generates a presigned S3 URL that the caller can use to upload a file (e.g. a KYC document) directly to Afriex's secure storage. The returned URL is time-limited and scoped to the requested operation. The file name is sanitised before it is used: any directory part is dropped, characters outside A-Z a-z 0-9 . - become `, and the result is cut to 200 characters. The object is stored as {businessId}/{sanitisedName}, so always use the returned key`, not the name you sent, when you reference the file in a later request.\",\"url\":\"https://docs.afriex.com/api-reference/endpoint/media/generate-upload-url\",\"mainEntityOfPage\":{\"@id\":\"https://docs.afriex.com/api-reference/endpoint/media/generate-upload-url#webpage\"},\"dateModified\":\"2026-10-16T09:09:40.691Z\",\"publisher\":{\"@id\":\"https://docs.afriex.com/#organization\"},\"isPartOf\":{\"@id\":\"https://docs.afriex.com#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"Afriex Business API\",\"creator\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","siteName":"Afriex Business API","nav":{"global":{"anchors":[{"anchor":"Status","icon":"wave-pulse","href":"https://afriex.statuspage.io"},{"anchor":"Support","icon":"envelope","href":"mailto:support@afriex.com"}]},"tabs":[{"tab":"Guides","pages":[{"title":"Guides","href":""}]},{"tab":"SDK","pages":[{"title":"SDK","href":"/sdk/introduction"}]},{"tab":"MCP","pages":[{"title":"MCP","href":"/mcp/introduction"}]},{"tab":"API reference","groups":[{"group":"Overview","pages":[{"title":"Introduction","href":"/api-reference/introduction"},{"title":"Authentication","href":"/api-reference/authentication"},{"title":"Permissions","href":"/api-reference/permissions"},{"title":"IP allowlisting","href":"/api-reference/ip-allowlisting"}]},{"group":"Requests and responses","pages":[{"title":"Idempotency","href":"/api-reference/idempotency"},{"title":"Errors","href":"/api-reference/errors"},{"title":"Pagination","href":"/api-reference/pagination"},{"title":"Rate limits","href":"/api-reference/rate-limits"},{"title":"Models","href":"/api-reference/models"}]},{"group":"Balance","pages":[{"title":"Get Balance","openapi":"GET /api/v1/org/balance","href":"/api-reference/endpoint/balance/get"}]},{"group":"Checkout Sessions","pages":[{"title":"Checkout Flow Guide","href":"/api-reference/endpoint/checkout-sessions/user-flow-guide"},{"title":"Create Checkout Session","openapi":"POST /api/v1/checkout-session","href":"/api-reference/endpoint/checkout-sessions/create"}]},{"group":"Rates","pages":[{"title":"Get Exchange Rates","openapi":"GET /api/v1/org/rates","href":"/api-reference/endpoint/rates/get"}]},{"group":"Customers","pages":[{"title":"Create Customer","openapi":"POST /api/v1/customer","href":"/api-reference/endpoint/customers/create"},{"title":"List Customers","openapi":"GET /api/v1/customer","href":"/api-reference/endpoint/customers/list"},{"title":"Get Customer","openapi":"GET /api/v1/customer/{customerId}","href":"/api-reference/endpoint/customers/get"},{"title":"Update Customer","openapi":"PATCH /api/v1/customer/{customerId}","href":"/api-reference/endpoint/customers/update"},{"title":"Delete Customer","openapi":"DELETE /api/v1/customer/{customerId}","href":"/api-reference/endpoint/customers/delete"},{"title":"Update Customer KYC","openapi":"PATCH /api/v1/customer/{customerId}/kyc","href":"/api-reference/endpoint/customers/update-kyc"},{"title":"Verify Customer","openapi":"POST /api/v1/customer/{customerId}/verify","href":"/api-reference/endpoint/customers/verify"}]},{"group":"Payment Methods","pages":[{"title":"Create Payment Method","openapi":"POST /api/v1/payment-method","href":"/api-reference/endpoint/payment-methods/create"},{"title":"List Payment Methods","openapi":"GET /api/v1/payment-method","href":"/api-reference/endpoint/payment-methods/list"},{"title":"Get Payment Method","openapi":"GET /api/v1/payment-method/{paymentMethodId}","href":"/api-reference/endpoint/payment-methods/get"},{"title":"Delete Payment Method","openapi":"DELETE /api/v1/payment-method/{paymentMethodId}","href":"/api-reference/endpoint/payment-methods/delete"},{"title":"List Institutions","openapi":"GET /api/v1/payment-method/institution","href":"/api-reference/endpoint/payment-methods/institution"},{"title":"Institution Codes","openapi":"GET /api/v1/payment-method/institution/codes","href":"/api-reference/endpoint/payment-methods/institution-codes"},{"title":"Resolve Payment Method","openapi":"GET /api/v1/payment-method/resolve","href":"/api-reference/endpoint/payment-methods/resolve"},{"title":"Get or Create Crypto Wallet","openapi":"GET /api/v1/payment-method/crypto-wallet","href":"/api-reference/endpoint/payment-methods/crypto-wallet"},{"title":"List Virtual Accounts","openapi":"GET /api/v1/payment-method/virtual-account","href":"/api-reference/endpoint/payment-methods/virtual-account"},{"title":"Create Virtual Account","openapi":"POST /api/v1/payment-method/virtual-account","href":"/api-reference/endpoint/payment-methods/virtual-account-create"},{"title":"Get Pool Account","openapi":"GET /api/v1/payment-method/pool-account","description":"Returns the pool account for the supplied `country`. Use the\n`reference` on the response to reconcile incoming deposits; it is a\nshortened form such as `afx1234` (with a customer, `afx1234012`).\nEach call also sends a `PAYMENT_METHOD.UPDATED` webhook carrying the\npool account.\n","href":"/api-reference/endpoint/payment-methods/pool-account"}]},{"group":"Media","pages":[{"title":"Generate Upload URL","openapi":"POST /api/v1/media/url","href":"/api-reference/endpoint/media/generate-upload-url"}]},{"group":"Transactions","pages":[{"title":"Create Transaction","openapi":"POST /api/v1/transaction","description":"Create a new transaction to process a payment for a customer. Use `type: WITHDRAW` to send funds to a destination payment method (requires `destinationId`), `type: DEPOSIT` to pull funds from a source payment method (requires `sourceId`), or `type: SWAP` to convert funds between currencies within the Afriex wallet (requires `sourceCurrency`, `destinationCurrency`, `meta`, and exactly one of `sourceAmount` or `destinationAmount`). A DEPOSIT settles in one currency, so `sourceCurrency` and `destinationCurrency` must be the same. Card deposits cannot be created through the API. Your business must have a webhook URL set, otherwise the request is rejected with a 400.\n","href":"/api-reference/endpoint/transactions/create"},{"title":"List Transactions","openapi":"GET /api/v1/transaction","href":"/api-reference/endpoint/transactions/list"},{"title":"Quote a Withdrawal","openapi":"GET /api/v1/transaction/quote","href":"/api-reference/endpoint/transactions/quote"},{"title":"Get Transaction","openapi":"GET /api/v1/transaction/{transactionId}","href":"/api-reference/endpoint/transactions/get"},{"title":"Authorize Transaction","openapi":"POST /api/v1/transaction/{transactionId}/authorize","href":"/api-reference/endpoint/transactions/authorize"},{"title":"Get Settlement Advice","openapi":"GET /api/v1/transaction/{transactionId}/advice","href":"/api-reference/endpoint/transactions/advice"},{"title":"Submit Pool-Account Payment Proof","openapi":"POST /api/v1/transaction/pool-account","href":"/api-reference/endpoint/transactions/pool-account-proof"}]},{"group":"Payment Batches","pages":[{"title":"List Payment Batches","openapi":"GET /api/v1/payment-batch","href":"/api-reference/endpoint/payment-batches/list"},{"title":"Create Payment Batch","openapi":"POST /api/v1/payment-batch","href":"/api-reference/endpoint/payment-batches/create"},{"title":"Get Payment Batch","openapi":"GET /api/v1/payment-batch/{batchId}","href":"/api-reference/endpoint/payment-batches/get"},{"title":"Update Payment Batch","openapi":"PATCH /api/v1/payment-batch/{batchId}","href":"/api-reference/endpoint/payment-batches/update"},{"title":"Delete Payment Batch","openapi":"DELETE /api/v1/payment-batch/{batchId}","href":"/api-reference/endpoint/payment-batches/delete"},{"title":"List Batch Recipients","openapi":"GET /api/v1/payment-batch/{batchId}/recipients","href":"/api-reference/endpoint/payment-batches/list-recipients"},{"title":"Add Recipient to Batch","openapi":"POST /api/v1/payment-batch/{batchId}/recipients","href":"/api-reference/endpoint/payment-batches/add-recipient"},{"title":"Bulk Add Recipients to Batch","openapi":"POST /api/v1/payment-batch/{batchId}/recipients/bulk","href":"/api-reference/endpoint/payment-batches/add-recipients-bulk"},{"title":"Update Recipient in Batch","openapi":"PATCH /api/v1/payment-batch/{batchId}/recipients/{recipientId}","href":"/api-reference/endpoint/payment-batches/update-recipient"},{"title":"Remove Recipient from Batch","openapi":"DELETE /api/v1/payment-batch/{batchId}/recipients/{recipientId}","href":"/api-reference/endpoint/payment-batches/remove-recipient"},{"title":"Withdraw Batch","openapi":"POST /api/v1/payment-batch/{batchId}/withdraw","href":"/api-reference/endpoint/payment-batches/withdraw"},{"title":"List Batch Sessions","openapi":"GET /api/v1/payment-batch/{batchId}/sessions","href":"/api-reference/endpoint/payment-batches/list-sessions"}]},{"group":"SME Registration","pages":[{"title":"Register SME","openapi":"POST /api/v1/sme-registration","href":"/api-reference/endpoint/sme-registration/register"},{"title":"Get SME Registration Status","openapi":"GET /api/v1/sme-registration/status","href":"/api-reference/endpoint/sme-registration/status"}]},{"group":"Sandbox helpers","pages":[{"title":"Simulate Transaction Outcome","openapi":"POST /api/v1/transaction/{transactionId}/simulate","href":"/api-reference/endpoint/transactions/simulate"},{"title":"Top Up Sandbox Balance","openapi":"POST /api/v1/org/balance/topup","href":"/api-reference/endpoint/balance/topup"},{"title":"Simulate Virtual Account Transfer","openapi":"POST /api/v1/payment-method/virtual-account/simulate-transfer","href":"/api-reference/endpoint/payment-methods/virtual-account-simulate-transfer"},{"title":"Trigger Test Webhook","openapi":"POST /api/v1/webhooks/trigger","href":"/api-reference/endpoint/webhooks/trigger"}]},{"group":"Webhooks","pages":[{"title":"Introduction","href":"/api-reference/endpoint/webhooks/introduction"},{"title":"Customer Events","openapi":"webhook customer.events","href":"/api-reference/endpoint/webhooks/customer-events"},{"title":"Payment Method Events","openapi":"webhook payment_method.events","href":"/api-reference/endpoint/webhooks/payment-method-events"},{"title":"Transaction Events","openapi":"webhook transaction.events","href":"/api-reference/endpoint/webhooks/transaction-events"},{"title":"Checkout Session Events","openapi":"webhook checkout_session.events","href":"/api-reference/endpoint/webhooks/checkout-session-events"},{"title":"Pool Deposit Events","openapi":"webhook pool_deposit_request.events","href":"/api-reference/endpoint/webhooks/pool-deposit-events"}]}]}]},"basePath":"","title":"Generate Upload URL - Afriex Business API","buildId":"dpl_DeHjVRGfFnhYQwHnfC2pjeXXv8h9","deploymentId":"dpl_DeHjVRGfFnhYQwHnfC2pjeXXv8h9","dynamics":["c2aa737661","2b790eda92","b0f84f53ff","a9bb46feb3"],"chunks":["OpenApiReferenceProvider-CS552b7R.js","utils-DDTCYAF2.js","cloneDeep-izs3Hzxb.js","_Uint8Array-BVIqJ90l.js","isObjectLike-C8vmzPEN.js","isArray-Dcu1dQ5t.js","utils-De8ttokP.js","toString-BX-iyh8G.js","isSymbol-CSH9U2Gm.js","addUniqueKeysToSchema-DrwRDvAh.js","snippetPresets-DtAN0nWx.js","style-to-object-BY3JEAdk.js","v4-DIgz8zy6.js","ApiExamples-D5rWArI6.js","isEqual-BfaiBbcl.js","usePlaygroundInputsStore-O2i12wsz.js","shallow-DV8xABTt.js","getApiPlaygroundDisplay-DBZ0B5Jx.js","CodeSnippet-BVi0tPUX.js","CodeSnippets-CqASbIwY.js","Page-m07pfKpT.js","getPastedJson-DG9vsMS8.js","icon-CXzRSCr8.js","MethodPill-BdKVtEuX.js","DuplicateIcon-CZlmBrJI.js","createIcon-biFEUKPL.js","DynamicMarkdown-B54_zNBF.js","SectionHeading-DwwHK3Pt.js","axios-vUo_bRtp.js","Markdown-DfhCTwyA.js","clsx-xpJZXxdP.js","lib-DuNMoZ05.js","lib-B8HbPgcC.js","html-void-elements-mCSPHezU.js","dist-BTZUMDnx.js","katex-YMM-FMeD.js","marked.esm-CZWythHk.js","AssistantPageLink-DqdKa2R4.js"]}