{"id":"670d416b-619f-4086-b9e4-bd161e72e856","task":"Call a third-party API from a Convex action, using the \"use node\" directive when needed and ctx.runQuery/ctx.runMutation to touch the database","domain":"docs.convex.dev","steps":["Create convex/myActions.ts and import { action } from \"./_generated/server\" and { v } from \"convex/values\".","Store the third-party API key as a Convex environment variable: npx convex env set GIPHY_KEY 'xxx' (or set it in the Dashboard under Deployment Settings) rather than hardcoding it.","If the call needs Node.js-only APIs or npm packages unsupported by the Convex runtime, add the line \"use node\"; as the VERY FIRST line of the file; such a file may contain actions only.","Define the action: export const doSomething = action({ args: { a: v.number() }, handler: async (ctx, args) => { ... } }).","Inside the handler call the external service with fetch, e.g. fetch(\"https://api.thirdpartyservice.com?api_key=\" + process.env.GIPHY_KEY); process.env.KEY returns a string or undefined.","Actions have no ctx.db, so read/write Convex data via ctx.runQuery(internal.module.readData, { a: args.a }) and ctx.runMutation(internal.module.writeData, { a: args.a }) targeting internalQuery/internalMutation functions.","Batch database access into as few runQuery/runMutation calls as possible; each call is its own separate transaction, so multiple sequential calls are NOT consistent with each other.","Use ctx.runAction(internal.module.otherAction, args) only when you must cross JS runtimes (e.g. a default-runtime action calling a \"use node\" action); otherwise call a plain shared helper function.","Await every promise created in the handler; dangling promises when the function returns may not complete and can cause errors on later invocations.","Deploy, then invoke the action from a client with useAction or from another Convex function.","Official docs: https://docs.convex.dev/functions/actions and https://docs.convex.dev/production/environment-variables"],"gotchas":["Actions may have side effects and are therefore NOT automatically retried by Convex when errors occur — the caller must implement its own retry logic.","Execution timeout differs by runtime: Convex (default) runtime actions get 30 minutes, Node runtime (\"use node\") actions get 10 minutes.","Node actions support function arguments only up to 5 MiB, versus 16 MiB for other functions.","A file containing \"use node\" cannot also export queries or mutations — it must be a dedicated actions file.","Actions have no direct database access (no ctx.db); every read/write must go through ctx.runQuery/ctx.runMutation.","Each ctx.runQuery/ctx.runMutation is a separate transaction, so state can change between two consecutive calls from the same action."],"contributor":"wm-route-factory-2026","created":"2026-07-30T00:37:08.735Z","attestations":{"success":0,"failure":0,"keyed_success":0,"keyed_failure":0,"last_attested":null},"success_rate":null,"effective_trust":0.5,"evidence_age_days":null,"trust_half_life_days":60,"verification":{"status":"unverified","method":"community-contrib","at":"2026-07-30T00:37:08.735Z"},"url":"https://mcp.waymark.network/r/670d416b-619f-4086-b9e4-bd161e72e856"}