Aurabase Logo
aurabasedocs
docs›Edge Functions›Invoke a function

Invoke a function

How to call a deployed function with the JavaScript SDK or over HTTP, and how your function knows who is calling.

8 min read·Level intermediate·Revised on Oct 12, 2026
This English text was generated automatically from the French original and has not been reviewed yet.
#
SDK

1. Call from the SDK

invoke is the only call a public key can make. It works the same in a browser and on a server.

src/lib/call.tstypescript
import { createClient } from '@aurabase/aurabase-js'

const aura = createClient(process.env.AURA_URL!, process.env.AURA_ANON_KEY!)

const { data, error } = await aura.functions.invoke<{ greeting: string }>('hello', {
  body: { name: 'Ada' },
})
if (error) throw error
console.log(data?.greeting)
src/lib/call-as-user.tstypescript
// After sign-in, the SDK adds the user's JWT to every call: no extra code.
await aura.auth.signInWithPassword({ email, password })
const { data } = await aura.functions.invoke('whoami')
// The function sees x-aura-role: authenticated and the user's id.

The generic invoke<T> only types the response. The name and the body are not checked at compile time.

A public key can only invoke

list, get, listJobs, enqueueJob and the other management methods need a service_role key and belong on your server. A public key receives 403. See who can call what.

#
Request

2. Describe the request

Your function receives exactly the request you describe, not a wrapper around it.

OptionDefaultWhat the function sees
methodPOSTreq.method
path/new URL(req.url).pathname
headersnonereq.headers, except the platform headers listed below
bodynoneawait req.json() (or req.text() for a string)
timeoutclient default (30 s)not visible: cancels your call
signalnonenot visible: cancels your call
responseType'json'not visible: how the SDK decodes the response, see non-JSON responses
request.tstypescript
await aura.functions.invoke('items', {
  method: 'PUT',
  path: '/items/1',
  headers: { 'x-source': 'dashboard' },
  body: { qty: 2 },
})
aurabase/functions/items/index.tstypescript
Deno.serve(async (req) => {
  const url = new URL(req.url)          // pathname: '/items/1'
  const source = req.headers.get('x-source') // 'dashboard'
  const body = await req.json()         // { qty: 2 }
  return Response.json({ method: req.method, id: url.pathname.split('/').pop(), source, body })
})

Rules worth knowing:

  • GET and HEAD are sent without a body.
  • A body that is not a string is sent as JSON, with content-type: application/json unless you set one. A string body is sent as-is and also gets content-type: application/json, so read it with req.text().
  • With no body, the function receives a request with no body. A bare await req.json() throws, so write await req.json().catch(() => ({})) when the call can be made without a payload.
  • The body must be JSON: an object, array, string, number or boolean. A Blob, ArrayBuffer, typed array, FormData, URLSearchParams or ReadableStream is refused with the error code invalid_body before any request is sent.
  • Framing headers (content-length, transfer-encoding, connection, host, …) are ignored.
#
Identity

3. Read the caller's identity

The platform validates the key and the user's token before your function runs, then adds these headers:

HeaderValue
x-aura-roleanon, authenticated or service_role
x-aura-user-idThe user's id when x-aura-role is authenticated, otherwise absent
x-aura-project-idThe project id
authorizationThe user's JWT, only for a signed-in user
apikeyThe key used for the call
aurabase/functions/whoami/index.tstypescript
Deno.serve((req) => {
  if (req.headers.get('x-aura-role') !== 'authenticated') {
    return new Response('Sign in first', { status: 401 })
  }
  return Response.json({ userId: req.headers.get('x-aura-user-id') })
})

Real results of this call with three different keys:

results.jsonjson
{ "role": "anon",          "userId": null }
{ "role": "authenticated", "userId": "b125f8cd-ddc8-4042-9d9d-2e0aa3cebe51" }
{ "role": "service_role",  "userId": null }
A caller cannot forge these headers

The platform discards authorization, apikey, x-request-id and every x-aura-* header that a caller puts in headers, whatever their case. Only the values it verified itself reach your function. Other custom headers pass through unchanged.

No request id inside the function

The x-request-id of the call is not forwarded to your function. To correlate a call with a log line, generate your own id, send it in headers and log it in the function.

#
HTTP

4. Call over HTTP

Without the SDK, send a JSON object that describes the request. The body field is what your function receives.

terminalbash
curl -X POST "$AURA_URL/v1/functions/hello/invoke" \
  -H "apikey: $AURA_ANON_KEY" \
  -H "Content-Type: application/json" \
  -d '{"body":{"name":"Ada"}}'

Both apikey and Content-Type: application/json are required. Add Authorization: Bearer <user JWT> to call as a signed-in user. The default response is an envelope; the X-Aurabase-Invoke-Mode: raw header returns your function's own response instead, see non-JSON responses.

#
Result

5. Read the result

invoke never throws. It returns { data, error }:

result.tstypescript
const { data, error } = await aura.functions.invoke('hello', { body: { name: 'Ada' } })

if (error) {
  // error.status: HTTP status of the failure
  // error.message: the text your function returned, or the platform's explanation
  return
}
// data is null when the function returned no content (for example a 204)
if (data === null) return
console.log(data)

Test data rather than error when you need the value: TypeScript then knows it is not null. To handle failures precisely, read errors, timeouts and retries.

Last updated · Oct 12, 2026