Givebear LogoGivebear
Connect API

Embedded components

Drop read-only donations, donors, and payouts tables into your product with a component session and three custom elements.

Show a connected organization's donations, donors, or payouts inside your own product without building tables or wiring the API yourself. Your backend mints a short-lived component session; the browser renders custom elements that fetch, paginate, and style themselves, like Stripe Connect's embedded components.

Prerequisites

  • Your app is connected to the organization through OAuth, or you hold the org's API key.
  • The credential holds the read scope behind each component you want: donations:read for donations, donors:read for donors, payouts:read for payouts.
  • @givebear/connect 0.2.0 or later in the browser bundle.

Steps

Mint a component session on your backend

Call POST /component-sessions with the components your page renders. The session's browser token can only read those resources, and only if your own credential could.

curl -X POST "https://givebear.io/api/v1/component-sessions" \
  -H "Authorization: Bearer gb_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "components": ["donations", "payouts"] }'
import { GivebearConnect } from "@givebear/connect";

const gb = new GivebearConnect({ token: "gb_live_..." });

const session = await gb.componentSessions.create({
  components: ["donations", "payouts"],
});
// session.token is returned only once. Send it to your frontend.
import requests

session = requests.post(
    "https://givebear.io/api/v1/component-sessions",
    headers={"Authorization": "Bearer gb_live_..."},
    json={"components": ["donations", "payouts"]},
).json()
<?php
$ch = curl_init("https://givebear.io/api/v1/component-sessions");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "Authorization: Bearer gb_live_...",
    "Content-Type: application/json",
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
    "components" => ["donations", "payouts"],
]));
$session = json_decode(curl_exec($ch), true);
curl_close($ch);
require "net/http"
require "json"

uri = URI("https://givebear.io/api/v1/component-sessions")
request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer gb_live_..."
request["Content-Type"] = "application/json"
request.body = { components: ["donations", "payouts"] }.to_json

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
  http.request(request)
end
session = JSON.parse(response.body)
body := strings.NewReader(`{ "components": ["donations", "payouts"] }`)
req, _ := http.NewRequest("POST", "https://givebear.io/api/v1/component-sessions", body)
req.Header.Set("Authorization", "Bearer gb_live_...")
req.Header.Set("Content-Type", "application/json")

resp, err := http.DefaultClient.Do(req)

The response includes token (gbct_...) exactly once, plus components and expires_at. Sessions expire after one hour and are reusable until then, so page reloads keep working. Mint a fresh session per page view; do not store tokens.

Render the components

Import the components module once (it registers the custom elements), then place elements with the session token. Each element renders its own loading, empty, and error states, plus a "Load more" pager.

<script type="module">
  import "@givebear/connect/components";
</script>

<givebear-donations session="gbct_..."></givebear-donations>
<givebear-payouts session="gbct_..." limit="5"></givebear-payouts>
import "@givebear/connect/components";

export function DonationsPanel({ token }: { token: string }) {
  return (
    <>
      <givebear-donations session={token} />
      <givebear-payouts session={token} limit="5" />
    </>
  );
}

Using TypeScript with React? Declare the elements once (for example in globals.d.ts) so JSX accepts them:

type GivebearElementProps = React.HTMLAttributes<HTMLElement> & {
  session: string;
  limit?: string;
  "base-url"?: string;
};

declare global {
  namespace React.JSX {
    interface IntrinsicElements {
      "givebear-donations": GivebearElementProps;
      "givebear-donors": GivebearElementProps;
      "givebear-payouts": GivebearElementProps;
    }
  }
}

Handle expiry

When the session expires the element shows a notice and dispatches a bubbling givebear:session-expired event. Listen for it, mint a fresh session on your backend, and update the session attribute; the element reloads itself.

document.addEventListener("givebear:session-expired", async () => {
  const { token } = await fetch("/api/my-givebear-session").then((r) => r.json());
  for (const el of document.querySelectorAll("[session]")) {
    el.setAttribute("session", token);
  }
});

Elements and attributes

ElementShowsNeeds scope
<givebear-donations>Donor, fund, amount (with a recurring pill), datedonations:read
<givebear-donors>Name, email, location, date addeddonors:read
<givebear-payouts>Amount, status, initiated and arrival datespayouts:read

Every element takes the same attributes.

AttributeMeaning
sessionThe component session token (gbct_...). Required.
limitRows per page, 1 to 100 (default 10).
base-urlAPI origin override (default https://givebear.io).

Failures other than expiry dispatch a bubbling givebear:error event with detail.message and, for HTTP errors, detail.status.

Theming

The elements render in an isolated shadow root with a neutral look. Override CSS custom properties on the element or any ancestor:

givebear-donations {
  --givebear-font: "Inter", sans-serif;
  --givebear-accent: #7c3aed;
  --givebear-fg: #1c1917;
  --givebear-muted: #78716c;
  --givebear-border: #e7e5e4;
  --givebear-bg: #ffffff;
  --givebear-radius: 8px;
}

How the security model works

The browser token is read-only by construction: its scopes are derived from the requested components (all *:read), capped by what your backend credential holds, and it cannot mint further sessions. It expires after one hour. Donor names and emails are visible to whoever holds the token, so only render these components to users who should see the organization's data.

Was this page helpful?

On this page