API Documentation
Complete developer guide for integrating beautiful Hindi, Marathi, Gujarati, and English calligraphy generation API. Build applications with professional Devanagari script rendering, customizable fonts, and high-quality image output.
Documentation
Get API Key
Sign up and generate your Free API key for testing
Sign up for free accountMake First Request
Test the API with a simple generation
Generate "नमस्ते" in HindiIntegrate & Build
Add calligraphy makers API to your application
Use SDKs or direct HTTP callsQuick Test Request
curl -X POST "https://api.calligraphymaker.com/api/v2/generate" \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{"text": "नमस्ते", "language": "hindi", "fontStyle": "calligraphy", "imageFormat": "png"}'Test the Calligraphy API with different parameters and see the exact code needed for your implementation.
Demo Mode
This is an interactive demo interface. To see actual generated calligraphy, sign up for a free API key and use the real endpoint.
API Key Authentication
All API requests require authentication using an API key sent in the request header:
x-api-key: your_api_key_hereAPI Key Permissions
CALLIGRAPHY_GENERATION
Basic text to calligraphy generation
BATCH_PROCESSING
Batch generation capabilities
Security Best Practices
- • Never expose API keys in client-side code
- • Use environment variables to store keys securely
- • Rotate API keys regularly
- • Use different keys for development and production
Core Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
text | string | Required | Text to convert to calligraphy |
language | string | Required | Language: "hindi", "marathi", "gujarati", "english" |
fontStyle | string | Optional | Style: "calligraphy", "decorative", "publication" |
fontWeight | string | Optional | Weights: "regular", "light", "bold" |
fontFamily | string | Optional | Specific font family name |
count | number | Optional | Number of generations (1-4, default: 4) |
imageFormat | string | Optional | Output format: "png", "jpg", "webp" (default: png) |
Example Request & Response
Request:
POST /api/v2/generate
Content-Type: application/json
x-api-key: YOUR_API_KEY
{
"text": "नमस्ते दोस्तों",
"language": "hindi",
"fontStyle": "calligraphy",
"count": 3,
"imageFormat": "png"
}Response:
{
"success": true,
"data": {
"generationId": "gen_clp7x8y9z123456789",
"images": [
{
"url": "https://api.calligraphymaker.com/generated/img_001.png",
"cdnUrl": "https://cdn.calligraphymaker.com/img_001.png",
"format": "png",
"size": 245760,
"fontUsed": "AMS-Abhimanyu"
},
{
"url": "https://api.calligraphymaker.com/generated/img_002.png",
"cdnUrl": "https://cdn.calligraphymaker.com/img_002.png",
"format": "png",
"size": 251340,
"fontUsed": "AMS-Chitra"
},
{
"url": "https://api.calligraphymaker.com/generated/img_003.png",
"cdnUrl": "https://cdn.calligraphymaker.com/img_003.png",
"format": "png",
"size": 248920,
"fontUsed": "AMS-Narendra"
}
],
"metadata": {
"text": "नमस्ते दोस्तों",
"language": "hindi",
"processingTime": "1.847s"
},
"creditsUsed": 1,
"remainingCredits": 8499
}
}/api/v2/generateCoreGenerate Calligraphy
Generate beautiful calligraphy images from text
/api/v2/download-svgSVGDownload SVG
Generate downloadable SVG from text and font name
/api/v2/download-imageImageDownload Image
Generate downloadable PNG/JPG images with custom dimensions
/api/v2/webhooksWebhooksGet Webhooks
Retrieve configured webhook settings
/api/v2/webhooksWebhooksConfigure Webhooks
Set up webhook endpoints for events
Generate and download SVG files directly from styled text and font names. Perfect for creating high-quality vector calligraphy with specific font choices.
SVG Download Example
POST /api/v2/download-svg
Content-Type: application/json
x-api-key: YOUR_API_KEY
{
"resultText": "ॐ॒ श॒ांत॒ि",
"fontName": "ams-abhimanyu"
}SVG Download Response
{
"success": true,
"data": {
"resultText": "ॐ॒ श॒ांत॒ि",
"fontFamily": "ams-abhimanyu",
"format": "svg",
"svgBase64": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iODAwIiBoZWlnaHQ9IjYwMCIgdmlld0JveD0iMCAwIDgwMCA2MDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHBhdGggZD0iTTE1MC41MCAxNTAuMzMgTDE2Mi40NSAxNDIuODkgQzE2OC4xMiAxNTYuNzggMTc0LjIzIDE2OC40NSAxODAuODkgMTc3LjkxIEwxOTIuMzMgMTg1LjIzIEMxODguNjcgMTkyLjEyIDE4NC4zNCAxOTcuNTYgMTc5LjIzIDIwMS40NSBaIiBmaWxsPSIjMDAwMDAwIi8+Cjwvc3ZnPg==",
"svgString": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<svg width=\"800\" height=\"600\" viewBox=\"0 0 800 600\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M150.50 150.33 L162.45 142.89 C168.12 156.78 174.23 168.45 180.89 177.91 L192.33 185.23 C188.67 192.12 184.34 197.56 179.23 201.45 Z\" fill=\"#000000\"/>\n</svg>",
"dimensions": {
"width": 800,
"height": 600
}
}
}cURL Command
curl -X POST "https://api.calligraphymaker.com/api/v2/download-svg" \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{
"resultText": "ॐ॒ श॒ांत॒ि",
"fontName": "ams-abhimanyu",
"svgWidth": 800,
"svgHeight": 600,
"fontSize": 48,
"textColor": "#000000",
"backgroundColor": "transparent"
}'Key Features
- • Direct font-to-SVG conversion
- • True vector paths from font glyphs
- • Both base64 and string formats
- • Scalable and font-independent
- • Optimal font sizing
Use Cases
- • Custom calligraphy downloads
- • Print-ready vector files
- • High-quality logos
- • Web graphics without fonts
- • Animation-ready paths
Parameters
Generate and download PNG or JPG images directly from styled text and font names with customizable dimensions, quality, and colors.
Image Download Example
POST /api/v2/download-image
Content-Type: application/json
x-api-key: YOUR_API_KEY
{
"resultText": "नमस्ते दुनिया",
"fontName": "ams-abhimanyu",
"imageWidth": 800,
"imageHeight": 600,
"imageQuality": 90,
"imageFormat": "png",
"backgroundColor": "#ffffff",
"textColor": "#000000"
}Image Download Response
{
"success": true,
"data": {
"resultText": "नमस्ते दुनिया",
"fontName": "ams-abhimanyu",
"format": "png",
"imageBase64": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...",
"dimensions": {
"width": 800,
"height": 600
},
"quality": 90,
"backgroundColor": "#ffffff",
"textColor": "#000000"
}
}cURL Command
curl -X POST "https://api.calligraphymaker.com/api/v2/download-image" \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{
"resultText": "नमस्ते दुनिया",
"fontName": "ams-abhimanyu",
"imageWidth": 800,
"imageHeight": 600,
"imageQuality": 90,
"imageFormat": "png",
"backgroundColor": "#ffffff",
"textColor": "#000000"
}'PNG Format
- • Supports transparency
- • Lossless compression
- • Best for graphics with text
- • Higher file size
JPG Format
- • No transparency support
- • Adjustable quality (1-100)
- • Smaller file size
- • Best for photos/web use
Parameters
Required:
- • resultText (string)
- • fontName (string, sanitized: alphanumeric, hyphen, underscore only)
Optional:
- • imageWidth (100-1200px, default: 800)
- • imageHeight (100-1200px, default: 600)
- • imageQuality (1-100, default: 90)
- • imageFormat (png/jpg, default: png)
- • backgroundColor (hex color, default: #ffffff)
- • textColor (hex color, default: #000000)
Receive real-time notifications about generation completions, downloads, billing events, and more.
Setting Up Webhooks
POST /api/v2/webhooks
Content-Type: application/json
x-api-key: YOUR_API_KEY
{
"url": "https://your-app.com/webhook",
"events": [
"generation.completed",
"svg.downloaded",
"image.downloaded",
"user.credits_low"
],
"secret": "your_webhook_secret_key"
}Available Webhook Events
generation.completedFired when a calligraphy generation is completed successfully
{ generationId, userId, imageUrls, metadata }generation.failedFired when a calligraphy generation fails
{ generationId, userId, error, metadata }svg.downloadedFired when an SVG is generated and downloaded
{ userId, resultText, fontName, svgBase64 }image.downloadedFired when an image is generated and downloaded
{ userId, resultText, fontName, format, dimensions }user.credits_lowFired when user credits fall below threshold
{ userId, creditsRemaining, threshold }user.quota_exceededFired when user exceeds their rate limit
{ userId, plan, requestCount, limit }payment.completedFired when a payment is successfully processed
{ userId, orderId, amount, plan }Webhook Signature Verification
// Webhook signature verification (Node.js)
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}
// Express.js webhook handler
app.post('/webhook', express.raw({type: 'application/json'}), (req, res) => {
const signature = req.headers['x-calligraphy-signature'];
const payload = req.body;
if (!verifyWebhookSignature(payload, signature, process.env.WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
const event = JSON.parse(payload);
console.log('Received event:', event.type);
res.status(200).send('OK');
});Webhook Best Practices
- • Always verify webhook signatures
- • Implement idempotency for duplicate events
- • Return HTTP 200 status for successful processing
- • Use HTTPS endpoints for security
- • Handle timeouts and retries gracefully
Manage user subscriptions, track usage, and handle billing events programmatically.
Get Subscription Plans
GET /api/v2/subscriptions/plans
x-api-key: YOUR_API_KEY
Response:
{
"success": true,
"data": {
"plans": [
{
"id": "plan_free",
"name": "Free Plan",
"price": 0,
"currency": "INR",
"interval": "monthly",
"credits": 100,
"features": ["Basic generation", "Standard fonts"],
"rateLimit": 100
},
{
"id": "plan_pro",
"name": "Professional Plan",
"price": {
"usd": 29,
"inr": 2465
},
"interval": "monthly",
"credits": 8500,
"rateLimit": 500
}
]
}
}Check User Credits
GET /api/v2/users/credits
x-api-key: YOUR_API_KEY
Response:
{
"success": true,
"data": {
"creditsRemaining": 7750,
"creditsUsed": 750,
"totalCredits": 8500,
"resetDate": "2024-02-01T00:00:00Z",
"plan": "Professional Plan"
}
}The API uses conventional HTTP response codes and provides detailed error information to help with debugging.
HTTP Status Codes
Bad Request
Invalid request parameters or missing required fields
Example: Missing "text" parameter
Unauthorized
Missing or invalid API key
Example: Invalid API key provided
Forbidden
API key lacks required permissions
Example: API key does not have SVG generation permission
Rate Limited
Too many requests, rate limit exceeded
Example: Rate limit of 100 requests/hour exceeded
Server Error
Internal server error, please retry
Example: Font rendering service temporarily unavailable
Error Response Format
{
"success": false,
"error": {
"code": "INVALID_LANGUAGE",
"message": "Unsupported language specified",
"details": {
"provided": "spanish",
"supported": ["hindi", "marathi", "gujarati", "english"]
},
"requestId": "req_clp7x8y9z123456789",
"timestamp": "2024-01-21T10:30:00Z"
}
}Error Handling Implementation
// Comprehensive error handling example
async function generateCalligraphy(requestData) {
try {
const response = await fetch('/api/v2/generate', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': process.env.CALLIGRAPHY_API_KEY
},
body: JSON.stringify(requestData)
});
const data = await response.json();
if (!data.success) {
const error = data.error;
switch (error.code) {
case 'INVALID_API_KEY':
throw new Error('API key is invalid or missing');
case 'INSUFFICIENT_CREDITS':
throw new Error('Not enough credits remaining');
case 'INVALID_LANGUAGE':
throw new Error(`Unsupported language: ${error.details.provided}`);
case 'TEXT_TOO_LONG':
throw new Error('Text exceeds maximum length limit');
default:
throw new Error(`API Error: ${error.message} (ID: ${error.requestId})`);
}
}
return data.data;
} catch (error) {
console.error('Calligraphy generation failed:', error.message);
throw error;
}
}Error Handling Best Practices
- • Always check the "success" field in responses
- • Log error requestId for support inquiries
- • Implement specific handling for common error codes
- • Validate input parameters before sending requests
- • Use try-catch blocks for network errors
- • Provide meaningful error messages to users
Plan-Based Limits
Free Plan
Paid Plans
Enterprise
Rate Limit Headers
Every API response includes rate limit information in the headers:
X-RateLimit-Limit: 500 X-RateLimit-Remaining: 495 X-RateLimit-Reset: 1640995200 X-RateLimit-Window: 3600
Handling Rate Limit Exceeded (429)
// Example: Exponential backoff retry strategy
async function callApiWithRetry(requestData, maxRetries = 3) {
for (let attempt = 0; attempt <= maxRetries; attempt++) {
try {
const response = await fetch('/api/v2/generate', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': 'YOUR_API_KEY'
},
body: JSON.stringify(requestData)
});
if (response.status === 429) {
const retryAfter = response.headers.get('Retry-After') || Math.pow(2, attempt);
const delay = parseInt(retryAfter) * 1000; // Convert to milliseconds
if (attempt < maxRetries) {
console.log(`Rate limited. Retrying after ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
continue;
} else {
throw new Error('Max retries exceeded');
}
}
return await response.json();
} catch (error) {
if (attempt === maxRetries) throw error;
}
}
}Rate Limiting Best Practices
- • Use batch endpoints to reduce API calls
- • Cache generated images when possible
- • Monitor rate limit headers in responses
- • Implement exponential backoff for retries
- • Use queue systems for high-volume usage
- • Consider upgrading plans for higher limits
Ready-to-use code examples for popular frameworks and platforms. Each example demonstrates best practices for integrating the Calligraphy API in your specific development environment.
cURL
Shellcurl -X POST "https://api.calligraphymaker.com/api/v2/generate" \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{
"text": "नमस्ते दोस्त",
"language": "hindi",
"fontStyle": "calligraphy",
"count": 3,
"imageFormat": "png"
}'JavaScript
Node.js// Using fetch API
const response = await fetch('https://api.calligraphymaker.com/api/v2/generate', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': 'YOUR_API_KEY'
},
body: JSON.stringify({
text: "नमस्ते दोस्त",
language: "hindi",
fontStyle: "calligraphy",
count: 3,
imageFormat: "png"
})
});
const data = await response.json();
if (data.success) {
console.log('Generated images:', data.data.images);
} else {
console.error('Generation failed:', data.error);
}Python
Pythonimport requests
url = "https://api.calligraphymaker.com/api/v2/generate"
headers = {
"Content-Type": "application/json",
"x-api-key": "YOUR_API_KEY"
}
payload = {
"text": "नमस्ते दोस्त",
"language": "hindi",
"fontStyle": "calligraphy",
"count": 3,
"imageFormat": "png"
}
response = requests.post(url, json=payload, headers=headers)
data = response.json()
if data.get('success'):
for image in data['data']['images']:
print(f"Image URL: {image['url']}")
print(f"Font Used: {image['fontUsed']}")
else:
print('Generation failed:', data.get('error'))PHP
PHP<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.calligraphymaker.com/api/v2/generate",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: YOUR_API_KEY"
],
CURLOPT_POSTFIELDS => json_encode([
"text" => "नमस्ते दोस्त",
"language" => "hindi",
"fontStyle" => "calligraphy",
"count" => 3,
"imageFormat" => "png"
])
]);
$response = curl_exec($curl);
curl_close($curl);
$data = json_decode($response, true);
if ($data['success']) {
foreach ($data['data']['images'] as $image) {
echo "Image URL: " . $image['url'] . "\n";
echo "Font Used: " . $image['fontUsed'] . "\n";
}
} else {
echo "Generation failed: " . $data['error']['message'] . "\n";
}
?>React Native
Mobile// React Native Example
import React from 'react';
import { View, Image, Text, Button } from 'react-native';
const generateCalligraphy = async () => {
try {
const response = await fetch('https://api.calligraphymaker.com/api/v2/generate', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': 'YOUR_API_KEY'
},
body: JSON.stringify({
text: "नमस्ते दोस्त",
language: "hindi",
fontStyle: "calligraphy",
count: 1,
imageFormat: "png"
})
});
const data = await response.json();
if (data.success) {
const imageUrl = data.data.images[0].url;
// Use imageUrl in Image component
return imageUrl;
}
} catch (error) {
console.error('Error generating calligraphy:', error);
}
};
// In your component
const CalligraphyDisplay = () => {
const [imageUrl, setImageUrl] = React.useState(null);
const handleGenerate = async () => {
const url = await generateCalligraphy();
setImageUrl(url);
};
return (
<View>
<Button title="Generate Calligraphy" onPress={handleGenerate} />
{imageUrl && <Image source={{ uri: imageUrl }} style={{ width: 300, height: 150 }} />}
</View>
);
};Flutter
Dart// Flutter Example
import 'package:http/http.dart' as http;
import 'dart:convert';
class CalligraphyService {
static const String apiUrl = 'https://api.calligraphymaker.com/api/v2/generate';
static const String apiKey = 'YOUR_API_KEY';
static Future<String?> generateCalligraphy(String text) async {
try {
final response = await http.post(
Uri.parse(apiUrl),
headers: {
'Content-Type': 'application/json',
'x-api-key': apiKey,
},
body: jsonEncode({
'text': text,
'language': 'hindi',
'fontStyle': 'calligraphy',
'count': 1,
'imageFormat': 'png',
}),
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
if (data['success']) {
return data['data']['images'][0]['url'];
}
}
} catch (e) {
print('Error generating calligraphy: $e');
}
return null;
}
}
// Usage in a Flutter widget
class CalligraphyWidget extends StatefulWidget {
@override
_CalligraphyWidgetState createState() => _CalligraphyWidgetState();
}
class _CalligraphyWidgetState extends State<CalligraphyWidget> {
String? _imageUrl;
void _generateCalligraphy() async {
final url = await CalligraphyService.generateCalligraphy('नमस्ते दोस्त');
setState(() {
_imageUrl = url;
});
}
@override
Widget build(BuildContext context) {
return Column(
children: [
ElevatedButton(
onPressed: _generateCalligraphy,
child: Text('Generate Calligraphy'),
),
if (_imageUrl != null)
Image.network(_imageUrl!),
],
);
}
}Android
Kotlin// Android (Kotlin) Example with Retrofit
import retrofit2.Call
import retrofit2.http.*
// Data classes
data class CalligraphyRequest(
val text: String,
val language: String,
val fontStyle: String,
val count: Int,
val imageFormat: String
)
data class CalligraphyResponse(
val success: Boolean,
val data: ResponseData
)
data class ResponseData(
val images: List<GeneratedImage>
)
data class GeneratedImage(
val url: String,
val fontUsed: String,
val width: Int,
val height: Int
)
// Retrofit interface
interface CalligraphyApiService {
@POST("api/v2/generate")
@Headers("Content-Type: application/json")
fun generateCalligraphy(
@Header("x-api-key") apiKey: String,
@Body request: CalligraphyRequest
): Call<CalligraphyResponse>
}
// Usage in Activity/Fragment
class CalligraphyActivity : AppCompatActivity() {
private val apiKey = "YOUR_API_KEY"
private fun generateCalligraphy() {
val retrofit = Retrofit.Builder()
.baseUrl("https://api.calligraphymaker.com/")
.addConverterFactory(GsonConverterFactory.create())
.build()
val service = retrofit.create(CalligraphyApiService::class.java)
val request = CalligraphyRequest(
text = "नमस्ते दोस्त",
language = "hindi",
fontStyle = "calligraphy",
count = 1,
imageFormat = "png"
)
service.generateCalligraphy(apiKey, request).enqueue(object : Callback<CalligraphyResponse> {
override fun onResponse(call: Call<CalligraphyResponse>, response: Response<CalligraphyResponse>) {
if (response.isSuccessful && response.body()?.success == true) {
val imageUrl = response.body()?.data?.images?.firstOrNull()?.url
// Load image using Glide or Picasso
imageUrl?.let { loadImage(it) }
}
}
override fun onFailure(call: Call<CalligraphyResponse>, t: Throwable) {
// Handle error
Log.e("CalligraphyAPI", "Error: ${t.message}")
}
})
}
}iOS/Swift
Swift// iOS Swift Example with URLSession
import UIKit
struct CalligraphyRequest: Codable {
let text: String
let language: String
let fontStyle: String
let count: Int
let imageFormat: String
}
struct CalligraphyResponse: Codable {
let success: Bool
let data: ResponseData
}
struct ResponseData: Codable {
let images: [GeneratedImage]
}
struct GeneratedImage: Codable {
let url: String
let fontUsed: String
let width: Int
let height: Int
}
class CalligraphyService {
static let apiKey = "YOUR_API_KEY"
static let apiURL = "https://api.calligraphymaker.com/api/v2/generate"
static func generateCalligraphy(text: String, completion: @escaping (String?) -> Void) {
guard let url = URL(string: apiURL) else {
completion(nil)
return
}
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue(apiKey, forHTTPHeaderField: "x-api-key")
let requestBody = CalligraphyRequest(
text: text,
language: "hindi",
fontStyle: "calligraphy",
count: 1,
imageFormat: "png"
)
do {
request.httpBody = try JSONEncoder().encode(requestBody)
} catch {
completion(nil)
return
}
URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
DispatchQueue.main.async {
completion(nil)
}
return
}
do {
let response = try JSONDecoder().decode(CalligraphyResponse.self, from: data)
if response.success, let imageUrl = response.data.images.first?.url {
DispatchQueue.main.async {
completion(imageUrl)
}
}
} catch {
DispatchQueue.main.async {
completion(nil)
}
}
}.resume()
}
}
// Usage in ViewController
class CalligraphyViewController: UIViewController {
@IBOutlet weak var imageView: UIImageView!
@IBAction func generateButtonTapped(_ sender: UIButton) {
CalligraphyService.generateCalligraphy(text: "नमस्ते दोस्त") { imageUrl in
guard let imageUrl = imageUrl,
let url = URL(string: imageUrl) else { return }
// Load image using URLSession or SDWebImage
self.loadImage(from: url)
}
}
}Next.js
React// Next.js Example with API Route and Client Component
// app/api/calligraphy/route.ts
import { NextResponse } from 'next/server';
export async function POST(request: Request) {
try {
const body = await request.json();
const response = await fetch('https://api.calligraphymaker.com/api/v2/generate', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': process.env.CALLIGRAPHY_API_KEY!
},
body: JSON.stringify({
text: body.text,
language: body.language || 'hindi',
fontStyle: body.fontStyle || 'calligraphy',
count: body.count || 1,
imageFormat: body.imageFormat || 'png'
})
});
const data = await response.json();
return NextResponse.json(data);
} catch (error) {
return NextResponse.json(
{ success: false, error: 'Failed to generate calligraphy' },
{ status: 500 }
);
}
}
// app/components/CalligraphyGenerator.tsx
'use client';
import { useState } from 'react';
import Image from 'next/image';
export default function CalligraphyGenerator() {
const [text, setText] = useState('नमस्ते दोस्त');
const [imageUrl, setImageUrl] = useState('');
const [loading, setLoading] = useState(false);
const generateCalligraphy = async () => {
setLoading(true);
try {
const response = await fetch('/api/calligraphy', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ text })
});
const data = await response.json();
if (data.success) {
setImageUrl(data.data.images[0].url);
}
} catch (error) {
console.error('Error:', error);
} finally {
setLoading(false);
}
};
return (
<div className="max-w-2xl mx-auto p-6">
<h2 className="text-3xl font-bold mb-6">Calligraphy Generator</h2>
<div className="space-y-4">
<input
type="text"
value={text}
onChange={(e) => setText(e.target.value)}
className="w-full px-4 py-2 border rounded-lg"
placeholder="Enter text for calligraphy"
/>
<button
onClick={generateCalligraphy}
disabled={loading}
className="w-full py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:opacity-50"
>
{loading ? 'Generating...' : 'Generate Calligraphy'}
</button>
{imageUrl && (
<div className="mt-6">
<Image
src={imageUrl}
alt="Generated Calligraphy"
width={600}
height={300}
className="rounded-lg shadow-lg"
/>
</div>
)}
</div>
</div>
);
}WordPress
PHP// WordPress Plugin Example
<?php
/**
* Plugin Name: Calligraphy Maker Integration
* Description: Generate beautiful calligraphy using Calligraphy Maker API
* Version: 1.0.0
*/
// Add settings page
add_action('admin_menu', 'calligraphy_maker_menu');
function calligraphy_maker_menu() {
add_options_page(
'Calligraphy Maker Settings',
'Calligraphy Maker',
'manage_options',
'calligraphy-maker',
'calligraphy_maker_settings_page'
);
}
// Settings page HTML
function calligraphy_maker_settings_page() {
?>
<div class="wrap">
<h2>Calligraphy Maker Settings</h2>
<form method="post" action="options.php">
<?php settings_fields('calligraphy_maker_settings'); ?>
<table class="form-table">
<tr>
<th scope="row">API Key</th>
<td>
<input type="text" name="calligraphy_maker_api_key"
value="<?php echo get_option('calligraphy_maker_api_key'); ?>" />
</td>
</tr>
</table>
<?php submit_button(); ?>
</form>
</div>
<?php
}
// Register settings
add_action('admin_init', 'calligraphy_maker_settings_init');
function calligraphy_maker_settings_init() {
register_setting('calligraphy_maker_settings', 'calligraphy_maker_api_key');
}
// Shortcode for generating calligraphy
add_shortcode('calligraphy', 'calligraphy_maker_shortcode');
function calligraphy_maker_shortcode($atts) {
$atts = shortcode_atts([
'text' => 'नमस्ते',
'language' => 'hindi',
'fontStyle' => 'calligraphy'
], $atts);
$api_key = get_option('calligraphy_maker_api_key');
if (!$api_key) {
return '<p>Please configure your Calligraphy Maker API key.</p>';
}
// Generate unique ID for this instance
$unique_id = 'calligraphy_' . uniqid();
ob_start();
?>
<div id="<?php echo $unique_id; ?>" class="calligraphy-container">
<button class="calligraphy-generate" data-text="<?php echo esc_attr($atts['text']); ?>"
data-language="<?php echo esc_attr($atts['language']); ?>"
data-fontStyle="<?php echo esc_attr($atts['fontStyle']); ?>">
Generate Calligraphy
</button>
<div class="calligraphy-result"></div>
</div>
<script>
jQuery(document).ready(function($) {
$('#<?php echo $unique_id; ?> .calligraphy-generate').click(function() {
var button = $(this);
var container = button.closest('.calligraphy-container');
var resultDiv = container.find('.calligraphy-result');
button.prop('disabled', true).text('Generating...');
$.ajax({
url: '<?php echo admin_url('admin-ajax.php'); ?>',
type: 'POST',
data: {
action: 'generate_calligraphy',
text: button.data('text'),
language: button.data('language'),
fontStyle: button.data('fontStyle'),
nonce: '<?php echo wp_create_nonce('calligraphy_nonce'); ?>'
},
success: function(response) {
if (response.success && response.data.imageUrl) {
resultDiv.html('<img src="' + response.data.imageUrl + '" alt="Calligraphy" />');
} else {
resultDiv.html('<p>Error generating calligraphy</p>');
}
},
complete: function() {
button.prop('disabled', false).text('Generate Calligraphy');
}
});
});
});
</script>
<?php
return ob_get_clean();
}
// AJAX handler
add_action('wp_ajax_generate_calligraphy', 'handle_calligraphy_generation');
add_action('wp_ajax_nopriv_generate_calligraphy', 'handle_calligraphy_generation');
function handle_calligraphy_generation() {
check_ajax_referer('calligraphy_nonce', 'nonce');
$api_key = get_option('calligraphy_maker_api_key');
$text = sanitize_text_field($_POST['text']);
$language = sanitize_text_field($_POST['language']);
$fontStyle = sanitize_text_field($_POST['fontStyle']);
$response = wp_remote_post('https://api.calligraphymaker.com/api/v2/generate', [
'headers' => [
'Content-Type' => 'application/json',
'x-api-key' => $api_key
],
'body' => json_encode([
'text' => $text,
'language' => $language,
'fontStyle' => $fontStyle,
'count' => 1,
'imageFormat' => 'png'
])
]);
if (!is_wp_error($response)) {
$body = json_decode(wp_remote_retrieve_body($response), true);
if ($body['success']) {
wp_send_json_success(['imageUrl' => $body['data']['images'][0]['url']]);
}
}
wp_send_json_error('Failed to generate calligraphy');
}Vue.js
Vue// Vue.js 3 Composition API Example
<template>
<div class="calligraphy-generator">
<h2>Calligraphy Generator</h2>
<div class="form-group">
<label>Text:</label>
<input v-model="text" type="text" placeholder="Enter text" />
</div>
<div class="form-group">
<label>Language:</label>
<select v-model="language">
<option value="hindi">Hindi</option>
<option value="marathi">Marathi</option>
<option value="gujarati">Gujarati</option>
<option value="english">English</option>
</select>
</div>
<button @click="generateCalligraphy" :disabled="loading">
{{ loading ? 'Generating...' : 'Generate Calligraphy' }}
</button>
<div v-if="error" class="error">{{ error }}</div>
<div v-if="images.length > 0" class="results">
<h3>Generated Images:</h3>
<div v-for="(image, index) in images" :key="index" class="image-container">
<img :src="image.url" :alt="'Calligraphy ' + (index + 1)" />
<p>Font: {{ image.fontUsed }}</p>
</div>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import axios from 'axios'
const API_KEY = 'YOUR_API_KEY'
const API_URL = 'https://api.calligraphymaker.com/api/v2/generate'
const text = ref('नमस्ते दोस्त')
const language = ref('hindi')
const loading = ref(false)
const error = ref('')
const images = ref([])
const generateCalligraphy = async () => {
loading.value = true
error.value = ''
images.value = []
try {
const response = await axios.post(API_URL, {
text: text.value,
language: language.value,
fontStyle: 'calligraphy',
count: 3,
imageFormat: 'png'
}, {
headers: {
'Content-Type': 'application/json',
'x-api-key': API_KEY
}
})
if (response.data.success) {
images.value = response.data.data.images
} else {
error.value = response.data.error.message || 'Failed to generate calligraphy'
}
} catch (err) {
error.value = err.message || 'An error occurred'
} finally {
loading.value = false
}
}
</script>
<style scoped>
.calligraphy-generator {
max-width: 600px;
margin: 0 auto;
padding: 20px;
}
.form-group {
margin-bottom: 15px;
}
.form-group label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
.form-group input,
.form-group select {
width: 100%;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
}
button {
background-color: #007bff;
color: white;
padding: 10px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
}
button:disabled {
opacity: 0.6;
cursor: not-allowed;
}
.error {
color: #dc3545;
margin-top: 10px;
}
.results {
margin-top: 20px;
}
.image-container {
margin-bottom: 20px;
text-align: center;
}
.image-container img {
max-width: 100%;
height: auto;
border: 1px solid #ddd;
border-radius: 4px;
}
</style>Node.js
Express// Node.js Example with Express
const express = require('express');
const axios = require('axios');
const app = express();
app.use(express.json());
const CALLIGRAPHY_API_KEY = process.env.CALLIGRAPHY_API_KEY;
const CALLIGRAPHY_API_URL = 'https://api.calligraphymaker.com/api/v2/generate';
// Route to generate calligraphy
app.post('/generate-calligraphy', async (req, res) => {
try {
const { text, language = 'hindi', fontStyle = 'calligraphy' } = req.body;
if (!text) {
return res.status(400).json({ error: 'Text is required' });
}
const response = await axios.post(CALLIGRAPHY_API_URL, {
text,
language,
fontStyle,
count: 3,
imageFormat: 'png'
}, {
headers: {
'Content-Type': 'application/json',
'x-api-key': CALLIGRAPHY_API_KEY
}
});
if (response.data.success) {
res.json({
success: true,
images: response.data.data.images
});
} else {
res.status(400).json({
success: false,
error: response.data.error
});
}
} catch (error) {
console.error('Calligraphy generation error:', error);
res.status(500).json({
success: false,
error: 'Failed to generate calligraphy'
});
}
});
// Webhook endpoint to receive notifications
app.post('/webhook/calligraphy', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-calligraphy-signature'];
const payload = req.body;
// Verify webhook signature
const crypto = require('crypto');
const expectedSignature = crypto
.createHmac('sha256', process.env.WEBHOOK_SECRET)
.update(payload)
.digest('hex');
if (signature !== expectedSignature) {
return res.status(401).send('Invalid signature');
}
const event = JSON.parse(payload);
// Handle different event types
switch (event.type) {
case 'generation.completed':
console.log('Generation completed:', event.data);
// Process completed generation
break;
case 'generation.failed':
console.error('Generation failed:', event.data);
// Handle failed generation
break;
case 'batch.completed':
console.log('Batch completed:', event.data);
// Process completed batch
break;
default:
console.log('Unknown event type:', event.type);
}
res.status(200).send('OK');
});
// Health check endpoint
app.get('/health', (req, res) => {
res.json({ status: 'ok', service: 'calligraphy-integration' });
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});SVG Download
JavaScript// SVG Download Example
const downloadSVG = async (resultText, fontName) => {
try {
const response = await fetch('https://api.calligraphymaker.com/api/v2/download-svg', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': 'YOUR_API_KEY'
},
body: JSON.stringify({
resultText: resultText,
fontName: fontName
})
});
const data = await response.json();
if (data.success) {
// Download SVG as file
const svgBlob = new Blob([data.data.svgString], { type: 'image/svg+xml' });
const url = URL.createObjectURL(svgBlob);
const a = document.createElement('a');
a.href = url;
a.download = 'calligraphy.svg';
a.click();
return data.data.svgBase64; // Return base64 for display
}
} catch (error) {
console.error('SVG download failed:', error);
}
};Image Download
JavaScript// Image Download Example
const downloadImage = async (resultText, fontName, format = 'png') => {
try {
const response = await fetch('https://api.calligraphymaker.com/api/v2/download-image', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': 'YOUR_API_KEY'
},
body: JSON.stringify({
resultText: resultText,
fontName: fontName,
imageWidth: 800,
imageHeight: 600,
imageQuality: 90,
imageFormat: format,
backgroundColor: '#ffffff',
textColor: '#000000'
})
});
const data = await response.json();
if (data.success) {
// Download image as file
const a = document.createElement('a');
a.href = data.data.imageBase64;
a.download = `calligraphy.${format}`;
a.click();
return data.data.imageBase64; // Return base64 for display
}
} catch (error) {
console.error('Image download failed:', error);
}
};Webhook Signature
Node.js// Webhook signature verification (Node.js)
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}
// Express.js webhook handler
app.post('/webhook', express.raw({type: 'application/json'}), (req, res) => {
const signature = req.headers['x-calligraphy-signature'];
const payload = req.body;
if (!verifyWebhookSignature(payload, signature, process.env.WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
const event = JSON.parse(payload);
console.log('Received event:', event.type);
res.status(200).send('OK');
});Devanagari script
Devanagari script
Gujarati script
Latin script