{
  "name": "problem+json: класс ошибки по статусу, код, расширения, request id; 4xx и 500 не повторяются",
  "description": "409 и 422 не повторяются даже у безопасной операции (calculateReceipt) и у запроса с ключом идемпотентности; ошибка несёт ключ вызова. request id — из X-Request-Id (у invalid_basket его нет в теле). 410 — класс api (статус без своего класса). 500 не повторяется и у GET.",
  "client": {
    "api": "runtime",
    "credential": {"terminalKey": "lk_test_k7m2p9q4r8s3.RqTvNAJirupwDOPZ8O48PZpsbGlZGfecp04FD7w06kw"},
    "baseUrl": "https://api.example.com"
  },
  "calls": [
    {
      "operation": "registerReceipt",
      "args": {
        "body": {
          "number": "1042",
          "business_date": "2026-10-11",
          "purchased_at": "2026-10-11T14:59:58+03:00",
          "member": {"phone": "+79000000001"},
          "lines": [
            {"id": "1", "sku": "BEANS-1KG", "name": "Зерно «Эфиопия», 1 кг", "quantity": 1000, "amount": 100000}
          ],
          "redeem_points": 300
        }
      },
      "options": {"idempotencyKey": "receipt:k7m2p9q4r8s3:2026-10-11:1042"},
      "expect": {
        "error": {
          "class": "conflict",
          "status": 409,
          "code": "receipt_exists",
          "requestId": "01929c20-0001-7000-8000-000000000001",
          "idempotencyKey": "receipt:k7m2p9q4r8s3:2026-10-11:1042",
          "problem": {
            "type": "urn:loyal:problem:receipt_exists",
            "title": "The terminal already registered a receipt with this number on this business date.",
            "status": 409,
            "code": "receipt_exists",
            "request_id": "01929c20-0001-7000-8000-000000000001",
            "receipt_id": "01929c1e-0050-7050-8050-000000000050"
          }
        }
      }
    },
    {
      "operation": "calculateReceipt",
      "args": {
        "body": {
          "purchased_at": "2026-10-11T15:05:00+03:00",
          "lines": [
            {"id": "1", "sku": "LATTE-M", "quantity": 1000, "amount": 25000},
            {"id": "1", "sku": "CROISSANT", "quantity": 1000, "amount": 18000}
          ]
        }
      },
      "expect": {
        "error": {
          "class": "validation",
          "status": 422,
          "code": "invalid_basket",
          "requestId": "01929c20-0002-7000-8000-000000000002",
          "idempotencyKey": null,
          "problem": {
            "type": "urn:loyal:problem:invalid_basket",
            "title": "The basket is invalid.",
            "status": 422,
            "code": "invalid_basket",
            "detail": "Line ids must be unique."
          }
        }
      }
    },
    {
      "operation": "registerMember",
      "args": {"body": {"phone": "+79000000003", "consents": ["program_rules", "personal_data"], "email": "anna@"}},
      "expect": {
        "error": {
          "class": "validation",
          "status": 422,
          "code": "validation_failed",
          "requestId": "01929c20-0003-7000-8000-000000000003",
          "idempotencyKey": "{{idempotency-key}}",
          "problem": {
            "type": "urn:loyal:problem:validation_failed",
            "title": "The request is invalid.",
            "status": 422,
            "code": "validation_failed",
            "errors": {"email": ["The email field must be a valid email address."]},
            "request_id": "01929c20-0003-7000-8000-000000000003"
          }
        }
      }
    },
    {
      "operation": "verifyCode",
      "args": {"verification": "01929c1e-0070-7070-8070-000000000070", "body": {"code": "000000"}},
      "expect": {
        "error": {
          "class": "api",
          "status": 410,
          "code": "verification_expired",
          "requestId": "01929c20-0004-7000-8000-000000000004"
        }
      }
    },
    {
      "operation": "getReceipt",
      "args": {"receipt": "01929c1e-005f-705f-805f-00000000005f"},
      "expect": {
        "error": {
          "class": "server",
          "status": 500,
          "code": "internal_error",
          "requestId": "01929c20-0005-7000-8000-000000000005"
        }
      }
    }
  ],
  "exchanges": [
    {
      "request": {
        "method": "POST",
        "url": "https://api.example.com/api/v1/receipts",
        "headers": {
          "authorization": "Bearer lk_test_k7m2p9q4r8s3.RqTvNAJirupwDOPZ8O48PZpsbGlZGfecp04FD7w06kw",
          "accept": "application/json",
          "content-type": "application/json",
          "idempotency-key": "receipt:k7m2p9q4r8s3:2026-10-11:1042",
          "loyal-merchant": null
        },
        "json": {
          "number": "1042",
          "business_date": "2026-10-11",
          "purchased_at": "2026-10-11T14:59:58+03:00",
          "member": {"phone": "+79000000001"},
          "lines": [
            {"id": "1", "sku": "BEANS-1KG", "name": "Зерно «Эфиопия», 1 кг", "quantity": 1000, "amount": 100000}
          ],
          "redeem_points": 300
        }
      },
      "response": {
        "status": 409,
        "headers": {
          "Content-Type": "application/problem+json",
          "X-Request-Id": "01929c20-0001-7000-8000-000000000001",
          "Loyal-Environment": "sandbox"
        },
        "json": {
          "type": "urn:loyal:problem:receipt_exists",
          "title": "The terminal already registered a receipt with this number on this business date.",
          "status": 409,
          "code": "receipt_exists",
          "request_id": "01929c20-0001-7000-8000-000000000001",
          "receipt_id": "01929c1e-0050-7050-8050-000000000050"
        }
      }
    },
    {
      "request": {
        "method": "POST",
        "url": "https://api.example.com/api/v1/receipts:calculate",
        "headers": {
          "authorization": "Bearer lk_test_k7m2p9q4r8s3.RqTvNAJirupwDOPZ8O48PZpsbGlZGfecp04FD7w06kw",
          "accept": "application/json",
          "content-type": "application/json",
          "idempotency-key": null,
          "loyal-merchant": null
        },
        "json": {
          "purchased_at": "2026-10-11T15:05:00+03:00",
          "lines": [
            {"id": "1", "sku": "LATTE-M", "quantity": 1000, "amount": 25000},
            {"id": "1", "sku": "CROISSANT", "quantity": 1000, "amount": 18000}
          ]
        }
      },
      "response": {
        "status": 422,
        "headers": {
          "Content-Type": "application/problem+json",
          "X-Request-Id": "01929c20-0002-7000-8000-000000000002",
          "Loyal-Environment": "sandbox"
        },
        "json": {
          "type": "urn:loyal:problem:invalid_basket",
          "title": "The basket is invalid.",
          "status": 422,
          "code": "invalid_basket",
          "detail": "Line ids must be unique."
        }
      }
    },
    {
      "request": {
        "method": "POST",
        "url": "https://api.example.com/api/v1/members",
        "headers": {
          "authorization": "Bearer lk_test_k7m2p9q4r8s3.RqTvNAJirupwDOPZ8O48PZpsbGlZGfecp04FD7w06kw",
          "accept": "application/json",
          "content-type": "application/json",
          "idempotency-key": "{{idempotency-key}}",
          "loyal-merchant": null
        },
        "json": {"phone": "+79000000003", "consents": ["program_rules", "personal_data"], "email": "anna@"}
      },
      "response": {
        "status": 422,
        "headers": {
          "Content-Type": "application/problem+json",
          "X-Request-Id": "01929c20-0003-7000-8000-000000000003",
          "Loyal-Environment": "sandbox"
        },
        "json": {
          "type": "urn:loyal:problem:validation_failed",
          "title": "The request is invalid.",
          "status": 422,
          "code": "validation_failed",
          "errors": {"email": ["The email field must be a valid email address."]},
          "request_id": "01929c20-0003-7000-8000-000000000003"
        }
      }
    },
    {
      "request": {
        "method": "POST",
        "url": "https://api.example.com/api/v1/verifications/01929c1e-0070-7070-8070-000000000070:verify",
        "headers": {
          "authorization": "Bearer lk_test_k7m2p9q4r8s3.RqTvNAJirupwDOPZ8O48PZpsbGlZGfecp04FD7w06kw",
          "accept": "application/json",
          "content-type": "application/json",
          "idempotency-key": null,
          "loyal-merchant": null
        },
        "json": {"code": "000000"}
      },
      "response": {
        "status": 410,
        "headers": {
          "Content-Type": "application/problem+json",
          "X-Request-Id": "01929c20-0004-7000-8000-000000000004",
          "Loyal-Environment": "sandbox"
        },
        "json": {
          "type": "urn:loyal:problem:verification_expired",
          "title": "The verification has expired.",
          "status": 410,
          "code": "verification_expired",
          "request_id": "01929c20-0004-7000-8000-000000000004"
        }
      }
    },
    {
      "request": {
        "method": "GET",
        "url": "https://api.example.com/api/v1/receipts/01929c1e-005f-705f-805f-00000000005f",
        "headers": {
          "authorization": "Bearer lk_test_k7m2p9q4r8s3.RqTvNAJirupwDOPZ8O48PZpsbGlZGfecp04FD7w06kw",
          "accept": "application/json",
          "content-type": null,
          "idempotency-key": null,
          "loyal-merchant": null
        }
      },
      "response": {
        "status": 500,
        "headers": {
          "Content-Type": "application/problem+json",
          "X-Request-Id": "01929c20-0005-7000-8000-000000000005",
          "Loyal-Environment": "sandbox"
        },
        "json": {
          "type": "urn:loyal:problem:internal_error",
          "title": "Internal server error.",
          "status": 500,
          "code": "internal_error",
          "request_id": "01929c20-0005-7000-8000-000000000005"
        }
      }
    }
  ],
  "sleeps": []
}
