Function secrets, webhooks and logs
Keep keys out of your code, protect a function with a signed webhook, and read or limit its execution logs.
Keep secrets out of your code
Never paste an API key into function code. Add it as a secret and read it at runtime.
There are two places:
- Per function: in the function dialog, Environment Secrets (JSON), for example
{"STRIPE_KEY": "sk_..."}. These are stored encrypted. - Project-wide: in the sidebar under Configuration, choose Secrets & Env, then + Add Secret. Enter a Secret Key Name (such as
STRIPE_API_KEY) and a Secret Value, then Save & Encrypt Secret. Project secrets are encrypted, shown as dots in the list, and automatically available to your functions and your containers.
Inside a function, read them from env:
export default async function handler(req, { env }) {
const key = env.STRIPE_API_KEY;
// ...
}
Once saved, a secret's value is never shown again. To change it, add it again with the new value.
Protect a function that others call
A function with the HTTP / Webhook trigger can be called by anyone who knows its address, so treat it like a public page. Two things help:
- Check the caller in your code. The request is available to your handler, including its headers and raw body. For a service that signs its webhooks (a payment provider, for example), keep the provider's signing secret in Secrets & Env and verify the signature in your function before doing any work.
- Use PGB's signature check. If a request carries an
X-PGBHub-Signatureheader, in the formt=<unix timestamp>,v1=<hash>, it is verified against the function's signing secret:v1is a hash over<timestamp>.<raw request body>. A wrong or missing signature is refused with401, and a timestamp more than five minutes old or in the future is refused, which stops replayed requests. A function whose trigger type is a webhook requires this header on every call.
If you only need to keep strangers out, you can also limit which addresses may call your project on the Network Access page. Calls from other addresses are refused.
Read the logs
Choose Logs next to a function, or Execution Logs at the top of Functions Studio. The page shows total invocations, success rate and average duration, and a table of runs with request and response details and the output your function printed. You can filter by function.
Function logs are stored in your database and count toward your storage. Use the settings on the logs page to control this:
- Record All Runs
- Errors Only (Save Space)
- Disabled (0 Storage)
- Purge Old Logs to delete older history. You can also set how many days of logs to keep (from 1 to 365; the default is 30).
All services also appear together under Unified Logs in the sidebar.
Good to know
- Secrets are encrypted at rest and only decrypted when a function runs.
- A function that fails returns its error message and appears as Error in the list.
- Python functions run in a restricted sandbox and can import only a short list of standard modules (such as
json,re,datetime,math,hashlib,base64anduuid). Importing anything else fails with a clear message. - Turn logging down for very busy functions to save storage.
More guides in Console: functions, cron & jobs
Create and deploy a function
Write a function in the Console editor, choose a runtime and trigger, test it, and call it over HTTP.
Schedule work with Cron Jobs
Run a function, SQL, an action, an HTTP call or an email on a schedule, and read the run history.
Background tasks (jobs) with automatic retries
Hand slow or unreliable work to a background job that retries on its own, and watch its status in the Console.
Actions: named transactions with effects
Define a named SQL transaction once, call it from your app, an AI agent or a schedule, and trigger emails, queues and more after it commits.