Quickstart: Public API
This quickstart calls the Grona Public API from a terminal. You check that the Grona script is on a page, create a website campaign, open its variation in the visual editor and set the campaign live. Use it to see the request and response shapes before you build the calls into your own platform.
Before you start
Section titled “Before you start”-
Install the website script on the page you want to change. Campaigns created through the API run through it. See Quickstart: website.
-
Get a secret API key from Grona. It looks like
grona_sk_<keyId>_<secret>and is scoped to one workspace. It is a server-side secret: never put it in a browser, an app or a repository. -
Put the key in an environment variable, so the commands below never contain it:
Terminal window export GRONA_SECRET_KEY="grona_sk_<keyId>_<secret>"In production, load it from your secrets manager instead.
Every request goes to https://api.grona.ai with the key in the Authorization header. The workspace comes from the key; it is never part of the URL or the body.
Make the calls
Section titled “Make the calls”-
Check that the script is on the page.
Terminal window curl -sS https://api.grona.ai/v1/websites/verify-script \-H "Authorization: Bearer $GRONA_SECRET_KEY" \-H "Content-Type: application/json" \-d '{"url": "https://shop.example.com/"}'{"data": {"url": "https://shop.example.com/","script": { "status": "present", "checkedAt": "2026-10-20T09:28:43.162Z" }},"meta": { "workspaceId": "65e8a1c47d2f9b03e6a15c42" }}absentmeans the script was not found or the page could not be loaded. Fix the installation before you go on. See Verify installations. -
Create a campaign. This creates a general campaign, with one variation, on the home page.
externalIdis your own id for the campaign.Terminal window curl -sS https://api.grona.ai/v1/campaigns \-H "Authorization: Bearer $GRONA_SECRET_KEY" \-H "Content-Type: application/json" \-d '{"name": "Free delivery bar on the home page","url": "https://shop.example.com/","externalId": "CMP-1024"}'The response is
201 Created:{"data": {"id": "671a3c90e4b0a1f2c3d40011","externalId": "CMP-1024","name": "Free delivery bar on the home page","status": "paused","domain": "https://shop.example.com","script": { "status": "checking", "checkedAt": null },"createdAt": "2026-10-20T09:30:12.418Z","updatedAt": "2026-10-20T09:30:12.702Z","type": "general","pageTargeting": "specific","segmentId": null,"segmentValue": null,"variations": [{"id": "671a3c90e4b0a1f2c3d40012","name": "Free delivery bar on the home page - Variation","type": "variant","previewUrl": "https://shop.example.com/?gronaPreview=671a3c90e4b0a1f2c3d40012","editUrl": "https://api.grona.ai/v1/editor/launch?token=eyJhbGciOi...","generatedAt": "2026-10-20T09:30:12.731Z","expiresAt": "2026-10-20T09:45:12.731Z"}]},"meta": { "workspaceId": "65e8a1c47d2f9b03e6a15c42" }}New campaigns always start
paused. The script check on the page runs in the background, soscript.statusstarts aschecking.Leaving out
segmentIdandsegmentValuetargets every visitor on the page. To create an A/B test, target several pages or target a page variable, see Create campaigns from your platform. -
Open the editor link in a browser. Copy
variations[0].editUrlfrom the response into your browser. It opens the visual editor on your page, where you build the variation. The link is a secret and expires 15 minutes aftergeneratedAt, so open it straight away and do not store or log it.If it has expired, ask for a new one:
Terminal window curl -sS https://api.grona.ai/v1/variations/edit-link \-H "Authorization: Bearer $GRONA_SECRET_KEY" \-H "Content-Type: application/json" \-d '{"variationId": "671a3c90e4b0a1f2c3d40012"}'When you have saved the variation, open its
previewUrlto check it on your page. Preview records nothing. See Visual editor links. -
Set the campaign live. You can use Grona’s campaign id or your
externalIdin the path:Terminal window curl -sS -X PATCH https://api.grona.ai/v1/campaigns/CMP-1024/status \-H "Authorization: Bearer $GRONA_SECRET_KEY" \-H "Content-Type: application/json" \-d '{"status": "live"}'{"data": { "status": "live" },"meta": { "workspaceId": "65e8a1c47d2f9b03e6a15c42" }}Grona then rebuilds your workspace’s script and refreshes the CDN, so allow a few minutes before visitors see the variation. To stop the campaign, send
{"status": "paused"}to the same endpoint.
If a call fails
Section titled “If a call fails”Errors share one shape, with a machine-readable code and a readable message. The exceptions are 429 and 503, which you handle by status alone:
{ "error": { "code": "conflict", "message": "externalId `CMP-1024` is already used by another campaign." }}conflict on create means a campaign with that externalId already exists. That makes externalId a safe way to retry a create: a retry cannot make a duplicate. See Errors for every code.
Next steps
Section titled “Next steps”- Authentication for how keys work and how to rotate them.
- Create campaigns from your platform for A/B tests, traffic splits and multi-page campaigns.
- Conventions for ids, timestamps and the response envelope.