{
  "openapi": "3.1.0",
  "info": {
    "title": "ogfetch URL metadata API",
    "version": "1.0.0",
    "summary": "Turn any URL into clean JSON metadata.",
    "description": "Fetch a URL and get its title, description, Open Graph and Twitter card tags, favicon, canonical URL, word count, and detected tech stack. Agents can self-serve: POST /v1/signup for a key (20 free credits), POST /v1/checkout (card) or POST /v1/topup/solana (USDC via Solana Pay, fully autonomous) to buy more. One-time credit packs, no subscription.",
    "contact": {
      "email": "hi@ogfetch.dev",
      "url": "https://ogfetch.dev"
    }
  },
  "servers": [
    {
      "url": "https://ogfetch.dev"
    }
  ],
  "externalDocs": {
    "url": "https://ogfetch.dev/docs/"
  },
  "security": [
    {
      "bearer": []
    },
    {
      "apiKey": []
    }
  ],
  "paths": {
    "/v1/fetch": {
      "get": {
        "operationId": "fetchUrlMetadata",
        "summary": "Get metadata for a URL",
        "description": "Fetches the page and returns its metadata. Consumes 1 credit on success.",
        "parameters": [
          {
            "name": "url",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Absolute http(s) URL to fetch.",
            "example": "https://github.com"
          }
        ],
        "responses": {
          "200": {
            "description": "Metadata",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Metadata"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "402": {
            "description": "No credits left. Body includes a `buy` object explaining how to top up.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/Error"
          },
          "504": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/signup": {
      "post": {
        "operationId": "createAccount",
        "summary": "Create an account and API key",
        "description": "No email or browser needed. Returns an API key with 20 free credits. The key is shown once. Limited to 3 signups per IP per day.",
        "security": [],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Optional label for the agent or app."
                  },
                  "contact": {
                    "type": "string",
                    "description": "Optional operator contact (email or URL)."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Account created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "account_id",
                    "api_key",
                    "credits"
                  ],
                  "properties": {
                    "account_id": {
                      "type": "string"
                    },
                    "api_key": {
                      "type": "string",
                      "example": "ogf_0123abcd..."
                    },
                    "credits": {
                      "type": "integer"
                    },
                    "note": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/account": {
      "get": {
        "operationId": "getAccount",
        "summary": "Credit balance and usage",
        "responses": {
          "200": {
            "description": "Account",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "account_id": {
                      "type": "string"
                    },
                    "credits": {
                      "type": "integer"
                    },
                    "total_calls": {
                      "type": "integer"
                    },
                    "last_used": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "created_at": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/pricing": {
      "get": {
        "operationId": "getPricing",
        "summary": "List credit packs",
        "security": [],
        "responses": {
          "200": {
            "description": "Pricing",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "currency": {
                      "type": "string"
                    },
                    "plans": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Plan"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/checkout": {
      "post": {
        "operationId": "buyCredits",
        "summary": "Create a Stripe checkout link",
        "description": "Returns a Stripe checkout_url. Open it (or hand it to a human) to pay. Credits are added to the calling API key automatically after payment; poll /v1/account to confirm.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "plan"
                ],
                "properties": {
                  "plan": {
                    "type": "string",
                    "enum": [
                      "starter",
                      "pro",
                      "business"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Checkout created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "checkout_url": {
                      "type": "string",
                      "format": "uri"
                    },
                    "checkout_id": {
                      "type": "string"
                    },
                    "expires_at": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "plan": {
                      "type": "string"
                    },
                    "credits": {
                      "type": "integer"
                    },
                    "price_usd": {
                      "type": "number"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "502": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/topup/solana": {
      "post": {
        "operationId": "quoteUsdcSolana",
        "summary": "Create a Solana Pay USDC quote",
        "description": "Creates a quote keyed by a reference. POST your wallet address to transaction_url to receive a ready-to-sign USDC transaction (Solana Pay transaction request), sign and send it, then poll status_url. Humans can scan solana_pay_url in Phantom.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "plan"
                ],
                "properties": {
                  "plan": {
                    "type": "string",
                    "enum": [
                      "starter",
                      "pro",
                      "business"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Quote",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "reference": {
                      "type": "string",
                      "description": "Solana Pay reference public key (base58); also the quote id"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "pending"
                      ]
                    },
                    "pay_to": {
                      "type": "string"
                    },
                    "mint": {
                      "type": "string"
                    },
                    "amount_usdc": {
                      "type": "string",
                      "example": "3.000000"
                    },
                    "amount_atomic": {
                      "type": "string"
                    },
                    "network": {
                      "type": "string",
                      "example": "solana-mainnet"
                    },
                    "plan": {
                      "type": "string"
                    },
                    "credits": {
                      "type": "integer"
                    },
                    "expires_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "solana_pay_url": {
                      "type": "string",
                      "description": "solana: link (transaction request) for QR codes and mobile wallets"
                    },
                    "status_url": {
                      "type": "string",
                      "format": "uri"
                    },
                    "transaction_url": {
                      "type": "string",
                      "format": "uri",
                      "description": "Solana Pay transaction request endpoint"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/topup/solana/{reference}": {
      "get": {
        "operationId": "getUsdcPaymentStatus",
        "summary": "USDC payment status",
        "security": [],
        "description": "Looks up the quote and, while pending, searches Solana for a transaction carrying the reference. A matching payment is credited exactly once. Poll every few seconds.",
        "parameters": [
          {
            "name": "reference",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Status",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "pending",
                        "credited",
                        "expired"
                      ]
                    },
                    "reference": {
                      "type": "string"
                    },
                    "credits": {
                      "type": "integer"
                    },
                    "signature": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "retry_after_seconds": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "502": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/topup/solana/{reference}/tx": {
      "get": {
        "operationId": "solanaPayLabel",
        "summary": "Solana Pay transaction request: label and icon",
        "security": [],
        "parameters": [
          {
            "name": "reference",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Label",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "label": {
                      "type": "string"
                    },
                    "icon": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "solanaPayTransaction",
        "summary": "Get a ready-to-sign USDC transaction",
        "security": [],
        "description": "Solana Pay transaction request. Returns an unsigned, base64-serialized transaction (fee payer = account) that transfers the quoted USDC with the reference attached. Sign and send it.",
        "parameters": [
          {
            "name": "reference",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "account"
                ],
                "properties": {
                  "account": {
                    "type": "string",
                    "description": "Payer wallet address (base58)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Transaction",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "transaction": {
                      "type": "string",
                      "description": "base64"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "502": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key from /v1/signup or the dashboard."
      },
      "apiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Api-Key"
      }
    },
    "responses": {
      "Error": {
        "description": "Error",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error",
          "code"
        ],
        "properties": {
          "error": {
            "type": "string"
          },
          "code": {
            "type": "string",
            "enum": [
              "MISSING_KEY",
              "INVALID_KEY",
              "NO_CREDITS",
              "MISSING_URL",
              "INVALID_URL",
              "RATE_LIMITED",
              "FETCH_FAILED",
              "TIMEOUT",
              "INVALID_PLAN",
              "CHECKOUT_FAILED",
              "UNKNOWN_ENDPOINT",
              "QUOTE_NOT_FOUND",
              "UNDERPAID",
              "INVALID_REFERENCE",
              "RPC_ERROR",
              "INVALID_ACCOUNT",
              "QUOTE_EXPIRED",
              "ALREADY_PAID",
              "CANNOT_BUILD"
            ]
          }
        }
      },
      "Plan": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "credits": {
            "type": "integer"
          },
          "price_usd": {
            "type": "number"
          },
          "usd_per_1000_requests": {
            "type": "number"
          }
        }
      },
      "Metadata": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "description": "Final URL after redirects"
          },
          "canonical": {
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "favicon": {
            "type": [
              "string",
              "null"
            ],
            "description": "Absolute URL"
          },
          "og": {
            "type": "object",
            "properties": {
              "title": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "description": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "image": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "url": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "type": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "siteName": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "twitter": {
            "type": "object",
            "properties": {
              "card": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "title": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "description": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "image": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "creator": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "meta": {
            "type": "object",
            "properties": {
              "author": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "keywords": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "robots": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "themeColor": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "wordCount": {
            "type": "integer"
          },
          "techStack": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "statusCode": {
            "type": "integer",
            "description": "HTTP status returned by the target URL"
          },
          "responseTime": {
            "type": "integer",
            "description": "Milliseconds"
          },
          "fetchedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      }
    }
  }
}