The Contentstack App SDK .api() method offers a unified approach for making internal API calls to Contentstack services as well as external calls to third-party services. It automatically manages authentication, routing, and security, so you can focus on building functionality instead of handling infrastructure.
Before making API calls, ensure the following:
Additional Resource: Refer to the App SDK documentation to learn more.
Internal API calls use Contentstack’s built-in authentication via App Permissions, eliminating the need for separate credential management.
Start by declaring the required permissions. In your Developer Hub application, go to the UI tab and select all the permissions your app needs. For this example, the following permissions are used:
The example below demonstrates how to read and write content and releases:
async function getContentTypes() {
try {
// Get all content types
const contentTypesRes = await appSdk.api(
`${appSdk.endpoints.CMA}/v3/content_types`,
{
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
}
);
return contentTypesRes.json();
} catch (error) {
console.error('Error fetching content types:', error);
throw error;
}
}
async function createContentType(contentTypeData) {
try {
const contentTypesRes = await appSdk.api(
`${appSdk.endpoints.CMA}/v3/content_types`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: contentTypeData
}
);
return contentTypesRes.json();
} catch (error) {
console.error('Error creating content type:', error);
throw error;
}
}
External API calls use Advanced Settings configurations to securely manage credentials and simplify URL routing.
Note: This example only uses AI. You can integrate any API.
In Developer Hub, under Advanced Settings > Variables, define your AI key variables as shown below:
{
"AI_API_KEY": "sk-your-default-ai-api-key",
"AI_MODEL": "gpt-3.5-turbo"
}In Developer Hub, under Advanced Settings > Mappings, define mappings that allow end users to provide their credentials for the application.
{
"CUSTOMER_AI_KEY": "integrations.ai.apiKey",
"PREFERRED_MODEL": "integrations.ai.model"
}In Developer Hub, under Advanced Settings > Rewrites, define rewrites to simplify the API calls made by your application.
{
"/ai-chat": "https://api.ai.com/v1/chat/completions",
"/ai-models": "https://api.ai.com/v1/models"
}The following is a complete example of how to integrate with the AI API:
async function generateAIContent(userPrompt) {
try {
// Get available models first
const modelsRes = await appSdk.api('/ai-models', {
method: 'GET',
headers: {
'Authorization': 'Bearer {{map.CUSTOMER_AI_KEY}}',
'Content-Type': 'application/json'
}
});
const models = await modelsRes.json();
console.log('Available Models:', models.data);
// Generate AI content
const aiResponse = await appSdk.api('/ai-chat', {
method: 'POST',
headers: {
'Authorization': 'Bearer {{map.CUSTOMER_AI_KEY}}',
'Content-Type': 'application/json'
},
body: JSON.stringify({
model: '{{map.PREFERRED_MODEL}}',
messages: [
{
role: 'system',
content: 'You are a helpful content writing assistant for a CMS.'
},
{
role: 'user',
content: userPrompt
}
],
max_tokens: 500,
temperature: 0.7
})
});
const data = await aiResponse.json();
console.log('AI Response:', data);
return {
generatedContent: data.choices[0].message.content,
usage: data.usage,
model: data.model
};
} catch (error) {
console.error('Error generating AI content:', error);
// Handle specific error cases
if (error.status === 401) {
throw new Error('Invalid API key. Please check your AI configuration.');
} else if (error.status === 429) {
throw new Error('Rate limit exceeded. Please try again later.');
}
throw error;
}
}Ensure that you are always implementing comprehensive error handling:
async function makeApiCallWithRetry(url, options, maxRetries = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const response = await appSdk.api(url, options);
return response.json();
} catch (error) {
console.warn(`Attempt ${attempt} failed:`, error.message);
if (attempt === maxRetries) {
throw error;
}
// Wait before retrying (exponential backoff)
await new Promise(resolve => setTimeout(resolve, Math.pow(2, attempt) * 1000));
}
}
}