Skip to content

articles.upvote()

Casts an upvote on an article to indicate it is helpful, well-written, or valuable content.

async upvote(articleId: number): Promise<ArticleResponseModel>
ParameterTypeRequiredDescription
articleIdnumberYesThe unique identifier of the article to upvote

Returns a Promise<ArticleResponseModel> containing the complete updated article information including the new vote count and score.

import { StackOverflowSDK } from 'so-teams-sdk';
const sdk = new StackOverflowSDK({
accessToken: 'your-access-token',
baseUrl: 'https://[your-site].stackenterprise.co/api/v3'
});
// Upvote an article
const result = await sdk.articles.upvote(123);
console.log(`Article score is now: ${result.score}`);
console.log(`Total upvotes: ${result.upvoteCount}`);
try {
const articleBefore = await sdk.articles.get(123);
console.log(`Current score: ${articleBefore.score}`);
console.log(`Current upvotes: ${articleBefore.upvoteCount}`);
const result = await sdk.articles.upvote(123);
console.log(`Score after upvote: ${result.score}`);
console.log(`Upvotes after vote: ${result.upvoteCount}`);
console.log(`Score increased by: ${result.score - articleBefore.score}`);
} catch (error) {
console.error('Failed to upvote:', error.message);
}
async function upvoteIfHelpful(articleId: number) {
try {
// Get current article state
const article = await sdk.articles.get(articleId);
// Check if we should upvote based on content quality
if (article.viewCount > 50 && article.score < 10) {
const result = await sdk.articles.upvote(articleId);
console.log(`Upvoted helpful article: ${article.title}`);
console.log(`New score: ${result.score}`);
return result;
} else {
console.log('Article doesn\'t meet upvote criteria');
return article;
}
} catch (error) {
console.error('Error in conditional upvote:', error.message);
throw error;
}
}
await upvoteIfHelpful(123);
// Using team context
const teamSDK = sdk.forTeam('team-123');
const result = await teamSDK.articles.upvote(123);
// Or with direct client initialization
import { ArticleClient } from 'so-teams-sdk';
const teamArticleClient = new ArticleClient(config, 'team-123');
const voteResult = await teamArticleClient.upvote(123);
async function upvoteMultipleArticles(articleIds: number[]) {
const results = [];
for (const articleId of articleIds) {
try {
const result = await sdk.articles.upvote(articleId);
results.push({
articleId,
status: 'upvoted',
newScore: result.score,
title: result.title
});
console.log(`✓ Upvoted: ${result.title} (Score: ${result.score})`);
} catch (error) {
results.push({
articleId,
status: 'failed',
error: error.message
});
console.error(`✗ Failed to upvote article ${articleId}:`, error.message);
}
}
return results;
}
const upvoteResults = await upvoteMultipleArticles([123, 456, 789]);
console.log('Upvote results:', upvoteResults);
async function upvoteWithAnalytics(articleId: number) {
try {
const beforeVote = await sdk.articles.get(articleId);
const voteResult = await sdk.articles.upvote(articleId);
const analytics = {
articleId: articleId,
title: voteResult.title,
author: voteResult.owner?.displayName,
beforeVote: {
score: beforeVote.score,
upvotes: beforeVote.upvoteCount,
views: beforeVote.viewCount
},
afterVote: {
score: voteResult.score,
upvotes: voteResult.upvoteCount,
views: voteResult.viewCount
},
engagement: {
upvoteToViewRatio: voteResult.upvoteCount / Math.max(voteResult.viewCount, 1),
scoreImprovement: voteResult.score - beforeVote.score
},
timestamp: new Date().toISOString()
};
console.log('Vote Analytics:', analytics);
return { voteResult, analytics };
} catch (error) {
console.error('Failed to upvote with analytics:', error.message);
throw error;
}
}
const { voteResult, analytics } = await upvoteWithAnalytics(123);
import StackOverflowSDK, { ForbiddenError } from 'so-teams-sdk';
async function toggleUpvote(articleId: number) {
try {
// Try to upvote
const result = await sdk.articles.upvote(articleId);
console.log('Upvote successful:', result.score);
return { action: 'upvoted', score: result.score };
} catch (error) {
if (error instanceof ForbiddenError && error.message.includes('already voted')) {
// If already upvoted, remove the upvote
const result = await sdk.articles.removeUpvote(articleId);
console.log('Upvote removed:', result.score);
return { action: 'removed_upvote', score: result.score };
} else {
console.error('Vote error:', error.message);
throw error;
}
}
}
const voteResult = await toggleUpvote(123);
console.log(`Action: ${voteResult.action}, New score: ${voteResult.score}`);
async function upvoteQualityArticles(articleIds: number[]) {
const qualityThresholds = {
minViews: 20,
minWordCount: 100,
requiredTags: 2
};
const results = [];
for (const articleId of articleIds) {
try {
const article = await sdk.articles.get(articleId);
// Quality checks
const wordCount = article.bodyMarkdown?.split(/\s+/).length || 0;
const meetsQuality =
article.viewCount >= qualityThresholds.minViews &&
wordCount >= qualityThresholds.minWordCount &&
article.tags.length >= qualityThresholds.requiredTags;
if (meetsQuality) {
const result = await sdk.articles.upvote(articleId);
results.push({
articleId,
title: result.title,
action: 'upvoted',
newScore: result.score,
qualityMetrics: {
views: article.viewCount,
wordCount,
tagCount: article.tags.length
}
});
console.log(`✓ Upvoted quality article: ${result.title}`);
} else {
results.push({
articleId,
title: article.title,
action: 'skipped',
reason: 'quality_threshold_not_met'
});
console.log(`- Skipped: ${article.title} (doesn't meet quality thresholds)`);
}
} catch (error) {
results.push({
articleId,
action: 'failed',
error: error.message
});
console.error(`✗ Failed to process article ${articleId}:`, error.message);
}
}
return results;
}
const qualityResults = await upvoteQualityArticles([123, 456, 789]);
console.log(`Upvoted ${qualityResults.filter(r => r.action === 'upvoted').length} quality articles`);

