curl -X POST "https://api.tktchurch.com/v1/files/provider/s3/upload" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
-H "Content-Type: image/jpeg" \
-H "Content-Disposition: attachment; filename=\"example.jpg\"" \
--data-binary "@/path/to/example.jpg"
const uploadFile = async (accessToken, provider, file) => {
const formData = new FormData();
formData.append('file', file);
const response = await fetch(
`https://api.tktchurch.com/v1/files/provider/${provider}/upload`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Disposition': `attachment; filename="${file.name}"`
},
body: file
}
);
if (!response.ok) {
const error = await response.json();
throw new Error(error.reason || 'Failed to upload file');
}
return response.json();
};
// Usage
try {
const file = new File(['...'], 'example.jpg', { type: 'image/jpeg' });
const result = await uploadFile(
'eyJhbGciOiJIUzI1NiIs...',
's3',
file
);
console.log('Uploaded file:', result);
} catch (error) {
console.error('Error:', error.message);
}
func uploadFile(
accessToken: String,
provider: String,
fileURL: URL
) async throws -> File {
let filename = fileURL.lastPathComponent
let data = try Data(contentsOf: fileURL)
let contentType = UTType(filenameExtension: fileURL.pathExtension)?.preferredMIMEType ?? "application/octet-stream"
var urlRequest = URLRequest(url: URL(string: "https://api.tktchurch.com/v1/files/provider/\(provider)/upload")!)
urlRequest.httpMethod = "POST"
urlRequest.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")
urlRequest.setValue(contentType, forHTTPHeaderField: "Content-Type")
urlRequest.setValue("attachment; filename=\"\(filename)\"", forHTTPHeaderField: "Content-Disposition")
urlRequest.httpBody = data
let (responseData, response) = try await URLSession.shared.data(for: urlRequest)
guard let httpResponse = response as? HTTPURLResponse else {
throw URLError(.badServerResponse)
}
if httpResponse.statusCode != 200 {
throw URLError(.badServerResponse)
}
return try JSONDecoder().decode(File.self, from: responseData)
}
// Usage
do {
let fileURL = URL(fileURLWithPath: "/path/to/example.jpg")
let result = try await uploadFile(
accessToken: "eyJhbGciOiJIUzI1NiIs...",
provider: "s3",
fileURL: fileURL
)
print("Uploaded file:", result)
} catch {
print("Error:", error)
}
suspend fun uploadFile(
accessToken: String,
provider: String,
file: File
): FileResponse {
val requestBody = RequestBody.create(
MediaType.parse(getMimeType(file) ?: "application/octet-stream"),
file.readBytes()
)
val request = Request.Builder()
.url("https://api.tktchurch.com/v1/files/provider/$provider/upload")
.post(requestBody)
.header("Authorization", "Bearer $accessToken")
.header("Content-Type", getMimeType(file) ?: "application/octet-stream")
.header("Content-Disposition", "attachment; filename=\"${file.name}\"")
.build()
return withContext(Dispatchers.IO) {
client.newCall(request).execute().use { response ->
if (!response.isSuccessful) {
throw IOException("Unexpected response ${response.code}")
}
val body = response.body?.string() ?: throw IOException("Empty response")
Json.decodeFromString<FileResponse>(body)
}
}
}
private fun getMimeType(file: File): String? {
return URLConnection.guessContentTypeFromName(file.name)
}
// Usage
try {
val file = File("/path/to/example.jpg")
val result = uploadFile(
"eyJhbGciOiJIUzI1NiIs...",
"s3",
file
)
println("Uploaded file: $result")
} catch (e: Exception) {
println("Error: ${e.message}")
}
interface FileResponse {
id: string;
originalName: string;
url: string;
key: string;
contentType: string;
size: number;
provider: 's3' | 'local';
providerMetadata?: Record<string, string>;
uploadedBy: string;
createdAt: string;
updatedAt: string;
}
const uploadFile = async (
accessToken: string,
provider: 's3' | 'local',
file: File
): Promise<FileResponse> => {
try {
const response = await axios.post<FileResponse>(
`https://api.tktchurch.com/v1/files/provider/${provider}/upload`,
file,
{
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': file.type,
'Content-Disposition': `attachment; filename="${file.name}"`
},
}
);
return response.data;
} catch (error) {
if (axios.isAxiosError(error)) {
throw new Error(error.response?.data?.reason || 'Failed to upload file');
}
throw error;
}
};
// Usage
try {
const file = new File(['...'], 'example.jpg', { type: 'image/jpeg' });
const result = await uploadFile(
'eyJhbGciOiJIUzI1NiIs...',
's3',
file
);
console.log('Uploaded file:', result);
} catch (error) {
console.error('Error:', error.message);
}
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"originalName": "example.jpg",
"url": "https://storage.example.com/uploads/abc123.jpg",
"key": "uploads/abc123.jpg",
"contentType": "image/jpeg",
"size": 1048576,
"provider": "s3",
"providerMetadata": {
"bucket": "my-bucket",
"region": "us-east-1"
},
"uploadedBy": "123e4567-e89b-12d3-a456-426614174001",
"createdAt": "2024-01-20T15:00:00Z",
"updatedAt": "2024-01-20T15:00:00Z"
}
{
"error": {
"status": 400,
"reason": "Invalid provider specified"
}
}
{
"error": {
"status": 401,
"reason": "Invalid or expired access token"
}
}
{
"error": {
"status": 403,
"reason": "Missing required permission: uploadFiles"
}
}
{
"error": {
"status": 413,
"reason": "File size exceeds limit of 10MB"
}
}
Files
Upload File
Upload a file to the specified storage provider
POST
/
files
/
provider
/
{provider}
/
upload
curl -X POST "https://api.tktchurch.com/v1/files/provider/s3/upload" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
-H "Content-Type: image/jpeg" \
-H "Content-Disposition: attachment; filename=\"example.jpg\"" \
--data-binary "@/path/to/example.jpg"
const uploadFile = async (accessToken, provider, file) => {
const formData = new FormData();
formData.append('file', file);
const response = await fetch(
`https://api.tktchurch.com/v1/files/provider/${provider}/upload`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Disposition': `attachment; filename="${file.name}"`
},
body: file
}
);
if (!response.ok) {
const error = await response.json();
throw new Error(error.reason || 'Failed to upload file');
}
return response.json();
};
// Usage
try {
const file = new File(['...'], 'example.jpg', { type: 'image/jpeg' });
const result = await uploadFile(
'eyJhbGciOiJIUzI1NiIs...',
's3',
file
);
console.log('Uploaded file:', result);
} catch (error) {
console.error('Error:', error.message);
}
func uploadFile(
accessToken: String,
provider: String,
fileURL: URL
) async throws -> File {
let filename = fileURL.lastPathComponent
let data = try Data(contentsOf: fileURL)
let contentType = UTType(filenameExtension: fileURL.pathExtension)?.preferredMIMEType ?? "application/octet-stream"
var urlRequest = URLRequest(url: URL(string: "https://api.tktchurch.com/v1/files/provider/\(provider)/upload")!)
urlRequest.httpMethod = "POST"
urlRequest.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")
urlRequest.setValue(contentType, forHTTPHeaderField: "Content-Type")
urlRequest.setValue("attachment; filename=\"\(filename)\"", forHTTPHeaderField: "Content-Disposition")
urlRequest.httpBody = data
let (responseData, response) = try await URLSession.shared.data(for: urlRequest)
guard let httpResponse = response as? HTTPURLResponse else {
throw URLError(.badServerResponse)
}
if httpResponse.statusCode != 200 {
throw URLError(.badServerResponse)
}
return try JSONDecoder().decode(File.self, from: responseData)
}
// Usage
do {
let fileURL = URL(fileURLWithPath: "/path/to/example.jpg")
let result = try await uploadFile(
accessToken: "eyJhbGciOiJIUzI1NiIs...",
provider: "s3",
fileURL: fileURL
)
print("Uploaded file:", result)
} catch {
print("Error:", error)
}
suspend fun uploadFile(
accessToken: String,
provider: String,
file: File
): FileResponse {
val requestBody = RequestBody.create(
MediaType.parse(getMimeType(file) ?: "application/octet-stream"),
file.readBytes()
)
val request = Request.Builder()
.url("https://api.tktchurch.com/v1/files/provider/$provider/upload")
.post(requestBody)
.header("Authorization", "Bearer $accessToken")
.header("Content-Type", getMimeType(file) ?: "application/octet-stream")
.header("Content-Disposition", "attachment; filename=\"${file.name}\"")
.build()
return withContext(Dispatchers.IO) {
client.newCall(request).execute().use { response ->
if (!response.isSuccessful) {
throw IOException("Unexpected response ${response.code}")
}
val body = response.body?.string() ?: throw IOException("Empty response")
Json.decodeFromString<FileResponse>(body)
}
}
}
private fun getMimeType(file: File): String? {
return URLConnection.guessContentTypeFromName(file.name)
}
// Usage
try {
val file = File("/path/to/example.jpg")
val result = uploadFile(
"eyJhbGciOiJIUzI1NiIs...",
"s3",
file
)
println("Uploaded file: $result")
} catch (e: Exception) {
println("Error: ${e.message}")
}
interface FileResponse {
id: string;
originalName: string;
url: string;
key: string;
contentType: string;
size: number;
provider: 's3' | 'local';
providerMetadata?: Record<string, string>;
uploadedBy: string;
createdAt: string;
updatedAt: string;
}
const uploadFile = async (
accessToken: string,
provider: 's3' | 'local',
file: File
): Promise<FileResponse> => {
try {
const response = await axios.post<FileResponse>(
`https://api.tktchurch.com/v1/files/provider/${provider}/upload`,
file,
{
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': file.type,
'Content-Disposition': `attachment; filename="${file.name}"`
},
}
);
return response.data;
} catch (error) {
if (axios.isAxiosError(error)) {
throw new Error(error.response?.data?.reason || 'Failed to upload file');
}
throw error;
}
};
// Usage
try {
const file = new File(['...'], 'example.jpg', { type: 'image/jpeg' });
const result = await uploadFile(
'eyJhbGciOiJIUzI1NiIs...',
's3',
file
);
console.log('Uploaded file:', result);
} catch (error) {
console.error('Error:', error.message);
}
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"originalName": "example.jpg",
"url": "https://storage.example.com/uploads/abc123.jpg",
"key": "uploads/abc123.jpg",
"contentType": "image/jpeg",
"size": 1048576,
"provider": "s3",
"providerMetadata": {
"bucket": "my-bucket",
"region": "us-east-1"
},
"uploadedBy": "123e4567-e89b-12d3-a456-426614174001",
"createdAt": "2024-01-20T15:00:00Z",
"updatedAt": "2024-01-20T15:00:00Z"
}
{
"error": {
"status": 400,
"reason": "Invalid provider specified"
}
}
{
"error": {
"status": 401,
"reason": "Invalid or expired access token"
}
}
{
"error": {
"status": 403,
"reason": "Missing required permission: uploadFiles"
}
}
{
"error": {
"status": 413,
"reason": "File size exceeds limit of 10MB"
}
}
This endpoint requires authentication and the
uploadFiles permission.
The maximum file size is 10MB.Path Parameters
string
required
The storage provider to use. One of:
s3: Amazon S3 storagelocal: Local file storage
Request Headers
string
required
The MIME type of the file being uploaded
string
required
Must include the filename parameter, e.g.
attachment; filename="example.jpg"Request Body
The request body should contain the raw file data.Response
string
File’s unique identifier (UUID)
string
Original filename
string
URL to access the file
string
Storage key/path of the file
string
MIME type of the file
integer
File size in bytes
string
Storage provider used (s3 or local)
object
Provider-specific metadata
string
UUID of the user who uploaded the file
string
Upload timestamp in ISO 8601 format
string
Last update timestamp in ISO 8601 format
Error Responses
object
Common error cases:
- 400 Bad Request: Invalid provider or missing filename
- 401 Unauthorized: Missing or invalid access token
- 403 Forbidden: Missing required permission
- 413 Payload Too Large: File exceeds size limit
curl -X POST "https://api.tktchurch.com/v1/files/provider/s3/upload" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
-H "Content-Type: image/jpeg" \
-H "Content-Disposition: attachment; filename=\"example.jpg\"" \
--data-binary "@/path/to/example.jpg"
const uploadFile = async (accessToken, provider, file) => {
const formData = new FormData();
formData.append('file', file);
const response = await fetch(
`https://api.tktchurch.com/v1/files/provider/${provider}/upload`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Disposition': `attachment; filename="${file.name}"`
},
body: file
}
);
if (!response.ok) {
const error = await response.json();
throw new Error(error.reason || 'Failed to upload file');
}
return response.json();
};
// Usage
try {
const file = new File(['...'], 'example.jpg', { type: 'image/jpeg' });
const result = await uploadFile(
'eyJhbGciOiJIUzI1NiIs...',
's3',
file
);
console.log('Uploaded file:', result);
} catch (error) {
console.error('Error:', error.message);
}
func uploadFile(
accessToken: String,
provider: String,
fileURL: URL
) async throws -> File {
let filename = fileURL.lastPathComponent
let data = try Data(contentsOf: fileURL)
let contentType = UTType(filenameExtension: fileURL.pathExtension)?.preferredMIMEType ?? "application/octet-stream"
var urlRequest = URLRequest(url: URL(string: "https://api.tktchurch.com/v1/files/provider/\(provider)/upload")!)
urlRequest.httpMethod = "POST"
urlRequest.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")
urlRequest.setValue(contentType, forHTTPHeaderField: "Content-Type")
urlRequest.setValue("attachment; filename=\"\(filename)\"", forHTTPHeaderField: "Content-Disposition")
urlRequest.httpBody = data
let (responseData, response) = try await URLSession.shared.data(for: urlRequest)
guard let httpResponse = response as? HTTPURLResponse else {
throw URLError(.badServerResponse)
}
if httpResponse.statusCode != 200 {
throw URLError(.badServerResponse)
}
return try JSONDecoder().decode(File.self, from: responseData)
}
// Usage
do {
let fileURL = URL(fileURLWithPath: "/path/to/example.jpg")
let result = try await uploadFile(
accessToken: "eyJhbGciOiJIUzI1NiIs...",
provider: "s3",
fileURL: fileURL
)
print("Uploaded file:", result)
} catch {
print("Error:", error)
}
suspend fun uploadFile(
accessToken: String,
provider: String,
file: File
): FileResponse {
val requestBody = RequestBody.create(
MediaType.parse(getMimeType(file) ?: "application/octet-stream"),
file.readBytes()
)
val request = Request.Builder()
.url("https://api.tktchurch.com/v1/files/provider/$provider/upload")
.post(requestBody)
.header("Authorization", "Bearer $accessToken")
.header("Content-Type", getMimeType(file) ?: "application/octet-stream")
.header("Content-Disposition", "attachment; filename=\"${file.name}\"")
.build()
return withContext(Dispatchers.IO) {
client.newCall(request).execute().use { response ->
if (!response.isSuccessful) {
throw IOException("Unexpected response ${response.code}")
}
val body = response.body?.string() ?: throw IOException("Empty response")
Json.decodeFromString<FileResponse>(body)
}
}
}
private fun getMimeType(file: File): String? {
return URLConnection.guessContentTypeFromName(file.name)
}
// Usage
try {
val file = File("/path/to/example.jpg")
val result = uploadFile(
"eyJhbGciOiJIUzI1NiIs...",
"s3",
file
)
println("Uploaded file: $result")
} catch (e: Exception) {
println("Error: ${e.message}")
}
interface FileResponse {
id: string;
originalName: string;
url: string;
key: string;
contentType: string;
size: number;
provider: 's3' | 'local';
providerMetadata?: Record<string, string>;
uploadedBy: string;
createdAt: string;
updatedAt: string;
}
const uploadFile = async (
accessToken: string,
provider: 's3' | 'local',
file: File
): Promise<FileResponse> => {
try {
const response = await axios.post<FileResponse>(
`https://api.tktchurch.com/v1/files/provider/${provider}/upload`,
file,
{
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': file.type,
'Content-Disposition': `attachment; filename="${file.name}"`
},
}
);
return response.data;
} catch (error) {
if (axios.isAxiosError(error)) {
throw new Error(error.response?.data?.reason || 'Failed to upload file');
}
throw error;
}
};
// Usage
try {
const file = new File(['...'], 'example.jpg', { type: 'image/jpeg' });
const result = await uploadFile(
'eyJhbGciOiJIUzI1NiIs...',
's3',
file
);
console.log('Uploaded file:', result);
} catch (error) {
console.error('Error:', error.message);
}
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"originalName": "example.jpg",
"url": "https://storage.example.com/uploads/abc123.jpg",
"key": "uploads/abc123.jpg",
"contentType": "image/jpeg",
"size": 1048576,
"provider": "s3",
"providerMetadata": {
"bucket": "my-bucket",
"region": "us-east-1"
},
"uploadedBy": "123e4567-e89b-12d3-a456-426614174001",
"createdAt": "2024-01-20T15:00:00Z",
"updatedAt": "2024-01-20T15:00:00Z"
}
{
"error": {
"status": 400,
"reason": "Invalid provider specified"
}
}
{
"error": {
"status": 401,
"reason": "Invalid or expired access token"
}
}
{
"error": {
"status": 403,
"reason": "Missing required permission: uploadFiles"
}
}
{
"error": {
"status": 413,
"reason": "File size exceeds limit of 10MB"
}
}
