Request CV Upload URL
curl --request POST \
--url https://api.example.com/api/v1/cv/presigned-url \
--header 'Content-Type: application/json' \
--data '
{
"fileName": "<string>",
"mimeType": "<string>"
}
'import requests
url = "https://api.example.com/api/v1/cv/presigned-url"
payload = {
"fileName": "<string>",
"mimeType": "<string>"
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({fileName: '<string>', mimeType: '<string>'})
};
fetch('https://api.example.com/api/v1/cv/presigned-url', 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.example.com/api/v1/cv/presigned-url",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'fileName' => '<string>',
'mimeType' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$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.example.com/api/v1/cv/presigned-url"
payload := strings.NewReader("{\n \"fileName\": \"<string>\",\n \"mimeType\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
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.example.com/api/v1/cv/presigned-url")
.header("Content-Type", "application/json")
.body("{\n \"fileName\": \"<string>\",\n \"mimeType\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/api/v1/cv/presigned-url")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"fileName\": \"<string>\",\n \"mimeType\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"uploadUrl": "<string>",
"key": "<string>"
}CV
Request CV Upload URL
Request a presigned URL for uploading your CV file
POST
/
api
/
v1
/
cv
/
presigned-url
Request CV Upload URL
curl --request POST \
--url https://api.example.com/api/v1/cv/presigned-url \
--header 'Content-Type: application/json' \
--data '
{
"fileName": "<string>",
"mimeType": "<string>"
}
'import requests
url = "https://api.example.com/api/v1/cv/presigned-url"
payload = {
"fileName": "<string>",
"mimeType": "<string>"
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({fileName: '<string>', mimeType: '<string>'})
};
fetch('https://api.example.com/api/v1/cv/presigned-url', 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.example.com/api/v1/cv/presigned-url",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'fileName' => '<string>',
'mimeType' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$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.example.com/api/v1/cv/presigned-url"
payload := strings.NewReader("{\n \"fileName\": \"<string>\",\n \"mimeType\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
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.example.com/api/v1/cv/presigned-url")
.header("Content-Type", "application/json")
.body("{\n \"fileName\": \"<string>\",\n \"mimeType\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/api/v1/cv/presigned-url")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"fileName\": \"<string>\",\n \"mimeType\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"uploadUrl": "<string>",
"key": "<string>"
}Endpoint
POST /api/v1/cv/presigned-url
http://localhost:3000/api/v1
This endpoint requires authentication and Job Seeker role.
Authentication
Include the access token in the Authorization header:Authorization: Bearer YOUR_ACCESS_TOKEN
Description
Request a presigned URL for uploading your CV file to cloud storage. This is the first step in the CV upload process.Request Body
string
required
The name of the file to upload (e.g., “my-cv.pdf”).
string
required
The MIME type of the file. Supported types: -
application/pdf -
application/vnd.openxmlformats-officedocument.wordprocessingml.document (.docx)Request Example
{
"fileName": "test-cv.pdf",
"mimeType": "application/pdf"
}
Response
Success Response (200 OK)
{
"success": true,
"data": {
"uploadUrl": "https://cvs.c0485e90a90f9be9ecd4e72559fee834.r2.cloudflarestorage.com/cvs/a9ff20fb-8010-4a22-8873-344c103726af/1771315860529-test-cv.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=c1feabbe8cd3c62e2dc015a4be9881f0%2F20260217%2Fauto%2Fs3%2Faws4_request&X-Amz-Date=20260217T081100Z&X-Amz-Expires=3600&X-Amz-Signature=4cc903d3ef75e39b8a3374304d214828bd1291e7acf661fd3d4f3d09ae414983&X-Amz-SignedHeaders=host&x-id=PutObject",
"key": "cvs/a9ff20fb-8010-4a22-8873-344c103726af/1771315860529-test-cv.pdf"
},
"message": "Success",
"meta": {
"timestamp": "2026-04-23T20:00:00.000Z",
"path": "/cv/presigned-url",
"method": "POST"
}
}
Response Fields
string
The presigned URL to use for uploading the file. This URL is valid for 1 hour (3600 seconds).
string
The storage key/path where the file will be stored. Save this for the confirmation step.
Error Responses
401 Unauthorized
{
"success": false,
"error": {
"message": "Unauthorized",
"statusCode": 401,
"timestamp": "2026-04-23T20:00:00.000Z",
"path": "/cv/presigned-url",
"method": "POST",
"details": "Unauthorized"
}
}
403 Forbidden
{
"success": false,
"error": {
"message": "Forbidden resource",
"statusCode": 403,
"timestamp": "2026-04-23T20:00:00.000Z",
"path": "/cv/presigned-url",
"method": "POST",
"details": "Forbidden"
}
}
400 Bad Request - Invalid File Type
{
"success": false,
"error": {
"message": [
"mimeType must be one of: application/pdf, application/vnd.openxmlformats-officedocument.wordprocessingml.document"
],
"statusCode": 400,
"timestamp": "2026-04-23T20:00:00.000Z",
"path": "/cv/presigned-url",
"method": "POST",
"details": "Bad Request"
}
}
Next Steps
- Use the
uploadUrlto upload your file (see Upload CV File) - After uploading, confirm the upload (see Confirm CV Upload)
URL Expiration: The presigned URL expires after 1 hour. If you don’t upload the file within
this time, you’ll need to request a new URL.
