Skip to content
All articles

Product guides

Posting records from your backend with an account key

The Records API now accepts an account API key, so one secret can feed every widget. How to switch, which key level to use, and what the records look like.

Provedly team··6 min read

Until now, a backend that sent purchases to Provedly used one key per widget, generated on that widget's Data tab. That works for one widget. For a business with several sites or several widgets, it meant several secrets to store and rotate. The Records API now also accepts an account API key, the same provedly_ key used by the REST API and the MCP server, so one secret can cover every widget on the account.

This post explains when to switch, how, and what does not change. The full field reference is still in the Records API guide.

What changed and what did not

The endpoint is the same:

POST https://provedly.app/api/v1/widgets/{token}/records
Authorization: Bearer <widget key or account key>
Content-Type: application/json

The fields are the same: name, city, state, country, product_name, price, avatar_url, external_id, occurred_at and visitor. Duplicate external_id values are still rejected per widget, so retries remain safe.

What changed is the header. You can now send an account key with the Read and write access level instead of the widget's own key. A read-only account key is refused on this endpoint, because adding a record is a write.

Widget keys keep working. Nothing breaks if you leave an existing integration alone.

When to use which key

Keep the widget key when the integration only ever writes to one widget and you like the narrow scope. A leaked widget key can only add records to that widget.

Use an account key when one service writes to several widgets, for example a checkout service that serves three storefronts, each with its own widget. One secret in the environment, the widget chosen by the token in the URL.

If you switch, create a dedicated key for the service in Settings, under API keys, and name it after the service: "Checkout service, production". Do not reuse the key you gave your AI assistant. Separate keys let you revoke one without breaking the other.

A worked example

A service that handles paid orders for two storefronts might look like this in outline:

const WIDGETS = {
    'shop-eu': 'pp_eu_widget_token',
    'shop-us': 'pp_us_widget_token',
};

async function sendRecord(order) {
    const token = WIDGETS[order.storefront];
    const res = await fetch(
        `https://provedly.app/api/v1/widgets/${token}/records`,
        {
            method: 'POST',
            headers: {
                Authorization: `Bearer ${process.env.PROVEDLY_KEY}`,
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({
                name: order.customerFirstName,
                city: order.city,
                country: order.countryCode,
                product_name: order.productName,
                price: order.displayPrice,
                external_id: order.id,
                occurred_at: order.paidAt,
                visitor: order.provedlyVisitorId,
            }),
        },
    );
    if (res.status === 422) return; // duplicate external_id or invalid data
    if (!res.ok) throw new Error(`Provedly ${res.status}`);
}

Call it after payment is confirmed, never on order creation. A record for a checkout that later failed is a notification about a purchase that did not happen.

The visitor field carries the Provedly visitor id from the browser, which is what lets the order count toward proof-assisted orders in your stats. Without it, the record still displays, and the attribution metric simply leaves it out. See measuring proof-assisted orders.

How these records appear

Records posted through the API keep the API source, whichever key you use. They show in the widget with a visible "Imported" label and without the Verified mark, and the public verification page counts them under "Site owner's backend (API)".

If your orders go through Stripe, Shopify or WooCommerce, the signed webhook connection is the better route: those records arrive verified with no code on your side. The Records API is for everything those connections do not cover. Why your assistant cannot verify a purchase explains why an API call, however it is authenticated, cannot produce a verified record.

Checking it from your assistant

The same account is visible to your AI assistant through the MCP server, with a separate key. After deploying the change, you can ask:

List my widgets and give me stats for the last day.

and compare the answer with your own order log. The prompt cookbook has more examples. If you want to test the integration by hand first, the assistant can call add_record for a single real order, which is a quick way to see exactly how a record renders.

Frequently asked questions

Does an account key let me post to a widget on another account?

No. An account key only works for widgets that belong to its own account. A token from another account is refused.

Should I rotate my widget keys now?

Only if you are moving to an account key. Once the service uses the new key, rotate the old widget key on the widget's Data tab so it no longer works.

Is there a bulk endpoint for history?

No. For past orders, use CSV import on the widget's Data tab, described in importing past orders from CSV. The API is for the live stream.

The Records API and account keys are available on the Free plan: create an account.

apirecordsbackendapi keys

Get new articles by email

Honest social proof, verified purchases and what actually moves conversion. A few emails a month at most; leave with one click.

We email you once to confirm. Your address is used only for this newsletter; see the privacy policy.

Show proof you can stand behind.

Free plan, one site, 2,000 impressions a month, verified purchases included. The badge on the free plan links to your verification page, which is the point.