This method can throw the following errors:

Error TypeStatus CodeDescription
AuthenticationError401Invalid or missing authentication token
TokenExpiredError401Authentication token has expired
ForbiddenError403Cannot vote (already voted, own article, insufficient permissions)
NotFoundError404Article with the specified ID does not exist
SDKErrorVariousOther API or network errors
import StackOverflowSDK, { NotFoundError, ForbiddenError } from 'so-teams-sdk';
const sdk = new StackOverflowSDK({
accessToken: 'your-access-token',
baseUrl: 'https://[your-site].stackenterprise.co/api/v3'
});
try {
const result = await sdk.articles.upvote(123);
console.log('Upvote successful, new score:', result.score);
} catch (error) {
if (error instanceof NotFoundError) {
console.error('Article not found');
} else if (error instanceof ForbiddenError) {
if (error.message.includes('already voted')) {
console.error('You have already upvoted this article');
} else if (error.message.includes('own article')) {
console.error('Cannot vote on your own article');
} else {
console.error('Vote not allowed:', error.message);
}
} else {
console.error('Failed to upvote:', error.message);
}
}
async function safeUpvote(articleId: number) {
try {
const result = await sdk.articles.upvote(articleId);
return {
success: true,
score: result.score,
upvoteCount: result.upvoteCount
};
} catch (error) {
if (error instanceof ForbiddenError) {
if (error.message.includes('already voted')) {
return { success: false, reason: 'already_voted' };
} else if (error.message.includes('own article')) {
return { success: false, reason: 'own_article' };
} else if (error.message.includes('reputation')) {
return { success: false, reason: 'insufficient_reputation' };
}
}
return { success: false, reason: 'error', message: error.message };
}
}
const result = await safeUpvote(123);
if (result.success) {
console.log('Upvoted successfully, new score:', result.score);
} else {
console.log('Could not upvote:', result.reason);
}
  • Users cannot vote on their own articles
  • Each user can only upvote an article once
  • If a user has already upvoted an article, calling this method again will typically result in a ForbiddenError
  • Articles only support upvoting (no downvoting) unlike questions and answers
  • To remove an upvote, use the removeUpvote() method
  • Voting may require a minimum reputation level depending on the platform configuration
  • The returned ArticleResponseModel contains the complete updated article information
  • Vote counts and scores are updated immediately and reflected in the response
  • Some articles may be protected from voting due to special circumstances (archived, locked, etc.)
  • Upvotes typically increase both the score and upvoteCount fields by 1