Skip to main content
developers/donations-sdk/getting-started
Developer12 min read

Getting Started

Add a working donation flow to any website in five minutes. Copy-paste snippet for HTML, React, and WordPress, plus an introduction to keys and sandbox mode.

Getting Started

This guide takes you from "no integration" to "donor flow live in sandbox" in five minutes. By the end you will have a working donation form on a page you control, taking a sandbox card payment that triggers a real webhook delivery to a URL of your choosing.

What you need

  1. A 1st Flock account with the Donations Embed product enabled. If you do not yet, sign up at account.1stflock.com and add the Donations Embed product from your subscription page.
  2. A page on a site you control. This can be a static HTML file you serve from any web server, a WordPress page, a React or Next.js component, or any platform that lets you paste an HTML snippet.

That is the entire prerequisite list. There is no separate dashboard, no credit-card vault to set up, no PCI form to file before you start. Card data is tokenised inside an isolated iframe before it ever reaches your code, so this integration is in PCI SAQ A scope from the moment you paste in the snippet.

Sandbox testing {#sandbox-testing}

Every integration page in this guide refers back to this section for the canonical test inputs. Use these inputs against any pk_test_… key — no real money moves and the donation appears in the Hub with a TEST badge.

Card payments

FieldValue
Card number4111 1111 1111 1111
ExpiryAny future date (examples use 10/29)
CVVAny 3 digits (examples use 123)
ZIPAny valid postal code (no AVS validation in sandbox)

This single test card always succeeds in sandbox. To exercise the failure path, use card number 4000 0000 0000 0002 (universal "card declined" tester) — the donor flow surfaces a card_declined flock-donation-failed event and your server-side donation row records status: "failed".

ACH bank-link payments

ACH in sandbox is gateway-restricted: the underlying gateway sandbox accepts only its own internal allowlist of test routing/account numbers, which the public bank-link sandbox does not vend. If you need to verify your ACH integration end-to-end against a real test bank pair, ask your account manager for the 1st Flock sandbox test bank credentials — they cannot be self-served from the public sandbox today.

The good news: sandbox ACH still exercises every line of YOUR integration code (session create, bank-link token vend, public-token exchange, /v1/embed/sessions/

/confirm). The only failure is on the gateway hop — a clear ach_account_not_in_test_whitelist donation.failed payload — so you can confirm your handler correctly routes a failed ACH event without ever moving a real dollar.

Test mode vs live mode {#test-mode-vs-live-mode}

Note: The same code works in test mode and live mode — only the key changes.

AspectTest mode (pk_test_* / sk_test_*)Live mode (pk_live_* / sk_live_*)
Money movementNone — every charge is simulated.Real cards, real ACH, real money.
Test card numbers (4111 …, 4000 0000 0000 0002)Work as documented.Rejected — production gateways do not accept test cards.
Webhook deliveryFires normally so you can exercise your handler end-to-end.Fires normally; donor-facing receipts also send.
Hub displayTEST badge on every row; never appears in the production ledger.Production ledger row, donor receipt issued.
Merchant approval requiredNo — you can use test mode the moment you create a 1st Flock account.Yes — your organisation must complete merchant onboarding before live keys are issued.
RoutingSandbox cluster (https://api.sandbox.1stflock.com).Production cluster (https://api.1stflock.com).

The key prefix is the only switch. There is no flag, no environment variable, no configuration file that toggles between sandbox and live — the SDK and embed look at the prefix on every call and route accordingly. Mixing keys is rejected at the API edge: a sandbox publishable key paired with a production secret key returns a 401.

The browser embed bundle is also environment-paired: load https://payments.1stflock.com/v1.js for live, and https://sandbox.payments.1stflock.com/v1.js for sandbox. The two hosts are paired with their key prefixes.

Cross-mismatch enforcement. If you load the SDK from payments.1stflock.com but supply a pk_test_* key, the SDK throws with: Live SDK cannot use test keys. Load https://sandbox.payments.1stflock.com/v1.js instead. Same in reverse for sandbox.payments.1stflock.com + pk_live_*.

Step 1: Generate a sandbox key pair

In the 1st Flock account portal:

  1. Open Donations Embed → Keys.
  2. Click Create key pair.
  3. Set the environment to Sandbox and give the pair a descriptive name (for example, My laptop or Marketing site staging).
  4. Copy the publishable key (starts with pk_test_) — you will paste this into the snippet in Step 2.
  5. If you also plan to call the server SDK, copy the secret key (starts with sk_test_) into your secrets manager immediately. The portal shows the secret only once at creation time; once you navigate away, the only way to recover access is to rotate the key pair.

Important: Never paste a secret key (sk_…) into a browser, into HTML, into a React component, or into any code that ships to a customer device. Secret keys belong in your server's environment variables only. Publishable keys (pk_…) are safe to ship to the browser — that is what they exist for.

Step 2: Add the donation flow to your page

Pick the snippet that matches how your site is built.

Paste this anywhere in the body of your HTML. Replace pk_test_REPLACE_ME with the publishable key you copied in Step 1.

<flock-donate
  publishable-key="pk_test_REPLACE_ME"
  mode="inline"
></flock-donate>
<script type="module" src="https://sandbox.payments.1stflock.com/v1.js"></script>

That single web component plus the script tag is the entire integration. The flow renders inline at the spot where you placed the tag. Set mode="modal" or mode="drawer" to render a launcher button that opens the flow in an overlay or side drawer instead.

When you switch to live, change the script src to https://payments.1stflock.com/v1.js and the publishable key to your pk_live_… value at the same time — the two are paired.

:::

Step 3: Make a sandbox donation

Open the page in a browser. You should see the donation flow rendered inline (or, if you set mode="modal", a "Give" button that opens the flow in an overlay). Walk through the steps the way a real donor would:

  1. Amount — pick a suggested amount or enter a custom one.
  2. Fund — your default fund is pre-selected.
  3. Cover fees — toggle as you wish.
  4. Donor info — any name and email work in sandbox.
  5. Payment — use the canonical sandbox card from the Sandbox testing section above (4111 1111 1111 1111, exp 10/29, CVV 123).
  6. Confirm — click Donate.

You should see a success screen with a confirmation ID like don_8a1b9c4d. The donation appears in the Donations tab of your 1st Flock hub within a few seconds, marked with a TEST badge so it is unmistakable that no real money moved.

If the flow fails or the embed does not render, see the Common pitfalls section below.

Step 4: Add a server integration (optional)

If you want to receive donation notifications, generate receipts, or sync donations into your own ledger, install the server SDK in the language that matches your stack.

npm install @1st-flock/donations-embed-node

:::

A minimal "list the most recent donations" call:

import { Client } from "@1st-flock/donations-embed-node";

const client = new Client({ apiKey: process.env.FLOCK_SECRET_KEY! });
const page = await client.listDonations({ limit: 25 });
for (const donation of page.donations) {
  console.log(donation.confirmation_id, donation.gross_amount_cents);
}
import os
import asyncio
from donations_embed import Client

async def main() -> None:
    async with Client(api_key=os.environ["FLOCK_SECRET_KEY"]) as client:
        page = await client.list_donations(limit=25)
        for donation in page.donations:
            print(donation.confirmation_id, donation.gross_amount_cents)

asyncio.run(main())
package main

import (
    "context"
    "fmt"
    "log"
    "os"

    donationsembed "gitlab.com/1st-flock/donations/go/donations-embed"
)

func main() {
    c, err := donationsembed.New(os.Getenv("FLOCK_SECRET_KEY"))
    if err != nil {
        log.Fatal(err)
    }
    page, err := c.ListDonations(context.Background(), &donationsembed.ListDonationsParams{Limit: 25})
    if err != nil {
        log.Fatal(err)
    }
    for _, d := range page.Donations {
        fmt.Println(d.ConfirmationID, d.GrossAmountCents)
    }
}

The full server SDK reference — including refunds, recurring schedules, error handling, retries, and webhook verification — is in Server SDKs.

Sandbox vs Live

The full sandbox / live comparison is documented in Sandbox testing → Test mode vs live mode earlier on this page.

For a complete end-to-end test of your live integration before you go public, generate a live key pair, swap the keys in your code, and run a real $1 donation against your own card. Refund yourself when you are done. The total round-trip cost is a few cents in processor fees.

Authentication & keys

There are two key types:

  • Publishable keys (pk_live_…, pk_test_…) — safe to ship to a browser. The embed authenticates with these. They are scoped to one or more origin patterns ("origin allowlist") so a leaked publishable key cannot be used from a domain you do not control.
  • Secret keys (sk_live_…, sk_test_…) — server-side only. They authenticate the SDKs. The Hub portal shows them once at creation time. Treat them like any other production credential — store in a secrets manager, rotate on suspicion of compromise, never commit to source control.

A key pair is frozen automatically if our card-testing detector observes a burst of declined attempts on the publishable key. When this happens, the pair is taken out of service and a key.frozen webhook is delivered. To recover, rotate the affected pair via the Hub and update your deployments to use the new keys.

For complete details on key creation, rotation, revocation, and origin allowlists, see Operations → Keys.

Common pitfalls

Note: The embed does not render. Check the browser console. The most common causes are: (1) the <script> tag is missing or its src is wrong, (2) the publishable key is mistyped, or (3) your site's Content Security Policy is blocking the script. The CSP recipe is in Compliance & Security.

Note: The donor reaches the success screen but no donation shows in the Hub. Make sure you used a sandbox key (pk_test_…); donations made with sandbox keys never appear in the production view. Switch the production / sandbox toggle in the Hub.

Note: A "key frozen" message appears in the embed. Your key pair was taken out of service by the automatic protection. Rotate the pair from the Hub and update your snippet with the new publishable key.

Note: The styling does not match my site. That is by design — the embed renders inside Shadow DOM with its own stylesheet so your site's CSS does not collide with it. To brand the embed, edit the theme JSON in Donations Embed → Theme in the Hub. The four built-in presets are modern, minimal, classic, and playful; pick one and override individual tokens as needed. See Browser Embed → Theming for the full token catalogue.

Next steps

Developer Portal