{
  "asyncapi": "3.0.0",
  "info": {
    "title": "grapl public status events",
    "description": "Server-sent events over HTTP. The application is the grapl API server; it sends messages to clients. No public server origin is announced.",
    "version": "0.1.0"
  },
  "defaultContentType": "application/json",
  "channels": {
    "transactionStatus": {
      "address": "/v1/swap/status/{signature}/events",
      "messages": {
        "snapshot": {
          "name": "snapshot",
          "title": "snapshot",
          "summary": "Current observation when there is no durable event and no resume cursor. It does not advance the cursor.",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "properties": {
              "signature": {
                "type": "string",
                "pattern": "^[1-9A-HJ-NP-Za-km-z]{64,88}$"
              },
              "status": {
                "type": "string",
                "enum": [
                  "not_observed",
                  "finalized",
                  "failed"
                ]
              },
              "commitment": {
                "type": "string",
                "enum": [
                  "finalized"
                ]
              },
              "slot": {
                "type": [
                  "string",
                  "null"
                ],
                "maxLength": 39,
                "pattern": "^(0|[1-9][0-9]*)$"
              },
              "observedAt": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              }
            },
            "required": [
              "signature",
              "status",
              "commitment",
              "slot",
              "observedAt"
            ]
          },
          "examples": [
            {
              "name": "snapshot-1",
              "payload": {
                "signature": "1111111111111111111111111111111111111111111111111111111111111111",
                "status": "not_observed",
                "commitment": "finalized",
                "slot": null,
                "observedAt": null
              }
            }
          ],
          "x-sse": {
            "event": "snapshot",
            "retry": 3000
          }
        },
        "transaction.status": {
          "name": "transaction.status",
          "title": "transaction.status",
          "summary": "Durable finalized or failed observation. The SSE id equals payload.id; retain it as a decimal string for resumption.",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "properties": {
              "signature": {
                "type": "string",
                "pattern": "^[1-9A-HJ-NP-Za-km-z]{64,88}$"
              },
              "status": {
                "type": "string",
                "enum": [
                  "finalized",
                  "failed"
                ]
              },
              "commitment": {
                "type": "string",
                "enum": [
                  "finalized"
                ]
              },
              "slot": {
                "type": [
                  "string",
                  "null"
                ],
                "maxLength": 39,
                "pattern": "^(0|[1-9][0-9]*)$"
              },
              "observedAt": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "id": {
                "type": "string",
                "pattern": "^[1-9][0-9]{0,18}$"
              }
            },
            "required": [
              "signature",
              "status",
              "commitment",
              "slot",
              "observedAt",
              "id"
            ]
          },
          "examples": [
            {
              "name": "transaction.status-1",
              "payload": {
                "signature": "1111111111111111111111111111111111111111111111111111111111111111",
                "status": "finalized",
                "commitment": "finalized",
                "slot": "9007199254740993",
                "observedAt": "2026-10-12T12:00:00.000Z",
                "id": "9007199254740994"
              }
            },
            {
              "name": "transaction.status-2",
              "payload": {
                "signature": "1111111111111111111111111111111111111111111111111111111111111111",
                "status": "failed",
                "commitment": "finalized",
                "slot": "9007199254740993",
                "observedAt": "2026-10-12T12:00:00.000Z",
                "id": "9007199254740994"
              }
            }
          ],
          "x-sse": {
            "event": "transaction.status",
            "retry": 3000,
            "id": "$message.payload#/id"
          }
        },
        "complete": {
          "name": "complete",
          "title": "complete",
          "summary": "Terminal observation; close the client connection. A resumed terminal cursor can receive complete without replaying transaction.status.",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "properties": {
              "signature": {
                "type": "string",
                "pattern": "^[1-9A-HJ-NP-Za-km-z]{64,88}$"
              },
              "status": {
                "type": "string",
                "enum": [
                  "finalized",
                  "failed"
                ]
              },
              "commitment": {
                "type": "string",
                "enum": [
                  "finalized"
                ]
              },
              "slot": {
                "type": [
                  "string",
                  "null"
                ],
                "maxLength": 39,
                "pattern": "^(0|[1-9][0-9]*)$"
              },
              "observedAt": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              }
            },
            "required": [
              "signature",
              "status",
              "commitment",
              "slot",
              "observedAt"
            ]
          },
          "examples": [
            {
              "name": "complete-1",
              "payload": {
                "signature": "1111111111111111111111111111111111111111111111111111111111111111",
                "status": "finalized",
                "commitment": "finalized",
                "slot": "9007199254740993",
                "observedAt": "2026-10-12T12:00:00.000Z"
              }
            },
            {
              "name": "complete-2",
              "payload": {
                "signature": "1111111111111111111111111111111111111111111111111111111111111111",
                "status": "failed",
                "commitment": "finalized",
                "slot": "9007199254740993",
                "observedAt": "2026-10-12T12:00:00.000Z"
              }
            }
          ],
          "x-sse": {
            "event": "complete",
            "retry": 3000
          }
        },
        "heartbeat": {
          "name": "heartbeat",
          "title": "heartbeat",
          "summary": "Connection liveness only. This timestamp is not a transaction observation and does not advance the cursor.",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "properties": {
              "observedAt": {
                "type": "string",
                "format": "date-time"
              }
            },
            "required": [
              "observedAt"
            ],
            "additionalProperties": false
          },
          "examples": [
            {
              "name": "heartbeat-1",
              "payload": {
                "observedAt": "1970-01-01T00:00:00.020Z"
              }
            },
            {
              "name": "heartbeat-2",
              "payload": {
                "observedAt": "1970-01-01T00:00:00.040Z"
              }
            }
          ],
          "x-sse": {
            "event": "heartbeat",
            "retry": 3000
          }
        },
        "reconnect": {
          "name": "reconnect",
          "title": "reconnect",
          "summary": "The connection lifetime elapsed. Reconnect after retryAfterMs with the last durable event ID, if present.",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "properties": {
              "reason": {
                "type": "string",
                "const": "connection_lifetime"
              },
              "retryAfterMs": {
                "type": "integer",
                "const": 3000
              }
            },
            "required": [
              "reason",
              "retryAfterMs"
            ],
            "additionalProperties": false
          },
          "examples": [
            {
              "name": "reconnect-1",
              "payload": {
                "reason": "connection_lifetime",
                "retryAfterMs": 3000
              }
            }
          ],
          "x-sse": {
            "event": "reconnect",
            "retry": 3000
          }
        },
        "stream-error": {
          "name": "stream-error",
          "title": "stream-error",
          "summary": "Safe error after response headers. No private exception text is published. Stop automatic retry when retryable is false.",
          "contentType": "application/json",
          "payload": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string"
              },
              "retryable": {
                "type": "boolean"
              }
            },
            "required": [
              "code",
              "retryable"
            ],
            "additionalProperties": false
          },
          "examples": [
            {
              "name": "stream-error-1",
              "payload": {
                "code": "STREAM_UNAVAILABLE",
                "retryable": true
              }
            },
            {
              "name": "stream-error-2",
              "payload": {
                "code": "UNAUTHORIZED",
                "retryable": false
              }
            },
            {
              "name": "stream-error-3",
              "payload": {
                "code": "FORBIDDEN",
                "retryable": false
              }
            },
            {
              "name": "stream-error-4",
              "payload": {
                "code": "CURSOR_NOT_AVAILABLE",
                "retryable": false
              }
            }
          ],
          "x-sse": {
            "event": "stream-error",
            "retry": 3000
          }
        }
      },
      "parameters": {
        "signature": {
          "description": "Solana transaction signature: base58, 64–88 characters. See the OpenAPI handshake schema."
        }
      }
    }
  },
  "operations": {
    "streamTransactionStatus": {
      "action": "send",
      "title": "Stream transaction status",
      "channel": {
        "$ref": "#/channels/transactionStatus"
      },
      "summary": "Send six public SSE message types for one signature.",
      "description": "The server sends over an authenticated GET response. Last-Event-ID resumes only the matching signature and configured observer. Invalid cursors return HTTP 409 before the stream starts; after headers, failures use stream-error. Delivery can repeat after reconnect; deduplicate transaction.status by its string id. This is not a pool subscription or exactly-once delivery.",
      "security": [
        {
          "$ref": "#/components/securitySchemes/IntegrationKey"
        }
      ],
      "bindings": {
        "http": {
          "method": "GET",
          "bindingVersion": "0.3.0"
        }
      },
      "messages": [
        {
          "$ref": "#/channels/transactionStatus/messages/snapshot"
        },
        {
          "$ref": "#/channels/transactionStatus/messages/transaction.status"
        },
        {
          "$ref": "#/channels/transactionStatus/messages/complete"
        },
        {
          "$ref": "#/channels/transactionStatus/messages/heartbeat"
        },
        {
          "$ref": "#/channels/transactionStatus/messages/reconnect"
        },
        {
          "$ref": "#/channels/transactionStatus/messages/stream-error"
        }
      ]
    }
  },
  "components": {
    "securitySchemes": {
      "IntegrationKey": {
        "type": "httpApiKey",
        "name": "x-api-key",
        "in": "header"
      }
    }
  },
  "x-sse": {
    "contentType": "text/event-stream",
    "resumeHeader": "Last-Event-ID",
    "retry": 3000,
    "description": "Only transaction.status carries an SSE id. Authenticate the GET handshake with x-api-key; frame data is JSON. These extension fields describe SSE framing, not a standard AsyncAPI SSE binding.",
    "defaults": {
      "pollMs": 1000,
      "heartbeatMs": 15000,
      "maxDurationMs": 60000
    }
  },
  "x-provenance": {
    "publisherSha256": "9429a86dd81f060cfb95f60da43385f5745b08f083673a209aa6704c44107258",
    "scope": "Checked local publisher fixtures; no public deployment or real wallet transaction."
  }
}
