Backend
Actions
Run arbitrary code including external API calls with Convex actions.
Actions run arbitrary code including external API calls. Unlike queries and mutations, actions cannot directly access the database.
Basic Action
Create an action that calls an external API:
convex/ai.ts
import { v } from 'convex/values'
import { action } from './_generated/server'
export const summarize = action({
args: { text: v.string() },
handler: async (ctx, { text }) => {
const response = await fetch('https://api.openai.com/v1/...', {
method: 'POST',
headers: { Authorization: `Bearer ${process.env.OPENAI_API_KEY}` },
body: JSON.stringify({ prompt: text }),
})
return await response.json()
},
})
When to Use Actions
Use actions when you need to:
- Call external APIs (payment providers, AI services, etc.)
- Perform long-running operations
- Use libraries that require Node.js APIs
- Execute side effects that shouldn't be transactional
Actions cannot read from or write to the database directly. Use
ctx.runQuery() and ctx.runMutation() to interact with data.Calling Queries and Mutations
Actions can call other Convex functions:
convex/tasks.ts
import { v } from 'convex/values'
import { api } from './_generated/api'
import { action } from './_generated/server'
export const processAndSave = action({
args: { text: v.string(), userId: v.string() },
handler: async (ctx, { text, userId }) => {
// Call external API
const processed = await processText(text)
// Save result using a mutation
await ctx.runMutation(api.tasks.add, {
title: processed,
userId,
})
return processed
},
})
Using in Components
Call actions from Vue components with useConvexAction:
app/components/Summarize.vue
<script setup lang="ts">
import { api } from '#convex/api'
const { execute: summarize, isLoading, error } = useConvexAction(api.ai.summarize)
const result = ref('')
async function handleSummarize(text: string) {
result.value = await summarize({ text })
}
</script>
<template>
<div>
<button :disabled="isLoading" @click="handleSummarize('Some text')">
Summarize
</button>
<p v-if="result">
{{ result }}
</p>
<p v-if="error">
{{ error.message }}
</p>
</div>
</template>
See useConvexAction for full documentation.
Environment Variables
Access environment variables in actions through process.env:
convex/integrations.ts
export const sendEmail = action({
args: { to: v.string(), subject: v.string(), body: v.string() },
handler: async (ctx, { to, subject, body }) => {
await fetch('https://api.sendgrid.com/v3/mail/send', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SENDGRID_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ to, subject, body }),
})
},
})
Set environment variables in the Convex dashboard under Settings → Environment Variables.