{
  "openapi": "3.1.0",
  "info": {
    "title": "Payment Review API",
    "version": "1.0.0",
    "description": "Expert reviews, grades, rates and fees for payment processors.\n\nThe catalogue is public and needs no key. A key authenticates as your account and is only needed to read your own records."
  },
  "servers": [
    {
      "url": "https://api.paymentreview.com/v1"
    }
  ],
  "components": {
    "securitySchemes": {
      "usersApiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "Authorization",
        "description": "Prefixed with the collection slug, so the full header value is `users API-Key <key>`. Generate one at https://app.paymentreview.com/connect/. A key authenticates as your account and cannot write a review."
      }
    },
    "schemas": {
      "Review": {
        "type": "object",
        "description": "A published review. Unpublished reviews are never returned.",
        "required": [
          "id",
          "companyName",
          "slug",
          "grade",
          "createdAt",
          "updatedAt"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "examples": [
              42
            ]
          },
          "companyName": {
            "type": "string",
            "examples": [
              "Example Payments"
            ]
          },
          "slug": {
            "type": "string",
            "description": "URL segment. Stable once published.",
            "examples": [
              "example-payments"
            ]
          },
          "type": {
            "type": "string",
            "enum": [
              "payment_processor",
              "payment_gateway",
              "pos_system",
              "iso",
              "agent_reseller",
              "high_risk_specialist"
            ]
          },
          "shortSummary": {
            "type": "string"
          },
          "grade": {
            "type": "string",
            "description": "Our expert grade. Present on every published review.",
            "enum": [
              "A+",
              "A",
              "A-",
              "B+",
              "B",
              "B-",
              "C+",
              "C",
              "C-"
            ]
          },
          "basicInfo": {
            "type": "object",
            "properties": {
              "website": {
                "type": "string",
                "format": "uri"
              },
              "foundedYear": {
                "type": "integer",
                "examples": [
                  2014
                ]
              },
              "headquarters": {
                "type": "string",
                "examples": [
                  "Austin, TX"
                ]
              },
              "companySize": {
                "type": "string"
              }
            }
          },
          "categoryRatings": {
            "type": "object",
            "description": "Each scored out of 5.",
            "properties": {
              "pricingTransparency": {
                "type": "number"
              },
              "featureSet": {
                "type": "number"
              },
              "easeOfUse": {
                "type": "number"
              },
              "customerSupport": {
                "type": "number"
              },
              "contractTerms": {
                "type": "number"
              },
              "industryReputation": {
                "type": "number"
              }
            }
          },
          "processingRates": {
            "type": "object",
            "description": "Free text as published by the provider. Absent rather than placeholder when undisclosed.",
            "properties": {
              "online": {
                "type": "string",
                "examples": [
                  "2.9% + $0.30"
                ]
              },
              "inPerson": {
                "type": "string"
              },
              "keyed": {
                "type": "string"
              },
              "international": {
                "type": "string"
              }
            }
          },
          "fees": {
            "type": "object",
            "properties": {
              "monthly": {
                "type": "string"
              },
              "chargeback": {
                "type": "string"
              },
              "earlyTermination": {
                "type": "string"
              },
              "pci": {
                "type": "string"
              },
              "statement": {
                "type": "string"
              }
            }
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ReviewList": {
        "type": "object",
        "required": [
          "docs",
          "totalDocs",
          "limit",
          "page"
        ],
        "properties": {
          "docs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Review"
            }
          },
          "totalDocs": {
            "type": "integer",
            "examples": [
              38
            ]
          },
          "limit": {
            "type": "integer",
            "examples": [
              10
            ]
          },
          "totalPages": {
            "type": "integer",
            "examples": [
              4
            ]
          },
          "page": {
            "type": "integer",
            "examples": [
              1
            ]
          },
          "hasPrevPage": {
            "type": "boolean"
          },
          "hasNextPage": {
            "type": "boolean"
          }
        }
      },
      "EditSuggestion": {
        "type": "object",
        "required": [
          "id",
          "review",
          "createdAt",
          "updatedAt"
        ],
        "properties": {
          "id": {
            "type": "integer"
          },
          "review": {
            "description": "The review this targets, populated in full. `EditSuggestions.review` sets no `maxDepth`, so this is always the review object rather than a bare id — and stays that way, because `depth` is deliberately not a documented parameter a caller could use to ask for the id form instead.",
            "allOf": [
              {
                "$ref": "#/components/schemas/Review"
              }
            ]
          },
          "status": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "pending",
              "applied",
              "rejected",
              null
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "EditSuggestionList": {
        "type": "object",
        "required": [
          "docs",
          "totalDocs",
          "limit",
          "page"
        ],
        "properties": {
          "docs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EditSuggestion"
            }
          },
          "totalDocs": {
            "type": "integer",
            "examples": [
              38
            ]
          },
          "limit": {
            "type": "integer",
            "examples": [
              10
            ]
          },
          "totalPages": {
            "type": "integer",
            "examples": [
              4
            ]
          },
          "page": {
            "type": "integer",
            "examples": [
              1
            ]
          },
          "hasPrevPage": {
            "type": "boolean"
          },
          "hasNextPage": {
            "type": "boolean"
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "errors"
        ],
        "properties": {
          "errors": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "message"
              ],
              "properties": {
                "message": {
                  "type": "string",
                  "examples": [
                    "You are not allowed to perform this action."
                  ]
                }
              }
            }
          }
        }
      }
    }
  },
  "tags": [
    {
      "name": "Reviews",
      "description": "The public catalogue."
    },
    {
      "name": "Edit suggestions",
      "description": "Changes proposed on a listing you own or share, plus anything you've proposed yourself."
    }
  ],
  "paths": {
    "/reviews": {
      "get": {
        "operationId": "listReviews",
        "summary": "List published reviews",
        "description": "Returns published reviews only. Unpublished and draft reviews are filtered out by access control, for anonymous and authenticated callers alike.",
        "tags": [
          "Reviews"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "description": "Documents per page. Defaults to 10.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 10
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "1-indexed page number.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          },
          {
            "name": "sort",
            "in": "query",
            "description": "Field to sort by. Prefix with `-` to reverse.",
            "schema": {
              "type": "string",
              "enum": [
                "companyName",
                "-companyName",
                "updatedAt",
                "-updatedAt"
              ]
            }
          },
          {
            "name": "where[slug][equals]",
            "in": "query",
            "description": "Exact slug match.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "where[grade][equals]",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "A+",
                "A",
                "A-",
                "B+",
                "B",
                "B-",
                "C+",
                "C",
                "C-"
              ]
            }
          },
          {
            "name": "where[type][equals]",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "payment_processor",
                "payment_gateway",
                "pos_system",
                "iso",
                "agent_reseller",
                "high_risk_specialist"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of reviews.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReviewList"
                }
              }
            }
          }
        }
      }
    },
    "/reviews/{id}": {
      "get": {
        "operationId": "getReview",
        "summary": "Fetch one published review",
        "tags": [
          "Reviews"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Numeric id. To look one up by slug, use `where[slug][equals]` on the list endpoint.",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The review.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Review"
                }
              }
            }
          },
          "404": {
            "description": "No published review with that id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/edit-suggestions": {
      "get": {
        "operationId": "listOwnEditSuggestions",
        "summary": "List edit suggestions for your listings",
        "description": "Scoped to the listings you own or share, plus anything you've submitted yourself. That means it can include a colleague's suggestion on a listing you both work on, one filed by someone who has since left the team, or one with no submitter recorded at all — not only rows you personally submitted. A key never returns suggestions for a listing you are not on and did not file against.",
        "tags": [
          "Edit suggestions"
        ],
        "security": [
          {
            "usersApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 10
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of your suggestions.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EditSuggestionList"
                }
              }
            }
          },
          "403": {
            "description": "Missing or invalid key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  }
}