curl -X PUT "https://api.tktchurch.com/v1/newsletters/123e4567-e89b-12d3-a456-426614174000" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{
"title": "Updated January Church Updates",
"content": "Welcome to our updated newsletter...",
"imageId": "file-789",
"pdfId": "file-012",
"status": "published",
"publishDate": "2024-01-01T12:00:00Z"
}'
const updateNewsletter = async (accessToken, newsletterId, updates) => {
const response = await fetch(
`https://api.tktchurch.com/v1/newsletters/${newsletterId}`,
{
method: 'PUT',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(updates)
}
);
if (!response.ok) {
const error = await response.json();
throw new Error(error.error.reason);
}
return response.json();
};
// Usage
try {
const newsletter = await updateNewsletter(
'eyJhbGciOiJIUzI1NiIs...',
'123e4567-e89b-12d3-a456-426614174000',
{
title: 'Updated January Church Updates',
content: 'Welcome to our updated newsletter...',
imageId: 'file-789',
pdfId: 'file-012',
status: 'published',
publishDate: '2024-01-01T12:00:00Z'
}
);
console.log('Updated newsletter:', newsletter);
} catch (error) {
console.error('Failed to update newsletter:', error.message);
}
struct UpdateNewsletterRequest: Codable {
let title: String?
let content: String?
let imageId: String?
let imageUrl: String?
let pdfId: String?
let pdfUrl: String?
let status: String?
let publishDate: Date?
}
func updateNewsletter(
accessToken: String,
newsletterId: UUID,
updates: UpdateNewsletterRequest
) async throws -> Newsletter {
var urlRequest = URLRequest(url: URL(string: "https://api.tktchurch.com/v1/newsletters/\(newsletterId)")!)
urlRequest.httpMethod = "PUT"
urlRequest.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")
urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
let encoder = JSONEncoder()
encoder.dateEncodingStrategy = .iso8601
urlRequest.httpBody = try encoder.encode(updates)
let (data, response) = try await URLSession.shared.data(for: urlRequest)
guard let httpResponse = response as? HTTPURLResponse else {
throw URLError(.badServerResponse)
}
if httpResponse.statusCode != 200 {
let error = try JSONDecoder().decode(ErrorResponse.self, from: data)
throw error
}
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
return try decoder.decode(Newsletter.self, from: data)
}
// Usage
do {
let request = UpdateNewsletterRequest(
title: "Updated January Church Updates",
content: "Welcome to our updated newsletter...",
imageId: "file-789",
imageUrl: nil,
pdfId: "file-012",
pdfUrl: nil,
status: "published",
publishDate: ISO8601DateFormatter().date(from: "2024-01-01T12:00:00Z")
)
let newsletter = try await updateNewsletter(
accessToken: "eyJhbGciOiJIUzI1NiIs...",
newsletterId: UUID(uuidString: "123e4567-e89b-12d3-a456-426614174000")!,
updates: request
)
print("Updated newsletter:", newsletter)
} catch {
print("Failed to update newsletter:", error.localizedDescription)
}
data class UpdateNewsletterRequest(
val title: String? = null,
val content: String? = null,
val imageId: String? = null,
val imageUrl: String? = null,
val pdfId: String? = null,
val pdfUrl: String? = null,
val status: String? = null,
val publishDate: String? = null
)
class NewsletterService(private val client: OkHttpClient) {
suspend fun updateNewsletter(
accessToken: String,
newsletterId: String,
updates: UpdateNewsletterRequest
): Newsletter {
val requestBody = updates.toJson()
.toRequestBody("application/json".toMediaType())
val request = Request.Builder()
.url("https://api.tktchurch.com/v1/newsletters/$newsletterId")
.put(requestBody)
.header("Authorization", "Bearer $accessToken")
.build()
client.newCall(request).execute().use { response ->
if (!response.isSuccessful) {
val error = response.body?.string()?.fromJson<ErrorResponse>()
throw Exception(error?.reason ?: "Failed to update newsletter")
}
return response.body?.string()?.fromJson<Newsletter>()
?: throw Exception("Empty response")
}
}
}
// Usage
try {
val request = UpdateNewsletterRequest(
title = "Updated January Church Updates",
content = "Welcome to our updated newsletter...",
imageId = "file-789",
pdfId = "file-012",
status = "published",
publishDate = "2024-01-01T12:00:00Z"
)
val newsletter = newsletterService.updateNewsletter(
"eyJhbGciOiJIUzI1NiIs...",
"123e4567-e89b-12d3-a456-426614174000",
request
)
println("Updated newsletter: $newsletter")
} catch (e: Exception) {
println("Failed to update newsletter: ${e.message}")
}
import axios from 'axios';
interface UpdateNewsletterRequest {
title?: string;
content?: string;
imageId?: string;
imageUrl?: string;
pdfId?: string;
pdfUrl?: string;
status?: 'draft' | 'scheduled' | 'published' | 'archived';
publishDate?: string;
}
const updateNewsletter = async (
accessToken: string,
newsletterId: string,
updates: UpdateNewsletterRequest
): Promise<Newsletter> => {
try {
const response = await axios.put(
`https://api.tktchurch.com/v1/newsletters/${newsletterId}`,
updates,
{
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
}
);
return response.data;
} catch (error) {
if (axios.isAxiosError(error)) {
throw new Error(error.response?.data?.error?.reason || 'Failed to update newsletter');
}
throw error;
}
};
// Usage
try {
const newsletter = await updateNewsletter(
'eyJhbGciOiJIUzI1NiIs...',
'123e4567-e89b-12d3-a456-426614174000',
{
title: 'Updated January Church Updates',
content: 'Welcome to our updated newsletter...',
imageId: 'file-789',
pdfId: 'file-012',
status: 'published',
publishDate: '2024-01-01T12:00:00Z'
}
);
console.log('Updated newsletter:', newsletter);
} catch (error) {
console.error('Failed to update newsletter:', error.message);
}
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"title": "Updated January Church Updates",
"content": "Welcome to our updated newsletter...",
"image": {
"id": "file-789",
"url": "https://cdn.tktchurch.com/files/updated-image.jpg"
},
"imageUrl": null,
"pdf": {
"id": "file-012",
"url": "https://cdn.tktchurch.com/files/updated.pdf"
},
"pdfUrl": null,
"hasPdf": true,
"status": "published",
"publishDate": "2024-01-01T12:00:00Z",
"recipientCount": 150,
"createdAt": "2023-12-30T15:00:00Z",
"updatedAt": "2023-12-31T10:30:00Z",
"createdBy": "user-123e4567-e89b-12d3-a456-426614174000"
}
{
"error": {
"status": 400,
"reason": "Invalid newsletter ID format"
}
}
{
"error": {
"status": 401,
"reason": "Invalid or expired access token"
}
}
{
"error": {
"status": 403,
"reason": "Missing required permission: updateNewsletter"
}
}
{
"error": {
"status": 404,
"reason": "Newsletter not found"
}
}
Newsletters
Update Newsletter
Update an existing newsletter
PUT
/
newsletters
/
{newsletterId}
curl -X PUT "https://api.tktchurch.com/v1/newsletters/123e4567-e89b-12d3-a456-426614174000" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{
"title": "Updated January Church Updates",
"content": "Welcome to our updated newsletter...",
"imageId": "file-789",
"pdfId": "file-012",
"status": "published",
"publishDate": "2024-01-01T12:00:00Z"
}'
const updateNewsletter = async (accessToken, newsletterId, updates) => {
const response = await fetch(
`https://api.tktchurch.com/v1/newsletters/${newsletterId}`,
{
method: 'PUT',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(updates)
}
);
if (!response.ok) {
const error = await response.json();
throw new Error(error.error.reason);
}
return response.json();
};
// Usage
try {
const newsletter = await updateNewsletter(
'eyJhbGciOiJIUzI1NiIs...',
'123e4567-e89b-12d3-a456-426614174000',
{
title: 'Updated January Church Updates',
content: 'Welcome to our updated newsletter...',
imageId: 'file-789',
pdfId: 'file-012',
status: 'published',
publishDate: '2024-01-01T12:00:00Z'
}
);
console.log('Updated newsletter:', newsletter);
} catch (error) {
console.error('Failed to update newsletter:', error.message);
}
struct UpdateNewsletterRequest: Codable {
let title: String?
let content: String?
let imageId: String?
let imageUrl: String?
let pdfId: String?
let pdfUrl: String?
let status: String?
let publishDate: Date?
}
func updateNewsletter(
accessToken: String,
newsletterId: UUID,
updates: UpdateNewsletterRequest
) async throws -> Newsletter {
var urlRequest = URLRequest(url: URL(string: "https://api.tktchurch.com/v1/newsletters/\(newsletterId)")!)
urlRequest.httpMethod = "PUT"
urlRequest.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")
urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
let encoder = JSONEncoder()
encoder.dateEncodingStrategy = .iso8601
urlRequest.httpBody = try encoder.encode(updates)
let (data, response) = try await URLSession.shared.data(for: urlRequest)
guard let httpResponse = response as? HTTPURLResponse else {
throw URLError(.badServerResponse)
}
if httpResponse.statusCode != 200 {
let error = try JSONDecoder().decode(ErrorResponse.self, from: data)
throw error
}
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
return try decoder.decode(Newsletter.self, from: data)
}
// Usage
do {
let request = UpdateNewsletterRequest(
title: "Updated January Church Updates",
content: "Welcome to our updated newsletter...",
imageId: "file-789",
imageUrl: nil,
pdfId: "file-012",
pdfUrl: nil,
status: "published",
publishDate: ISO8601DateFormatter().date(from: "2024-01-01T12:00:00Z")
)
let newsletter = try await updateNewsletter(
accessToken: "eyJhbGciOiJIUzI1NiIs...",
newsletterId: UUID(uuidString: "123e4567-e89b-12d3-a456-426614174000")!,
updates: request
)
print("Updated newsletter:", newsletter)
} catch {
print("Failed to update newsletter:", error.localizedDescription)
}
data class UpdateNewsletterRequest(
val title: String? = null,
val content: String? = null,
val imageId: String? = null,
val imageUrl: String? = null,
val pdfId: String? = null,
val pdfUrl: String? = null,
val status: String? = null,
val publishDate: String? = null
)
class NewsletterService(private val client: OkHttpClient) {
suspend fun updateNewsletter(
accessToken: String,
newsletterId: String,
updates: UpdateNewsletterRequest
): Newsletter {
val requestBody = updates.toJson()
.toRequestBody("application/json".toMediaType())
val request = Request.Builder()
.url("https://api.tktchurch.com/v1/newsletters/$newsletterId")
.put(requestBody)
.header("Authorization", "Bearer $accessToken")
.build()
client.newCall(request).execute().use { response ->
if (!response.isSuccessful) {
val error = response.body?.string()?.fromJson<ErrorResponse>()
throw Exception(error?.reason ?: "Failed to update newsletter")
}
return response.body?.string()?.fromJson<Newsletter>()
?: throw Exception("Empty response")
}
}
}
// Usage
try {
val request = UpdateNewsletterRequest(
title = "Updated January Church Updates",
content = "Welcome to our updated newsletter...",
imageId = "file-789",
pdfId = "file-012",
status = "published",
publishDate = "2024-01-01T12:00:00Z"
)
val newsletter = newsletterService.updateNewsletter(
"eyJhbGciOiJIUzI1NiIs...",
"123e4567-e89b-12d3-a456-426614174000",
request
)
println("Updated newsletter: $newsletter")
} catch (e: Exception) {
println("Failed to update newsletter: ${e.message}")
}
import axios from 'axios';
interface UpdateNewsletterRequest {
title?: string;
content?: string;
imageId?: string;
imageUrl?: string;
pdfId?: string;
pdfUrl?: string;
status?: 'draft' | 'scheduled' | 'published' | 'archived';
publishDate?: string;
}
const updateNewsletter = async (
accessToken: string,
newsletterId: string,
updates: UpdateNewsletterRequest
): Promise<Newsletter> => {
try {
const response = await axios.put(
`https://api.tktchurch.com/v1/newsletters/${newsletterId}`,
updates,
{
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
}
);
return response.data;
} catch (error) {
if (axios.isAxiosError(error)) {
throw new Error(error.response?.data?.error?.reason || 'Failed to update newsletter');
}
throw error;
}
};
// Usage
try {
const newsletter = await updateNewsletter(
'eyJhbGciOiJIUzI1NiIs...',
'123e4567-e89b-12d3-a456-426614174000',
{
title: 'Updated January Church Updates',
content: 'Welcome to our updated newsletter...',
imageId: 'file-789',
pdfId: 'file-012',
status: 'published',
publishDate: '2024-01-01T12:00:00Z'
}
);
console.log('Updated newsletter:', newsletter);
} catch (error) {
console.error('Failed to update newsletter:', error.message);
}
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"title": "Updated January Church Updates",
"content": "Welcome to our updated newsletter...",
"image": {
"id": "file-789",
"url": "https://cdn.tktchurch.com/files/updated-image.jpg"
},
"imageUrl": null,
"pdf": {
"id": "file-012",
"url": "https://cdn.tktchurch.com/files/updated.pdf"
},
"pdfUrl": null,
"hasPdf": true,
"status": "published",
"publishDate": "2024-01-01T12:00:00Z",
"recipientCount": 150,
"createdAt": "2023-12-30T15:00:00Z",
"updatedAt": "2023-12-31T10:30:00Z",
"createdBy": "user-123e4567-e89b-12d3-a456-426614174000"
}
{
"error": {
"status": 400,
"reason": "Invalid newsletter ID format"
}
}
{
"error": {
"status": 401,
"reason": "Invalid or expired access token"
}
}
{
"error": {
"status": 403,
"reason": "Missing required permission: updateNewsletter"
}
}
{
"error": {
"status": 404,
"reason": "Newsletter not found"
}
}
This endpoint requires authentication and the
updateNewsletter permission.Path Parameters
string
required
The UUID of the newsletter to update
Request Body
string
Newsletter title
string
Newsletter content
string
ID of the uploaded image file
string
External image URL if not using uploaded file
string
ID of the uploaded PDF file
string
External PDF URL if not using uploaded file
string
Newsletter status. One of:
draft, scheduled, published, archivedstring
Scheduled publication date (ISO 8601)
Response
string
Unique identifier for the newsletter (UUID)
string
Newsletter title
string
Newsletter content
string
External image URL if not using uploaded file
string
External PDF URL if not using uploaded file
boolean
Whether the newsletter has an associated PDF
string
Newsletter status. One of:
draft, scheduled, published, archivedstring
Scheduled or actual publication date (ISO 8601)
integer
Number of times the newsletter has been viewed/received
string
Creation timestamp (ISO 8601)
string
Last update timestamp (ISO 8601)
string
UUID of the user who created the newsletter
Error Responses
object
Common error cases:
- 400 Bad Request: Invalid newsletter ID format or validation error
- 401 Unauthorized: Missing or invalid access token
- 403 Forbidden: Missing required permission
- 404 Not Found: Newsletter not found
curl -X PUT "https://api.tktchurch.com/v1/newsletters/123e4567-e89b-12d3-a456-426614174000" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{
"title": "Updated January Church Updates",
"content": "Welcome to our updated newsletter...",
"imageId": "file-789",
"pdfId": "file-012",
"status": "published",
"publishDate": "2024-01-01T12:00:00Z"
}'
const updateNewsletter = async (accessToken, newsletterId, updates) => {
const response = await fetch(
`https://api.tktchurch.com/v1/newsletters/${newsletterId}`,
{
method: 'PUT',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(updates)
}
);
if (!response.ok) {
const error = await response.json();
throw new Error(error.error.reason);
}
return response.json();
};
// Usage
try {
const newsletter = await updateNewsletter(
'eyJhbGciOiJIUzI1NiIs...',
'123e4567-e89b-12d3-a456-426614174000',
{
title: 'Updated January Church Updates',
content: 'Welcome to our updated newsletter...',
imageId: 'file-789',
pdfId: 'file-012',
status: 'published',
publishDate: '2024-01-01T12:00:00Z'
}
);
console.log('Updated newsletter:', newsletter);
} catch (error) {
console.error('Failed to update newsletter:', error.message);
}
struct UpdateNewsletterRequest: Codable {
let title: String?
let content: String?
let imageId: String?
let imageUrl: String?
let pdfId: String?
let pdfUrl: String?
let status: String?
let publishDate: Date?
}
func updateNewsletter(
accessToken: String,
newsletterId: UUID,
updates: UpdateNewsletterRequest
) async throws -> Newsletter {
var urlRequest = URLRequest(url: URL(string: "https://api.tktchurch.com/v1/newsletters/\(newsletterId)")!)
urlRequest.httpMethod = "PUT"
urlRequest.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")
urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
let encoder = JSONEncoder()
encoder.dateEncodingStrategy = .iso8601
urlRequest.httpBody = try encoder.encode(updates)
let (data, response) = try await URLSession.shared.data(for: urlRequest)
guard let httpResponse = response as? HTTPURLResponse else {
throw URLError(.badServerResponse)
}
if httpResponse.statusCode != 200 {
let error = try JSONDecoder().decode(ErrorResponse.self, from: data)
throw error
}
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
return try decoder.decode(Newsletter.self, from: data)
}
// Usage
do {
let request = UpdateNewsletterRequest(
title: "Updated January Church Updates",
content: "Welcome to our updated newsletter...",
imageId: "file-789",
imageUrl: nil,
pdfId: "file-012",
pdfUrl: nil,
status: "published",
publishDate: ISO8601DateFormatter().date(from: "2024-01-01T12:00:00Z")
)
let newsletter = try await updateNewsletter(
accessToken: "eyJhbGciOiJIUzI1NiIs...",
newsletterId: UUID(uuidString: "123e4567-e89b-12d3-a456-426614174000")!,
updates: request
)
print("Updated newsletter:", newsletter)
} catch {
print("Failed to update newsletter:", error.localizedDescription)
}
data class UpdateNewsletterRequest(
val title: String? = null,
val content: String? = null,
val imageId: String? = null,
val imageUrl: String? = null,
val pdfId: String? = null,
val pdfUrl: String? = null,
val status: String? = null,
val publishDate: String? = null
)
class NewsletterService(private val client: OkHttpClient) {
suspend fun updateNewsletter(
accessToken: String,
newsletterId: String,
updates: UpdateNewsletterRequest
): Newsletter {
val requestBody = updates.toJson()
.toRequestBody("application/json".toMediaType())
val request = Request.Builder()
.url("https://api.tktchurch.com/v1/newsletters/$newsletterId")
.put(requestBody)
.header("Authorization", "Bearer $accessToken")
.build()
client.newCall(request).execute().use { response ->
if (!response.isSuccessful) {
val error = response.body?.string()?.fromJson<ErrorResponse>()
throw Exception(error?.reason ?: "Failed to update newsletter")
}
return response.body?.string()?.fromJson<Newsletter>()
?: throw Exception("Empty response")
}
}
}
// Usage
try {
val request = UpdateNewsletterRequest(
title = "Updated January Church Updates",
content = "Welcome to our updated newsletter...",
imageId = "file-789",
pdfId = "file-012",
status = "published",
publishDate = "2024-01-01T12:00:00Z"
)
val newsletter = newsletterService.updateNewsletter(
"eyJhbGciOiJIUzI1NiIs...",
"123e4567-e89b-12d3-a456-426614174000",
request
)
println("Updated newsletter: $newsletter")
} catch (e: Exception) {
println("Failed to update newsletter: ${e.message}")
}
import axios from 'axios';
interface UpdateNewsletterRequest {
title?: string;
content?: string;
imageId?: string;
imageUrl?: string;
pdfId?: string;
pdfUrl?: string;
status?: 'draft' | 'scheduled' | 'published' | 'archived';
publishDate?: string;
}
const updateNewsletter = async (
accessToken: string,
newsletterId: string,
updates: UpdateNewsletterRequest
): Promise<Newsletter> => {
try {
const response = await axios.put(
`https://api.tktchurch.com/v1/newsletters/${newsletterId}`,
updates,
{
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
}
);
return response.data;
} catch (error) {
if (axios.isAxiosError(error)) {
throw new Error(error.response?.data?.error?.reason || 'Failed to update newsletter');
}
throw error;
}
};
// Usage
try {
const newsletter = await updateNewsletter(
'eyJhbGciOiJIUzI1NiIs...',
'123e4567-e89b-12d3-a456-426614174000',
{
title: 'Updated January Church Updates',
content: 'Welcome to our updated newsletter...',
imageId: 'file-789',
pdfId: 'file-012',
status: 'published',
publishDate: '2024-01-01T12:00:00Z'
}
);
console.log('Updated newsletter:', newsletter);
} catch (error) {
console.error('Failed to update newsletter:', error.message);
}
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"title": "Updated January Church Updates",
"content": "Welcome to our updated newsletter...",
"image": {
"id": "file-789",
"url": "https://cdn.tktchurch.com/files/updated-image.jpg"
},
"imageUrl": null,
"pdf": {
"id": "file-012",
"url": "https://cdn.tktchurch.com/files/updated.pdf"
},
"pdfUrl": null,
"hasPdf": true,
"status": "published",
"publishDate": "2024-01-01T12:00:00Z",
"recipientCount": 150,
"createdAt": "2023-12-30T15:00:00Z",
"updatedAt": "2023-12-31T10:30:00Z",
"createdBy": "user-123e4567-e89b-12d3-a456-426614174000"
}
{
"error": {
"status": 400,
"reason": "Invalid newsletter ID format"
}
}
{
"error": {
"status": 401,
"reason": "Invalid or expired access token"
}
}
{
"error": {
"status": 403,
"reason": "Missing required permission: updateNewsletter"
}
}
{
"error": {
"status": 404,
"reason": "Newsletter not found"
}
}
