{
  "openapi": "3.2.0",
  "info": {
    "title": "Anchorify Notarization API",
    "description": "REST API for creating and retrieving blockchain notarizations. Notarize document hashes with cryptographic timestamps and multi-blockchain anchoring.",
    "version": "1.0.0",
    "contact": {
      "name": "Anchorify",
      "url": "https://anchorify.cloud"
    }
  },
  "servers": [
    {
      "url": "https://api.anchorify.cloud",
      "description": "Production"
    }
  ],
  "security": [
    {
      "ApiKeyAuth": []
    }
  ],
  "paths": {
    "/v1/notarizations": {
      "post": {
        "operationId": "createNotarization",
        "summary": "Create a notarization",
        "description": "Submit a document hash for notarization. The hash will be timestamped (RFC 3161) and anchored on one or more blockchains via a Merkle tree accumulator.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateNotarizationRequest"
              },
              "example": {
                "name": "contract-v2.pdf",
                "external_id": "invoice-2026-001",
                "algorithm": "SHA256",
                "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Notarization created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotarizationResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (bad algorithm, invalid hex hash, wrong hash length)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Feature not available on current plan (e.g. SHA-384/512 requires Pro, qualified timestamps require Enterprise)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/notarizations/{id}": {
      "get": {
        "operationId": "getNotarization",
        "summary": "Get a notarization",
        "description": "Retrieve a notarization by its ID, including timestamp proof, blockchain proofs, and Merkle proof when available.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Notarization ID (UUIDv7)",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Notarization found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotarizationResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid notarization ID",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Not authorized to access this notarization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Notarization not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "API key for authentication. Obtain one from the Anchorify console."
      }
    },
    "schemas": {
      "CreateNotarizationRequest": {
        "type": "object",
        "required": ["algorithm", "hash"],
        "properties": {
          "name": {
            "type": "string",
            "description": "Optional human-readable name for the notarization"
          },
          "external_id": {
            "type": "string",
            "maxLength": 255,
            "description": "Optional client-defined external identifier for correlating with your own system. Whitespace is trimmed. Must not be blank after trimming."
          },
          "algorithm": {
            "type": "string",
            "enum": ["SHA256", "SHA384", "SHA512"],
            "description": "Hash algorithm used to compute the hash. SHA-384 and SHA-512 require a Pro or Enterprise plan."
          },
          "hash": {
            "type": "string",
            "pattern": "^[0-9a-f]+$",
            "description": "Hex-encoded hash of the document. Must match the expected length for the algorithm (64 chars for SHA-256, 96 for SHA-384, 128 for SHA-512)."
          },
          "qualified_timestamp": {
            "type": "boolean",
            "default": false,
            "description": "Request a qualified timestamp (eIDAS compliant). Requires an Enterprise plan."
          }
        }
      },
      "NotarizationResponse": {
        "type": "object",
        "required": ["id", "algorithm", "hash", "status", "created_at"],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique notarization identifier (UUIDv7)"
          },
          "name": {
            "type": "string",
            "description": "Human-readable name, if provided at creation"
          },
          "external_id": {
            "type": "string",
            "description": "Client-defined external identifier, if provided at creation"
          },
          "algorithm": {
            "type": "string",
            "enum": ["SHA256", "SHA384", "SHA512"],
            "description": "Hash algorithm"
          },
          "hash": {
            "type": "string",
            "description": "Hex-encoded document hash"
          },
          "status": {
            "type": "string",
            "enum": ["pending", "in_progress", "completed", "failed"],
            "description": "Current notarization status"
          },
          "timestamp_proof": {
            "$ref": "#/components/schemas/TimestampProofResponse"
          },
          "blockchain_proofs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BlockchainProofResponse"
            },
            "description": "Blockchain anchoring proofs (one per blockchain provider). Pre-populated at creation with expected providers in pending status, allowing progress tracking before anchoring begins."
          },
          "merkle_proof": {
            "$ref": "#/components/schemas/MerkleProofResponse"
          },
          "merkle_root": {
            "type": "string",
            "description": "Hex-encoded Merkle tree root hash"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Creation timestamp (RFC 3339)"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "Last update timestamp (RFC 3339)"
          },
          "notarized_at": {
            "type": "string",
            "format": "date-time",
            "description": "Completion timestamp when all proofs are finalized (RFC 3339)"
          }
        }
      },
      "TimestampProofResponse": {
        "type": "object",
        "required": ["status", "created_at"],
        "properties": {
          "status": {
            "type": "string",
            "enum": ["pending", "timestamped", "failed"],
            "description": "Timestamp proof status"
          },
          "tsa_provider": {
            "$ref": "#/components/schemas/TSAProviderResponse"
          },
          "data": {
            "type": "string",
            "description": "Hex-encoded RFC 3161 timestamp token"
          },
          "serial_number": {
            "type": "string",
            "description": "TSA serial number"
          },
          "timestamped_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the timestamp was issued (RFC 3339)"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Proof creation timestamp (RFC 3339)"
          }
        }
      },
      "TSAProviderResponse": {
        "type": "object",
        "required": ["name"],
        "properties": {
          "name": {
            "type": "string",
            "description": "Timestamp Authority provider name"
          },
          "cert_subject": {
            "type": "string",
            "description": "TSA certificate subject"
          },
          "cert_serial": {
            "type": "string",
            "description": "TSA certificate serial number"
          },
          "cert_ski": {
            "type": "string",
            "description": "TSA certificate Subject Key Identifier"
          },
          "policy_oid": {
            "type": "string",
            "description": "TSA policy OID"
          }
        }
      },
      "BlockchainProofResponse": {
        "type": "object",
        "required": ["provider_name", "status", "created_at"],
        "properties": {
          "transaction_id": {
            "type": "string",
            "description": "Blockchain transaction hash"
          },
          "provider_name": {
            "type": "string",
            "description": "Blockchain provider name (e.g. Polygon, Base)"
          },
          "explorer_url": {
            "type": "string",
            "format": "uri",
            "description": "URL to view the transaction on a blockchain explorer"
          },
          "status": {
            "type": "string",
            "enum": ["pending", "submitted", "anchored", "failed"],
            "description": "Blockchain transaction status"
          },
          "submitted_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the transaction was submitted (RFC 3339)"
          },
          "anchored_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the transaction was confirmed on-chain (RFC 3339)"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Proof creation timestamp (RFC 3339)"
          }
        }
      },
      "MerkleProofResponse": {
        "type": "object",
        "required": ["hash_algorithm", "leaf_index", "siblings"],
        "properties": {
          "hash_algorithm": {
            "type": "string",
            "enum": ["SHA256", "SHA384", "SHA512"],
            "description": "Hash algorithm used for the Merkle tree"
          },
          "leaf_index": {
            "type": "integer",
            "format": "int32",
            "minimum": 0,
            "description": "Position of this notarization's hash in the Merkle tree"
          },
          "siblings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MerkleSiblingResponse"
            },
            "description": "Sibling hashes forming the path from leaf to root"
          }
        }
      },
      "MerkleSiblingResponse": {
        "type": "object",
        "required": ["position", "hash"],
        "properties": {
          "position": {
            "type": "string",
            "enum": ["left", "right"],
            "description": "Position of the sibling relative to the current node"
          },
          "hash": {
            "type": "string",
            "description": "Hex-encoded sibling hash"
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "required": ["error"],
        "properties": {
          "error": {
            "$ref": "#/components/schemas/ErrorDetail"
          }
        }
      },
      "ErrorDetail": {
        "type": "object",
        "required": ["code", "message"],
        "properties": {
          "code": {
            "type": "string",
            "description": "Machine-readable error code",
            "enum": ["invalid_argument", "unauthenticated", "permission_denied", "not_found", "internal"]
          },
          "message": {
            "type": "string",
            "description": "Human-readable error message"
          }
        }
      }
    }
  }
}
