{
  "openapi": "3.1.0",
  "info": {
    "title": "Print for Agents",
    "version": "0.1.0",
    "description": "Print and installation for AI agents: sticker and sign production, on-site fitting and photo proof in Tallinn and Harju County, Estonia. No design and no marketing advice: you bring finished files."
  },
  "servers": [
    {
      "url": "https://printforagents.com"
    }
  ],
  "paths": {
    "/api/list_services": {
      "get": {
        "operationId": "list_services",
        "summary": "List every physical service with limits, artwork rules and the service area. There is no price list: each job is priced on request. Call this first.",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/validate_artwork": {
      "post": {
        "operationId": "validate_artwork",
        "summary": "Check a declared print file spec against the rules for a service, before requesting a price.",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "service_id",
                  "artwork"
                ],
                "additionalProperties": false,
                "properties": {
                  "service_id": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 40
                  },
                  "artwork": {
                    "type": "object",
                    "description": "Declared spec of the print file. A person checks the actual file before production.",
                    "required": [
                      "file_url",
                      "format",
                      "width_mm",
                      "height_mm",
                      "color_space",
                      "bleed_mm"
                    ],
                    "additionalProperties": false,
                    "properties": {
                      "file_url": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 2000,
                        "description": "Public https link to the print file."
                      },
                      "format": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 10,
                        "description": "One of: pdf, ai, eps, svg, tiff, png"
                      },
                      "width_mm": {
                        "type": "number",
                        "exclusiveMinimum": 0,
                        "maximum": 10000,
                        "description": "Trim width without bleed."
                      },
                      "height_mm": {
                        "type": "number",
                        "exclusiveMinimum": 0,
                        "maximum": 10000,
                        "description": "Trim height without bleed."
                      },
                      "dpi": {
                        "type": "integer",
                        "minimum": 1,
                        "maximum": 10000,
                        "description": "Effective resolution at final size. Required for raster files."
                      },
                      "color_space": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 10,
                        "description": "One of: cmyk, rgb, spot. Preferred: CMYK (FOGRA39)."
                      },
                      "bleed_mm": {
                        "type": "number",
                        "minimum": 0,
                        "maximum": 100
                      },
                      "fonts_outlined": {
                        "type": "boolean"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/request_quote": {
      "post": {
        "operationId": "request_quote",
        "summary": "Send a job for pricing. This commits nobody. A person prices it within 24 hours, then a human at the buyer approves the price through a link and pays a 50% deposit. Work is finished within 10 days of the deposit. You cannot approve on the buyer's behalf. Poll get_request_status for the price.",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "service_id",
                  "quantity",
                  "buyer"
                ],
                "additionalProperties": false,
                "properties": {
                  "service_id": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 40
                  },
                  "quantity": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 100000
                  },
                  "width_mm": {
                    "type": "number",
                    "exclusiveMinimum": 0,
                    "maximum": 10000,
                    "description": "Required when the service has needs_dimensions."
                  },
                  "height_mm": {
                    "type": "number",
                    "exclusiveMinimum": 0,
                    "maximum": 10000,
                    "description": "Required when the service has needs_dimensions."
                  },
                  "fulfilment": {
                    "type": "string",
                    "enum": [
                      "install",
                      "ship"
                    ],
                    "description": "Defaults to the service's first option."
                  },
                  "buyer": {
                    "type": "object",
                    "description": "The company or person legally buying and paying. Must be a real, identifiable party.",
                    "required": [
                      "legal_name",
                      "contact_name",
                      "email",
                      "phone"
                    ],
                    "additionalProperties": false,
                    "properties": {
                      "legal_name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 200
                      },
                      "registry_code": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 40
                      },
                      "vat_number": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 40
                      },
                      "contact_name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 120
                      },
                      "email": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 254,
                        "pattern": "^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$"
                      },
                      "phone": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 40
                      }
                    }
                  },
                  "approver_email": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 254,
                    "pattern": "^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$",
                    "description": "Human who approves the price. Defaults to buyer.email."
                  },
                  "site": {
                    "type": "object",
                    "description": "Required for on-site work.",
                    "required": [
                      "address",
                      "city",
                      "country",
                      "max_work_height_m"
                    ],
                    "additionalProperties": false,
                    "properties": {
                      "address": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 300
                      },
                      "city": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 100
                      },
                      "county": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 100
                      },
                      "country": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 2,
                        "description": "ISO 3166-1 alpha-2, for example EE."
                      },
                      "latitude": {
                        "type": "number",
                        "minimum": -90,
                        "maximum": 90
                      },
                      "longitude": {
                        "type": "number",
                        "minimum": -180,
                        "maximum": 180
                      },
                      "max_work_height_m": {
                        "type": "number",
                        "minimum": 0,
                        "maximum": 1000,
                        "description": "Highest point to reach, in metres from standing ground."
                      },
                      "surface": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 200
                      },
                      "access_notes": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 1000,
                        "description": "When and how the site can be reached."
                      },
                      "onsite_contact_phone": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 40
                      },
                      "vehicle": {
                        "type": "object",
                        "required": [
                          "make",
                          "model",
                          "year"
                        ],
                        "additionalProperties": false,
                        "properties": {
                          "make": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 60
                          },
                          "model": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 60
                          },
                          "year": {
                            "type": "integer",
                            "minimum": 1950,
                            "maximum": 2100
                          },
                          "registration": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 20
                          }
                        }
                      }
                    }
                  },
                  "ship_to": {
                    "type": "object",
                    "description": "Required for shipped orders.",
                    "required": [
                      "recipient",
                      "address",
                      "city",
                      "postal_code",
                      "country",
                      "phone"
                    ],
                    "additionalProperties": false,
                    "properties": {
                      "recipient": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 200
                      },
                      "address": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 300
                      },
                      "city": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 100
                      },
                      "postal_code": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 20
                      },
                      "country": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 2
                      },
                      "phone": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 40
                      }
                    }
                  },
                  "artwork": {
                    "type": "object",
                    "description": "Declared spec of the print file. A person checks the actual file before production.",
                    "required": [
                      "file_url",
                      "format",
                      "width_mm",
                      "height_mm",
                      "color_space",
                      "bleed_mm"
                    ],
                    "additionalProperties": false,
                    "properties": {
                      "file_url": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 2000,
                        "description": "Public https link to the print file."
                      },
                      "format": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 10,
                        "description": "One of: pdf, ai, eps, svg, tiff, png"
                      },
                      "width_mm": {
                        "type": "number",
                        "exclusiveMinimum": 0,
                        "maximum": 10000,
                        "description": "Trim width without bleed."
                      },
                      "height_mm": {
                        "type": "number",
                        "exclusiveMinimum": 0,
                        "maximum": 10000,
                        "description": "Trim height without bleed."
                      },
                      "dpi": {
                        "type": "integer",
                        "minimum": 1,
                        "maximum": 10000,
                        "description": "Effective resolution at final size. Required for raster files."
                      },
                      "color_space": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 10,
                        "description": "One of: cmyk, rgb, spot. Preferred: CMYK (FOGRA39)."
                      },
                      "bleed_mm": {
                        "type": "number",
                        "minimum": 0,
                        "maximum": 100
                      },
                      "fonts_outlined": {
                        "type": "boolean"
                      }
                    }
                  },
                  "notes": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 2000,
                    "description": "Work instructions. For a survey, list the surfaces and questions."
                  },
                  "agent": {
                    "type": "object",
                    "additionalProperties": false,
                    "properties": {
                      "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 100
                      },
                      "operator": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 200
                      }
                    }
                  },
                  "idempotency_key": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100,
                    "description": "Retrying with the same buyer and key returns the same request."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/get_request_status": {
      "post": {
        "operationId": "get_request_status",
        "summary": "Read status, price, next action, due date and proof of completed work: photos, hashes, coordinates and measurements.",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "request_id",
                  "access_key"
                ],
                "additionalProperties": false,
                "properties": {
                  "request_id": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 40
                  },
                  "access_key": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/cancel_request": {
      "post": {
        "operationId": "cancel_request",
        "summary": "Cancel a request before the deposit is received.",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "request_id",
                  "access_key"
                ],
                "additionalProperties": false,
                "properties": {
                  "request_id": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 40
                  },
                  "access_key": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "details": {}
            }
          }
        }
      }
    }
  }
}