Composables

useConvexAction

Execute Convex actions for external API calls.

Call a Convex action for external API calls or long-running tasks.

Usage

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 to summarize')">
      {{ isLoading ? 'Processing...' : 'Summarize' }}
    </button>
    <p v-if="result">
      {{ result }}
    </p>
    <p v-if="error">
      {{ error.message }}
    </p>
  </div>
</template>

Parameters

ParameterTypeDescription
actionFunctionReferenceThe Convex action to call

Return Values

PropertyTypeDescription
execute(args) => Promise<T>Call the action
isLoadingRef<boolean>True while running
errorRef<Error | null>Error if action failed

Actions vs Mutations

Use mutations for database operations. Use actions when you need to:

  • Call external APIs (payment providers, AI services)
  • Perform operations that shouldn't be transactional
  • Use Node.js APIs not available in mutations
FeatureMutationAction
Database accessDirectVia ctx.runMutation()
External APIsNoYes
TransactionalYesNo
RetriesAutomaticManual

Example: Payment Processing

app/components/Checkout.vue
<script setup lang="ts">
import { api } from '#convex/api'

const { execute: processPayment, isLoading } = useConvexAction(api.payments.process)

async function handleCheckout(amount: number) {
  const result = await processPayment({ amount, currency: 'usd' })
  if (result.success) {
    navigateTo('/order-confirmation')
  }
}
</script>

The payment action calls an external payment provider, then saves the result using a mutation:

convex/payments.ts
import { v } from 'convex/values'
import { api } from './_generated/api'
import { action } from './_generated/server'

export const process = action({
  args: { amount: v.number(), currency: v.string() },
  handler: async (ctx, { amount, currency }) => {
    // Call external payment API
    const result = await stripe.charges.create({ amount, currency })

    // Save result to database
    await ctx.runMutation(api.orders.create, {
      chargeId: result.id,
      amount,
      status: result.status,
    })

    return { success: result.status === 'succeeded' }
  },
})