Create an editor link
package main
import ( "fmt" "strings" "net/http" "io")
func main() {
url := "https://api.grona.ai/v1/variations/edit-link"
payload := strings.NewReader("{ \"variationId\": \"671a3c90e4b0a1f2c3d40012\" }")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>") req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close() body, _ := io.ReadAll(res.Body)
fmt.Println(res) fmt.Println(string(body))
}OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json");RequestBody body = RequestBody.create(mediaType, "{ \"variationId\": \"671a3c90e4b0a1f2c3d40012\" }");Request request = new Request.Builder() .url("https://api.grona.ai/v1/variations/edit-link") .post(body) .addHeader("Authorization", "Bearer <token>") .addHeader("Content-Type", "application/json") .build();
Response response = client.newCall(request).execute();const url = 'https://api.grona.ai/v1/variations/edit-link';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"variationId":"671a3c90e4b0a1f2c3d40012"}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://api.grona.ai/v1/variations/edit-link \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "variationId": "671a3c90e4b0a1f2c3d40012" }'Returns a new editor link for a variation. The token in the link expires 15 minutes after
generatedAt. generatedAt and expiresAt describe editUrl only and are read from the
token itself, so they always agree with the link.
The token travels in the query string. Open the link right away and do not store, log or forward it.
Authorizations
Section titled “Authorizations”Request Bodyrequired
Section titled “Request Bodyrequired”object
A variation id from variations[].id on create, list or get.
Example
{ "variationId": "671a3c90e4b0a1f2c3d40012"}Responses
Section titled “Responses”OK.
object
object
Editor link. Its token expires 15 minutes after generatedAt.
The page with the variation’s saved changes applied. It does not expire.
ISO 8601 in UTC, with millisecond precision.
ISO 8601 in UTC, with millisecond precision.
object
The workspace resolved from the secret key.
Example
{ "data": { "editUrl": "https://api.grona.ai/v1/editor/launch?token=eyJhbGciOi...", "variationId": "671a3c90e4b0a1f2c3d40012", "previewUrl": "https://shop.example.com/?gronaPreview=671a3c90e4b0a1f2c3d40012", "generatedAt": "2026-10-20T11:12:05.614Z", "expiresAt": "2026-10-20T11:27:05.614Z" }, "meta": { "workspaceId": "65e8a1c47d2f9b03e6a15c42" }}variationId is missing or is not a valid id. error.code is invalid_request.
object
object
Stable and machine-readable. Branch on this, and on the HTTP status for codes you do not know.
Human-readable. The wording can change, so do not parse it.
Example
{ "error": { "code": "invalid_request", "message": "`variationId` is not a valid id." }}The secret key is missing, malformed, unknown or revoked. error.code is unauthorized.
object
object
Stable and machine-readable. Branch on this, and on the HTTP status for codes you do not know.
Human-readable. The wording can change, so do not parse it.
Example
{ "error": { "code": "unauthorized", "message": "Missing or invalid API key." }}No variation with this id exists in the key’s workspace, for example because its
campaign was deleted. error.code is not_found.
object
object
Stable and machine-readable. Branch on this, and on the HTTP status for codes you do not know.
Human-readable. The wording can change, so do not parse it.
Example
{ "error": { "code": "not_found", "message": "Variation not found." }}Too many requests. Retry with exponential backoff and jitter, and wait at least as long
as Retry-After when it is present. Branch on the status code; the body is not
guaranteed to use the error envelope.
Headers
Section titled “Headers”How long to wait before retrying, in seconds or as an HTTP date.
Unexpected server error. error.code is internal_error. Retry with backoff; if it
persists, contact support@grona.ai with the time of the request and the endpoint.
object
object
Stable and machine-readable. Branch on this, and on the HTTP status for codes you do not know.
Human-readable. The wording can change, so do not parse it.
Example
{ "error": { "code": "internal_error", "message": "Something went wrong on our side." }}Temporarily unavailable. Retry with exponential backoff and jitter, and wait at least as
long as Retry-After when it is present. Branch on the status code; the body is not
guaranteed to use the error envelope.
Headers
Section titled “Headers”How long to wait before retrying, in seconds or as an HTTP date.