Browse documentation
Tutorial JSON:API

Perform an idempotent write

Create one test dashboard through JSON:API, replay the identical request safely, and recognize a conflicting key reuse.

Goal: Create exactly one dashboard even when the client repeats the same request.

View as Markdown

Create one harmless dashboard configuration, replay the identical request, and prove that the second attempt does not create a duplicate. Use a disposable non-production workspace and remove the test dashboard through the application when finished.

What you will do

  1. Prepare one JSON:API dashboard document.
  2. Send it with a stable Idempotency-Key.
  3. Repeat the exact method, path, body bytes, and key.
  4. Verify idempotency-replayed: true.
  5. See why reusing that key for different input returns 409.

Prerequisites

  • A service account in the test workspace with api_write.
  • An active run-as member authorized to create dashboards.
  • HODOFLOW_BASE_URL, TOKEN, cURL, and jq.
  • A plan to delete the test dashboard in the Hodoflow application afterward.

Do not run this tutorial against production configuration. Read Scopes and run-as permissions before granting write access.

Request

Create the request body as a file so every retry uses identical bytes:

REQUEST_FILE="$(mktemp)"
IDEMPOTENCY_KEY="docs-dashboard-$(date -u +%Y%m%d)-001"
jq -n '{
data: {
type: "dashboard",
attributes: {
name: "API idempotency verification",
description: "Disposable dashboard created by the developer guide"
}
}
}' > "$REQUEST_FILE"

Send the first request and keep its headers visible:

curl --silent --show-error --include \
--request POST \
--header "Accept: application/vnd.api+json" \
--header "Content-Type: application/vnd.api+json" \
--header "Authorization: Bearer $TOKEN" \
--header "Idempotency-Key: $IDEMPOTENCY_KEY" \
--data-binary "@$REQUEST_FILE" \
"$HODOFLOW_BASE_URL/api/json/v1/dashboards"

Repeat that exact command without changing the file or key. Then, only as a conflict exercise, change the dashboard name while keeping the old key and send again. The changed request must not execute.

Expected response

The first request returns 201 and one dashboard resource:

{
"data": {
"type": "dashboard",
"id": "00000000-0000-4000-8000-000000000001",
"attributes": {
"name": "API idempotency verification",
"description": "Disposable dashboard created by the developer guide"
}
}
}

The identical replay returns the stored status and body with:

idempotency-replayed: true

The altered body with the same key returns 409 and the stable idempotency_key_reused code. It does not create or update another dashboard. Keys are retained for 24 hours by default, though deployments can configure the window.

Troubleshooting

  • 401: exchange once, then retry with the same key and body.
  • 403: the account lacks api_write, the run-as member cannot create a dashboard, or a plan limit applies. Correct access; do not loop.
  • 409 idempotency_key_in_progress: wait briefly and repeat the identical request.
  • 409 idempotency_key_reused: reconcile the caller bug; do not hide it behind a new key.
  • 422: compare the body with the create dashboard reference.
  • 429 or 5xx: wait according to headers/backoff and retry with the same key.

Remove the temporary file and sensitive variables, then delete the test dashboard through the application:

rm "$REQUEST_FILE"
unset REQUEST_FILE IDEMPOTENCY_KEY

Next steps

Related documentation