{
  "openapi": "3.1.0",
  "info": {
    "title": "Receipt Out API",
    "version": "1.0.0",
    "description": "Deliver itemized digital receipts from retailer and POS systems to activated Receipt Out customer accounts."
  },
  "servers": [
    {
      "url": "https://receiptout.com"
    }
  ],
  "paths": {
    "/api/v1/receipts": {
      "post": {
        "summary": "Deliver a receipt",
        "operationId": "deliverReceipt",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Unique key for safe retry behavior. 1-128 letters, numbers, dots, underscores, colons, or dashes.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[A-Za-z0-9._:-]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReceiptDeliveryRequest"
              },
              "examples": {
                "basic": {
                  "value": {
                    "customer": {
                      "receiptout_id": "RO-7K4M-82P9"
                    },
                    "receipt": {
                      "transaction_id": "SALE-12345",
                      "purchased_at": "2026-09-27T13:45:00-05:00",
                      "store": {
                        "location": "Jackson, Missouri"
                      },
                      "currency": "USD",
                      "payment": {
                        "label": "Card payment"
                      },
                      "items": [
                        {
                          "description": "Milk",
                          "quantity": 1,
                          "unit_price_cents": 348,
                          "line_total_cents": 348
                        }
                      ],
                      "subtotal_cents": 348,
                      "discount_cents": 0,
                      "tax_cents": 28,
                      "total_cents": 376
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Idempotent replay of a previously delivered receipt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeliverySuccess"
                }
              }
            }
          },
          "201": {
            "description": "Receipt delivered",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeliverySuccess"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request or idempotency key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Customer not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Idempotency or transaction conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "413": {
            "description": "Payload too large",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported media type",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/customer-links": {
      "post": {
        "summary": "Link a retailer customer ID to Receipt Out",
        "operationId": "linkCustomer",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CustomerLinkRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Customer link created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerLinkSuccess"
                }
              }
            }
          },
          "200": {
            "description": "Existing/revoked link reactivated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerLinkSuccess"
                }
              }
            }
          },
          "401": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "QR credential invalid or revoked",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Retailer external ID already linked to another account",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported media type",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "Receipt Out API key"
      }
    },
    "schemas": {
      "ReceiptDeliveryRequest": {
        "type": "object",
        "required": [
          "customer",
          "receipt"
        ],
        "additionalProperties": true,
        "properties": {
          "customer": {
            "type": "object",
            "properties": {
              "qr_code": {
                "type": "string",
                "maxLength": 1024,
                "description": "Full value scanned from the customer\u2019s active Receipt Out QR."
              },
              "receiptout_id": {
                "type": "string",
                "pattern": "^RO-[A-Z2-9]{4}-[A-Z2-9]{4}$"
              },
              "external_id": {
                "type": "string",
                "maxLength": 160,
                "description": "Retailer customer/loyalty ID previously linked to Receipt Out."
              },
              "email": {
                "type": "string",
                "format": "email",
                "maxLength": 254,
                "description": "Fallback customer identifier."
              }
            },
            "anyOf": [
              {
                "required": [
                  "qr_code"
                ]
              },
              {
                "required": [
                  "receiptout_id"
                ]
              },
              {
                "required": [
                  "external_id"
                ]
              },
              {
                "required": [
                  "email"
                ]
              }
            ]
          },
          "receipt": {
            "type": "object",
            "required": [
              "transaction_id",
              "purchased_at",
              "items",
              "subtotal_cents",
              "tax_cents",
              "total_cents"
            ],
            "properties": {
              "transaction_id": {
                "type": "string",
                "maxLength": 120
              },
              "purchased_at": {
                "type": "string",
                "format": "date-time"
              },
              "store": {
                "type": "object",
                "properties": {
                  "location": {
                    "type": "string",
                    "maxLength": 160
                  }
                }
              },
              "currency": {
                "type": "string",
                "pattern": "^[A-Z]{3}$",
                "default": "USD"
              },
              "payment": {
                "type": "object",
                "properties": {
                  "label": {
                    "type": "string",
                    "maxLength": 80
                  }
                }
              },
              "items": {
                "type": "array",
                "minItems": 1,
                "maxItems": 200,
                "items": {
                  "$ref": "#/components/schemas/ReceiptItem"
                }
              },
              "subtotal_cents": {
                "type": "integer",
                "minimum": 0,
                "maximum": 100000000
              },
              "discount_cents": {
                "type": "integer",
                "minimum": 0,
                "maximum": 100000000,
                "default": 0
              },
              "tax_cents": {
                "type": "integer",
                "minimum": 0,
                "maximum": 100000000
              },
              "total_cents": {
                "type": "integer",
                "minimum": 0,
                "maximum": 100000000
              }
            }
          }
        }
      },
      "ReceiptItem": {
        "type": "object",
        "required": [
          "description",
          "unit_price_cents",
          "line_total_cents"
        ],
        "properties": {
          "description": {
            "type": "string",
            "maxLength": 140
          },
          "quantity": {
            "type": "number",
            "exclusiveMinimum": 0,
            "maximum": 9999,
            "default": 1
          },
          "unit_price_cents": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100000000
          },
          "line_total_cents": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100000000
          }
        }
      },
      "DeliverySuccess": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "const": "receipt_delivery"
          },
          "status": {
            "type": "string",
            "const": "delivered"
          },
          "receipt_id": {
            "type": "integer"
          },
          "transaction_id": {
            "type": "string"
          },
          "customer": {
            "type": "object",
            "properties": {
              "email": {
                "type": "string"
              }
            }
          },
          "mode": {
            "type": "string",
            "enum": [
              "test",
              "live"
            ]
          },
          "demo": {
            "type": "boolean"
          },
          "idempotent_replay": {
            "type": "boolean"
          },
          "request_id": {
            "type": "string"
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "fields": {
                "type": "object",
                "additionalProperties": {
                  "type": "string"
                }
              }
            }
          },
          "request_id": {
            "type": "string"
          }
        }
      },
      "CustomerLinkRequest": {
        "type": "object",
        "required": [
          "qr_code",
          "external_customer_id"
        ],
        "properties": {
          "qr_code": {
            "type": "string",
            "maxLength": 1024
          },
          "external_customer_id": {
            "type": "string",
            "maxLength": 160
          }
        }
      },
      "CustomerLinkSuccess": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "const": "customer_link"
          },
          "status": {
            "type": "string",
            "const": "linked"
          },
          "link_id": {
            "type": "integer"
          },
          "retailer": {
            "type": "string"
          },
          "external_customer_id": {
            "type": "string"
          },
          "receiptout_id": {
            "type": "string"
          },
          "request_id": {
            "type": "string"
          }
        }
      }
    }
  }
}
