Edge Functions are server-side TypeScript functions hosted by Supabase. Use them for logic that should not run on the client: calling third-party APIs with secret keys, processing webhooks, sending emails, or any operation that needs server-level access.
For the full guide, see the Supabase Edge Functions docs.
Setup
You need the Supabase CLI to create and deploy functions. Install it, then log in and link to your project. You can find your project reference ID in the Supabase dashboard under Settings → General.
npm install -g supabase
supabase login
supabase link --project-ref your-project-refCreate a Function
This command creates a new function folder with a template file at supabase/functions/hello-world/index.ts. Edge Functions use Deno (a TypeScript runtime, similar to Node.js but with built-in TypeScript support).
supabase functions new hello-worldEdit the generated file. The function receives an HTTP request and returns an HTTP response:
import { serve } from 'https://deno.land/std@0.177.0/http/server.ts'
serve(async (req) => {
const { name } = await req.json()
return new Response(
JSON.stringify({ message: `Hello ${name}!` }),
{ headers: { 'Content-Type': 'application/json' } },
)
})Test Locally
Start the local Supabase environment (this runs a local Postgres database and all Supabase services), then serve your function:
supabase start
supabase functions serve hello-worldYour function is now available at http://localhost:54321/functions/v1/hello-world. Test it with a POST request.
Deploy
Deploy to production with a single command. The function becomes available at your Supabase project's URL.
supabase functions deploy hello-worldCall from Flutter
Use the Supabase client to invoke the function by name. Pass data in the body parameter and read the response from response.data.
final response = await supabase.functions.invoke(
'hello-world',
body: {'name': 'Mitch'},
);
final data = response.data;
print(data['message']); // Hello Mitch!Secrets
Store API keys and sensitive values as secrets. They are available as environment variables inside your function but never exposed to the client.
# Set a secret via CLI
supabase secrets set STRIPE_KEY=sk_live_xxx// Access it in your function
const stripeKey = Deno.env.get('STRIPE_KEY')!Practical Example
A function that calls a third-party API using a secret key. The secret stays on the server and is never sent to the client app.
import { serve } from 'https://deno.land/std@0.177.0/http/server.ts'
serve(async (req) => {
try {
const apiKey = Deno.env.get('API_KEY')!
const { query } = await req.json()
const res = await fetch('https://api.example.com/search', {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ q: query }),
})
if (!res.ok) {
return new Response(
JSON.stringify({ error: 'API request failed' }),
{ status: res.status, headers: { 'Content-Type': 'application/json' } },
)
}
const data = await res.json()
return new Response(JSON.stringify(data), {
headers: { 'Content-Type': 'application/json' },
})
} catch (error) {
return new Response(
JSON.stringify({ error: error.message }),
{ status: 500, headers: { 'Content-Type': 'application/json' } },
)
}
})Call it from Flutter the same way as any other function:
final response = await supabase.functions.invoke(
'search',
body: {'query': 'flutter tutorials'},
);
if (response.status != 200) {
// Handle error
print('Error: ${response.data['error']}');
}