Skip to content

Slate API Keys and Webhooks: Setup Guide

Create a Read only key and a Full access key, turn on webhooks, add an endpoint, verify its signature and test it in sandbox. Then repeat the same steps in live.

Read

8 min read

Published On

Oct 29, 2026

Read: 8 minutes

Last updated: November 10, 2026

In this guide

  • Full access keys read and write. Read only keys can only read, and writes are refused with a 403
  • A key is shown once, so store it before you close the dialog
  • Webhooks are one switch, then an embedded portal where you add endpoints and choose events
  • Sandbox and live are separate. Set up both

Two Kinds of Key, and Who Should Hold Each

Open Developers in the sidebar, then API keys. The page is titled "Create and manage keys for the Slate API". Choose "Create API Key" and pick one of two access levels.

AccessWhat it can doWho should hold it
Full accessRead and write. Create customers, attach data, create requestsYour backend servers, and nobody else
Read onlyGET requests only. Any write is refused with a 403Analytics, dashboards, support tools and anything that only needs to look

The reason to have both is blast radius. A reporting job does not need the power to create customers. If its key ends up in a log file or a shared spreadsheet, a Read only key can leak data but cannot change anything.


Create Your First Keys

  1. Check which dashboard you are in. Sandbox shows a banner at the top, and keys made there only work in sandbox.
  2. Go to Developers, then API keys, and choose "Create API Key".
  3. Pick "Full access" or "Read only".
  4. Copy the key from the "API Key Created" dialog and put it in your secrets manager straight away. The dialog shows it once.
  5. Check the new row. It lists the key as a prefix, dots and the last four characters, with an Access badge and a Created date.

There is no way to see a key again. If you lose it, create a new key and revoke the old one. The page has no key naming, expiry or rotation settings, so keep your own record of which key is used where: system, access level and who created it.

You can also create a key from the Home checklist in sandbox, in the step called "Create an API key". It produces the same kind of key.


Make a Call With Each Key

Slate reads the key from the x-api-key header. The live API is at https://api.tryslatehq.com and the sandbox API is at https://api-sandbox.tryslatehq.com. Every list page has an "API reference" button with snippets for that page's operations. Copy the path and body from there, and send the key in x-api-key. The full reference is at tryslatehq.apidocumentation.com/slate-api.

A good first test proves the access levels do what they say. List customers with the Read only key and expect a normal answer. Then try to create a customer with the same key and expect a 403. With the Full access key, the same create call should succeed.

# 1) Read with the Read only key: expect 200
curl -s -o /dev/null -w "%{http_code}\n" \
  -H "x-api-key: $SLATE_READ_KEY" \
  https://api-sandbox.tryslatehq.com/customers

# 2) Write with the same key: expect 403
curl -s -o /dev/null -w "%{http_code}\n" -X POST \
  -H "x-api-key: $SLATE_READ_KEY" \
  -H "Content-Type: application/json" \
  -d '<body from the Create a customer sheet>' \
  https://api-sandbox.tryslatehq.com/customers

Run the same two calls with the Full access key. If both behave as described, you know your keys are what you think they are before anyone builds on them.


Habits That Keep Keys Safe

  1. Keep the Full access key on the server only. Never ship it in a mobile app, a browser bundle or a public repository.
  2. Give each system its own key. When one system is retired or compromised, you revoke one key and nothing else breaks.
  3. Prefer Read only wherever a system only looks.
  4. Record each key in your own inventory with its access level, owner and use, since the page shows only a prefix and the last four characters.

Your customers' browsers need a different credential, not your secret key. The embed icon on each Product page shows three steps: create a user session token on your server, embed the component, and listen for its events.


Revoke a Key That Should Not Exist

Each row has a trash icon labelled "Revoke key" that opens a confirmation dialog. Revoking is immediate and cannot be undone, and anything still using the key starts failing right away. If a key may have leaked, create its replacement first, deploy it, then revoke the old one. If you are certain the key is exposed and cannot wait, revoke first and accept the downtime.


Turn On Webhooks

Webhooks tell your system when something happens at Slate, so you do not have to keep asking. Go to Developers, then Webhooks. The page is titled "Webhook endpoints that receive Slate events". Flip the switch "Enable Webhooks". An embedded webhook portal appears, where you add endpoints, choose which events each one receives and see delivery attempts and retries. Webhooks are self-serve, and each environment has its own setup.

  1. Stand up an HTTPS URL that accepts a POST and returns a 2xx status quickly.
  2. In the portal, add that URL as an endpoint and choose events. Start with the two or three your product reacts to first.
  3. Trigger something in sandbox, such as creating a customer, and watch the delivery appear in the portal.
  4. If a delivery fails, read the attempt in the portal, fix your side and trigger it again.

Every event has the same shape: event_type, a data object with the id of the thing that changed, and a timestamp. Webhooks are notifications, not payloads, so fetch the current state from the API when one arrives. Examples are customer.created, preapproval.created, application.submitted, application.approved, financing-agreement.payment.failed and credit-line.draw.funded. There are dozens, and the portal lists them all.


Verify Every Delivery

Slate delivers webhooks with Svix and signs every request. Each carries svix-id, svix-timestamp and svix-signature headers, and each endpoint has a signing secret starting whsec_, shown with its webhook information in the dashboard. The svix-id is the same when a message is resent, so store it and skip repeats. Check the signature on the raw body before you trust anything.

import crypto from "node:crypto";

export function verify(rawBody, headers, secret) {
  const key = Buffer.from(secret.replace("whsec_", ""), "base64");
  const signed = `${headers["svix-id"]}.${headers["svix-timestamp"]}.${rawBody}`;
  const expected = crypto.createHmac("sha256", key).update(signed).digest("base64");
  return headers["svix-signature"].split(" ").some((part) => {
    const sig = part.split(",")[1] ?? "";
    return sig.length === expected.length &&
      crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
  });
}

Return 200 quickly and do the real work afterwards, so a slow database never turns into a failed delivery. Make your handler safe to run twice.


Choosing Events Without Drowning

It is tempting to subscribe to everything. Every event you subscribe to is one your handler has to understand, log and test. Begin with the smallest set that drives something your customer can see.

If your product needs toStart with
Show a customer that an offer existspreapproval.created
Update a status line when someone appliesapplication.submitted, application.approved, application.rejected
Reflect that money has been fundedfinancing-agreement.created, financing-agreement.disbursed
Alert your team to a failed paymentfinancing-agreement.payment.failed
Send your own customer emailsThe event listed next to each email on the Emails, Templates tab

Repeat Everything in Live

Sandbox and live do not share keys or webhook settings. In the live dashboard, open Developers and repeat both steps: create the keys you need, enable webhooks, add the production endpoint and choose the events. Write the setup down once as a short runbook, then follow it twice.


Common Questions

Can I name a key or set an expiry?

Not in the dashboard. Keep your own record of where each key is used, and replace keys on your own schedule.

What does a Read only key do on a write?

The write is refused with a 403. Reads work normally.

I closed the dialog without copying my key. Now what?

Create a new key, update whatever needs it and revoke the lost one. The dialog shows a key only once.

Do my sandbox webhook endpoints carry over to live?

No. Webhooks are set up per environment, so add your endpoint again in live.

Is there an SDK?

The Partners SDK is published as @tryslatehq/partners-sdk on npm, and the help panel links to it.


Read next: Your First Week on Slate · What to Expect When You’re Onboarding With Slate

Talk to an expert to see a demo and estimate your revenue.

Chat with our team about how Slate can help you offer embedded capital to your customers.