{
    "openapi": "3.0.3",
    "info": {
        "title": "Copy My Media catalogue and pricing API",
        "version": "1.2.0",
        "description": "Read-only information and fixed prices for media digitisation in Nice, France, with selected European return destinations. POST /estimate only calculates; it never creates an enquiry, order, payment or shipment. No contact details or files accepted."
    },
    "servers": [
        {
            "url": "https://copymymedia.com/wp-json/copymymedia/v1"
        }
    ],
    "externalDocs": {
        "description": "Examples and service boundaries",
        "url": "https://copymymedia.com/for-agents/"
    },
    "paths": {
        "/catalog": {
            "get": {
                "operationId": "getMediaCatalogue",
                "summary": "List media, prices and supported return destinations",
                "description": "Read the current catalogue before calculating a price. Some formats need individual assessment. Country codes alone do not establish eligibility for excluded territories.",
                "responses": {
                    "200": {
                        "description": "Current public catalogue, pricing policy and delivery scope.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Invalid request or unavailable service. No enquiry or payment was created."
                    },
                    "503": {
                        "description": "Invalid request or unavailable service. No enquiry or payment was created."
                    }
                }
            }
        },
        "/estimate": {
            "post": {
                "operationId": "estimateMediaProject",
                "summary": "Calculate the final price for selected services without saving a request",
                "description": "Pass only media SKU, quantity and destination country. Weight is estimated automatically. Incoming postage to France is paid separately. Unknown media, unsupported destinations and overweight parcels may require assessment and have no complete total. No checkout, reservation or customer data access.",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/EstimateInput"
                            },
                            "example": {
                                "items": [
                                    {
                                        "sku": "vhs",
                                        "quantity": 1
                                    }
                                ],
                                "country": "FR"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Known prices are final for the selected services and destination. totalCents contains the complete fixed service and return-postage price; it is absent when any required component is unknown.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Estimate"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid request or unavailable service. No enquiry or payment was created."
                    },
                    "401": {
                        "description": "Invalid request or unavailable service. No enquiry or payment was created."
                    },
                    "413": {
                        "description": "Invalid request or unavailable service. No enquiry or payment was created."
                    },
                    "415": {
                        "description": "Invalid request or unavailable service. No enquiry or payment was created."
                    },
                    "422": {
                        "description": "Invalid request or unavailable service. No enquiry or payment was created."
                    },
                    "503": {
                        "description": "Invalid request or unavailable service. No enquiry or payment was created."
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "EstimateInput": {
                "type": "object",
                "additionalProperties": false,
                "description": "Maximum 16384 UTF-8 request bytes, 34 lines and 10000 media in total; repeated SKU quantities are combined and capped at 9999.",
                "required": [
                    "items",
                    "country"
                ],
                "properties": {
                    "items": {
                        "type": "array",
                        "minItems": 0,
                        "maxItems": 34,
                        "items": {
                            "type": "object",
                            "additionalProperties": false,
                            "required": [
                                "sku",
                                "quantity"
                            ],
                            "properties": {
                                "sku": {
                                    "type": "string",
                                    "description": "Use an exact SKU from GET /catalog; medical media are excluded."
                                },
                                "quantity": {
                                    "type": "integer",
                                    "minimum": 1,
                                    "maximum": 9999
                                }
                            }
                        }
                    },
                    "country": {
                        "type": "string",
                        "pattern": "^([A-Z]{2})?$",
                        "example": "FR",
                        "description": "ISO two-letter destination country, or empty if not yet known. See catalogue for service scope and territorial exclusions."
                    }
                }
            },
            "Estimate": {
                "type": "object",
                "description": "A calculation, never an order or payment. Additional fields explain versions, weight, shipping and assessment reasons.",
                "properties": {
                    "status": {
                        "type": "string",
                        "enum": [
                            "fixed",
                            "requires_assessment",
                            "empty"
                        ]
                    },
                    "currency": {
                        "type": "string",
                        "enum": [
                            "EUR"
                        ]
                    },
                    "priceBasis": {
                        "type": "string",
                        "enum": [
                            "fixed"
                        ]
                    },
                    "fixedPrice": {
                        "type": "boolean",
                        "description": "True only when the complete service and return-postage price is known."
                    },
                    "priceScope": {
                        "type": "string",
                        "enum": [
                            "selected_media_and_return_shipping"
                        ]
                    },
                    "totalCents": {
                        "type": "integer",
                        "minimum": 0,
                        "description": "Final price for the selected catalogue services, quantities and return destination. Present only with status=fixed. Initial postage to France and separately agreed additional work are excluded."
                    },
                    "estimateCents": {
                        "type": "integer",
                        "minimum": 0,
                        "description": "Compatibility alias for totalCents; despite its legacy name, the amount is fixed for the selected scope.",
                        "deprecated": true
                    },
                    "lines": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "properties": {
                                "sku": {
                                    "type": "string"
                                },
                                "quantity": {
                                    "type": "integer"
                                },
                                "priceCents": {
                                    "type": "integer",
                                    "minimum": 0,
                                    "description": "Euro cents, VAT included.",
                                    "nullable": true
                                },
                                "fixedPrice": {
                                    "type": "boolean"
                                },
                                "requiresQuote": {
                                    "type": "boolean"
                                }
                            }
                        }
                    },
                    "serviceTotalCents": {
                        "type": "integer",
                        "minimum": 0,
                        "description": "Euro cents, VAT included.",
                        "nullable": true
                    },
                    "incomingPostageIncluded": {
                        "type": "boolean",
                        "enum": [
                            false
                        ]
                    }
                }
            }
        }
    }
}