REST & API Design - backend’da endpoint yozish emas, balki API’ni tushunarli, barqaror, kengayadigan, xavfsiz va clientlar uchun qulay qilib loyihalash.
Bu bo‘limga quyidagilar kiradi: RESTful conventions, HATEOAS, OpenAPI/Swagger, RFC 7807 error response, versioning strategies, HTTP caching headers.
1. API Design nima?
API Design - frontend, mobile app yoki boshqa backend service sening backend’ing bilan qanday gaplashishini loyihalash.
Masalan:
Mobile app → Backend API → Database
Frontend → Backend API → Payment service
CRM → Backend API → Order serviceYaxshi API:
tushunarli
consistent
xatolarni aniq qaytaradi
version bilan boshqariladi
pagination/filter/sort bor
security hisobga olingan
documentation borYomon API esa ishlaydi, lekin vaqt o‘tib muammo qiladi.
2. REST nima?
REST - HTTP asosida resource’lar bilan ishlash uslubi.
REST’da asosiy narsa - resource.
Resource misollar:
users
orders
products
payments
categoriesEndpoint resource nomi bilan yoziladi.
Yaxshi:
GET /api/users
GET /api/users/10
POST /api/users
PUT /api/users/10
DELETE /api/users/10Yomon:
GET /api/getUsers
GET /api/getUserById?id=10
POST /api/createUser
POST /api/deleteUser
POST /api/updateUserREST’da action’ni URL emas, HTTP method bildiradi.
3. HTTP Methods
Method | Vazifasi | Misol |
|---|---|---|
| Ma’lumot olish |
|
| Yangi resource yaratish |
|
| Resource’ni to‘liq yangilash |
|
| Qisman yangilash |
|
| O‘chirish |
|
4. Resource nomlash
Yaxshi qoida
Resource nomlari odatda plural bo‘ladi:
/users
/orders
/products
/paymentsYomon:
/user
/order
/productSabab: /users userlar collection’ini bildiradi.
Nested resource
Agar orderlar userga tegishli bo‘lsa:
GET /api/users/10/ordersBu 10-idli userning orderlarini olish degani.
Lekin haddan tashqari chuqur nesting yomon:
GET /api/users/10/orders/5/items/3/products/8Yaxshiroq:
GET /api/order-items/3
GET /api/products/8Odatda 2 darajadan oshirmaslik yaxshi.
5. HTTP Status Codes
Status code API’da juda muhim. Client nima bo‘lganini statusdan tushunishi kerak.
Status | Ma’nosi |
|---|---|
| Muvaffaqiyatli |
| Yangi resource yaratildi |
| Muvaffaqiyatli, response body yo‘q |
| Request noto‘g‘ri |
| Login/token yo‘q yoki noto‘g‘ri |
| Ruxsat yo‘q |
| Resource topilmadi |
| Conflict holat |
| Validation/business rule xato |
| Server xatosi |
6. 200, 201, 204 farqi
200 OK
Ma’lumot qaytarilganda:
GET /api/users/1Response:
200 OK{
"id": 1,
"name": "Ali"
}201 Created
Yangi resource yaratilganda:
POST /api/usersResponse:
201 Created
Location: /api/users/1{
"id": 1,
"name": "Ali"
}Spring’da:
@PostMapping
public ResponseEntity<UserDto> create(@Valid @RequestBody CreateUserRequest request) {
UserDto user = userService.create(request);
return ResponseEntity
.created(URI.create("/api/users/" + user.id()))
.body(user);
}204 No Content
Delete yoki response body kerak bo‘lmagan update uchun:
@DeleteMapping("/{id}")
public ResponseEntity<Void> delete(@PathVariable Long id) {
userService.delete(id);
return ResponseEntity.noContent().build();
}Response:
204 No ContentBody bo‘lmaydi.
7. RESTful Controller misol
@RestController
@RequestMapping("/api/users")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping
public Page<UserDto> getUsers(Pageable pageable) {
return userService.getUsers(pageable);
}
@GetMapping("/{id}")
public UserDto getById(@PathVariable Long id) {
return userService.getById(id);
}
@PostMapping
public ResponseEntity<UserDto> create(@Valid @RequestBody CreateUserRequest request) {
UserDto created = userService.create(request);
return ResponseEntity
.created(URI.create("/api/users/" + created.id()))
.body(created);
}
@PutMapping("/{id}")
public UserDto update(
@PathVariable Long id,
@Valid @RequestBody UpdateUserRequest request
) {
return userService.update(id, request);
}
@DeleteMapping("/{id}")
public ResponseEntity<Void> delete(@PathVariable Long id) {
userService.delete(id);
return ResponseEntity.noContent().build();
}
}8. Request DTO va Response DTO
Entity’ni API’da to‘g‘ridan-to‘g‘ri qaytarish yomon.
Yomon:
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
return userRepository.findById(id).orElseThrow();
}Muammolar:
sensitive field chiqib ketishi mumkin
LazyInitializationException bo‘lishi mumkin
JSON recursion bo‘lishi mumkin
API entity structure’ga bog‘lanib qoladiYaxshi:
public record UserDto(
Long id,
String name,
String email
) {
public static UserDto from(User user) {
return new UserDto(
user.getId(),
user.getName(),
user.getEmail()
);
}
}Request DTO:
public record CreateUserRequest(
@NotBlank String name,
@Email String email,
@Pattern(regexp = "^\\+998\\d{9}$") String phone
) {
}9. Validation
API request kelganda darhol validation qilish kerak.
@PostMapping
public ResponseEntity<UserDto> create(@Valid @RequestBody CreateUserRequest request) {
UserDto user = userService.create(request);
return ResponseEntity.status(HttpStatus.CREATED).body(user);
}DTO:
public record CreateUserRequest(
@NotBlank(message = "Ism bo‘sh bo‘lmasin")
String name,
@Email(message = "Email noto‘g‘ri formatda")
String email,
@Pattern(regexp = "^\\+998\\d{9}$", message = "Telefon +998 bilan boshlanishi kerak")
String phone
) {
}10. Error Response
Yomon error response:
{
"error": "Something went wrong"
}Client buni tushunmaydi.
Yaxshi error response:
{
"type": "https://api.example.com/errors/validation",
"title": "Validation failed",
"status": 400,
"detail": "Request body has invalid fields",
"instance": "/api/users",
"errors": [
{
"field": "email",
"message": "Email noto‘g‘ri formatda"
}
]
}Bu RFC 7807 uslubiga yaqin.
11. RFC 7807 - Problem Details
RFC 7807 - HTTP API xatolarini standart ko‘rinishda qaytarish formati.
Asosiy fieldlar:
Field | Ma’nosi |
|---|---|
| Error turi haqida URI |
| Qisqa error nomi |
| HTTP status code |
| Batafsil xabar |
| Qaysi endpointda bo‘ldi |
Spring 6 / Spring Boot 3'da ProblemDetail bor.
@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity<ProblemDetail> handleUserNotFound(UserNotFoundException ex) {
ProblemDetail problem = ProblemDetail.forStatus(HttpStatus.NOT_FOUND);
problem.setTitle("User not found");
problem.setDetail(ex.getMessage());
problem.setType(URI.create("https://api.example.com/errors/user-not-found"));
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(problem);
}Response:
{
"type": "https://api.example.com/errors/user-not-found",
"title": "User not found",
"status": 404,
"detail": "User not found with id: 10"
}12. Global Exception Handler
API’da xatolarni bitta joyda boshqarish kerak.
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity<ProblemDetail> handleUserNotFound(UserNotFoundException ex) {
ProblemDetail problem = ProblemDetail.forStatus(HttpStatus.NOT_FOUND);
problem.setTitle("User not found");
problem.setDetail(ex.getMessage());
problem.setType(URI.create("https://api.example.com/errors/user-not-found"));
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(problem);
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ValidationProblemDetail> handleValidation(
MethodArgumentNotValidException ex,
HttpServletRequest request
) {
List<FieldErrorDto> errors = ex.getBindingResult()
.getFieldErrors()
.stream()
.map(error -> new FieldErrorDto(
error.getField(),
error.getDefaultMessage()
))
.toList();
ValidationProblemDetail body = new ValidationProblemDetail(
"https://api.example.com/errors/validation",
"Validation failed",
400,
"Request body has invalid fields",
request.getRequestURI(),
errors
);
return ResponseEntity.badRequest().body(body);
}
}DTO:
public record FieldErrorDto(
String field,
String message
) {
}public record ValidationProblemDetail(
String type,
String title,
int status,
String detail,
String instance,
List<FieldErrorDto> errors
) {
}13. Pagination
Katta list endpointlarda pagination majburiy.
Yomon:
GET /api/ordersAgar 1 million order bo‘lsa, server qiynaladi.
Yaxshi:
GET /api/orders?page=0&size=20Spring:
@GetMapping
public Page<OrderDto> getOrders(Pageable pageable) {
return orderService.getOrders(pageable);
}14. Page response’ni custom qilish
Spring Pageni to‘g‘ridan-to‘g‘ri qaytarish mumkin, lekin API contract juda katta bo‘lib ketadi. Custom response yaxshiroq.
public record PageResponse<T>(
List<T> content,
int page,
int size,
long totalElements,
int totalPages,
boolean last
) {
public static <T> PageResponse<T> from(Page<T> page) {
return new PageResponse<>(
page.getContent(),
page.getNumber(),
page.getSize(),
page.getTotalElements(),
page.getTotalPages(),
page.isLast()
);
}
}Controller:
@GetMapping
public PageResponse<OrderDto> getOrders(Pageable pageable) {
return PageResponse.from(orderService.getOrders(pageable));
}Response:
{
"content": [
{
"id": 1,
"status": "NEW"
}
],
"page": 0,
"size": 20,
"totalElements": 125,
"totalPages": 7,
"last": false
}15. Filtering
Filtering query parameter orqali bo‘ladi.
GET /api/orders?status=PAID
GET /api/orders?status=PAID&from=2026-01-01&to=2026-01-31
GET /api/users?name=ali&active=trueRequest object qilish mumkin:
public record OrderFilterRequest(
OrderStatus status,
LocalDate from,
LocalDate to
) {
}Controller:
@GetMapping
public PageResponse<OrderDto> getOrders(
OrderFilterRequest filter,
Pageable pageable
) {
return PageResponse.from(orderService.getOrders(filter, pageable));
}16. Sorting
GET /api/orders?sort=createdAt,desc
GET /api/users?sort=name,ascSpring Pageable buni qo‘llaydi:
@GetMapping
public PageResponse<UserDto> getUsers(Pageable pageable) {
return PageResponse.from(userService.getUsers(pageable));
}Lekin production’da sort fieldlarni whitelist qilish yaxshi.
Nega?
GET /api/users?sort=password,ascBunday fieldlarga sort qilish xavfli yoki keraksiz bo‘lishi mumkin.
Yaxshiroq:
private static final Set<String> ALLOWED_SORT_FIELDS = Set.of(
"id",
"name",
"createdAt"
);17. Keyset / Cursor Pagination
Katta tablelarda offset pagination sekinlashadi.
Offset:
GET /api/orders?page=5000&size=20DB oldingi qatorlarni sanab o‘tadi.
Keyset:
GET /api/orders?cursor=1000&size=20SQL:
SELECT *
FROM orders
WHERE id < :cursor
ORDER BY id DESC
LIMIT :size;Response:
{
"content": [
{
"id": 999,
"status": "PAID"
}
],
"nextCursor": 980,
"hasNext": true
}DTO:
public record CursorPageResponse<T>(
List<T> content,
Long nextCursor,
boolean hasNext
) {
}18. Idempotency
Idempotency - bitta request takror yuborilsa ham, natija xavfsiz bo‘lishi.
Masalan, payment yaratishda client timeout oldi va requestni qayta yubordi. Agar idempotency bo‘lmasa, ikki marta payment bo‘lishi mumkin.
Header:
Idempotency-Key: 6d4c8c20-7a47-4b0d-9c16Server shu key bo‘yicha oldingi natijani saqlaydi.
@PostMapping("/payments")
public PaymentResponse createPayment(
@RequestHeader("Idempotency-Key") String idempotencyKey,
@Valid @RequestBody CreatePaymentRequest request
) {
return paymentService.create(idempotencyKey, request);
}Qayerda kerak?
payment
order creation
money transfer
external API callback
retry bo‘ladigan POST requestlar19. PUT vs PATCH
PUT
Resource’ni to‘liq almashtirish.
PUT /api/users/1{
"name": "Ali",
"email": "ali@example.com",
"phone": "+998901234567"
}Agar phone yuborilmasa, u bo‘sh/null bo‘lib qolishi mumkin, chunki PUT to‘liq update sifatida qaraladi.
PATCH
Qisman update.
PATCH /api/users/1/status{
"status": "BLOCKED"
}Yoki:
PATCH /api/users/1{
"phone": "+998901234567"
}PATCH’da faqat berilgan fieldlar o‘zgaradi.
20. API Versioning
API o‘zgarganda eski clientlar buzilmasligi kerak.
Eng oddiy usul:
/api/v1/users
/api/v2/usersController:
@RestController
@RequestMapping("/api/v1/users")
public class UserV1Controller {
}Yangi versiya:
@RestController
@RequestMapping("/api/v2/users")
public class UserV2Controller {
}Versioning strategiyalari
Strategiya | Misol | Izoh |
|---|---|---|
URL version |
| Oddiy va tushunarli |
Header version |
| URL toza, lekin debug qiyinroq |
Accept header |
| Enterprise uslub |
Query param |
| Kamroq tavsiya qilinadi |
Oddiy Spring Boot loyihalarda URL version yetarli.
21. Backward Compatibility
API’ni o‘zgartirishda ehtiyot bo‘lish kerak.
Xavfsiz o‘zgarishlar
response’ga yangi optional field qo‘shish
yangi endpoint qo‘shish
yangi query param qo‘shishMasalan:
{
"id": 1,
"name": "Ali",
"email": "ali@example.com",
"phone": "+998901234567"
}Agar eski client phoneni ishlatmasa, buzilmaydi.
Breaking changes
field nomini o‘zgartirish
fieldni olib tashlash
status code o‘zgartirish
response structure o‘zgartirish
required field qo‘shish
enum qiymatini olib tashlashBular uchun yangi API version kerak bo‘lishi mumkin.
22. OpenAPI / Swagger
API documentation uchun ishlatiladi.
Spring Boot’da odatda springdoc-openapi ishlatiladi.
Gradle:
implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:2.6.0")Endpoint:
/swagger-ui/index.html
/v3/api-docsController annotation:
@Tag(name = "Users", description = "User management API")
@RestController
@RequestMapping("/api/v1/users")
public class UserController {
@Operation(summary = "Create user", description = "Creates a new user")
@ApiResponses({
@ApiResponse(responseCode = "201", description = "User created"),
@ApiResponse(responseCode = "400", description = "Validation error")
})
@PostMapping
public ResponseEntity<UserDto> create(@Valid @RequestBody CreateUserRequest request) {
UserDto created = userService.create(request);
return ResponseEntity
.created(URI.create("/api/v1/users/" + created.id()))
.body(created);
}
}23. Swagger’da security
JWT ishlatilsa Swagger’da token qo‘yish uchun config yoziladi.
@Configuration
public class OpenApiConfig {
@Bean
public OpenAPI openAPI() {
String securitySchemeName = "bearerAuth";
return new OpenAPI()
.addSecurityItem(new SecurityRequirement().addList(securitySchemeName))
.components(new Components()
.addSecuritySchemes(securitySchemeName,
new SecurityScheme()
.name(securitySchemeName)
.type(SecurityScheme.Type.HTTP)
.scheme("bearer")
.bearerFormat("JWT")));
}
}24. HTTP Caching Headers
Agar data tez-tez o‘zgarmasa, caching headerlar performance beradi.
Muhim headerlar:
Header | Vazifasi |
|---|---|
| Cache qoidasi |
| Resource versiya belgisi |
| Oxirgi o‘zgarish vaqti |
| Clientdagi ETag bilan tekshirish |
| Sana bo‘yicha tekshirish |
Cache-Control
Masalan, public product categorylar kam o‘zgaradi.
Cache-Control: public, max-age=3600Bu 1 soat cache qilish mumkin degani.
Sensitive data uchun:
Cache-Control: no-storeMasalan:
profile
payment info
personal data
token response25. ETag
ETag resource versiyasini bildiradi.
Birinchi request:
GET /api/products/1Response:
200 OK
ETag: "product-1-v5"Keyingi requestda client yuboradi:
If-None-Match: "product-1-v5"Agar product o‘zgarmagan bo‘lsa:
304 Not ModifiedBody qaytmaydi. Traffic kamayadi.
Spring misol:
@GetMapping("/{id}")
public ResponseEntity<ProductDto> getProduct(@PathVariable Long id) {
ProductDto product = productService.getById(id);
String etag = "\"" + product.id() + "-" + product.version() + "\"";
return ResponseEntity.ok()
.eTag(etag)
.body(product);
}26. Security API Design
API design’da security ham bor.
Muhim qoidalar:
password response’da qaytmasin
token logga chiqmasin
sensitive endpointlar protected bo‘lsin
admin endpointlar role bilan cheklansin
CORS aniq sozlansin
rate limit bo‘lsin
request size limit bo‘lsinYomon response:
{
"id": 1,
"email": "ali@example.com",
"password": "$2a$10$..."
}Yaxshi response:
{
"id": 1,
"email": "ali@example.com"
}27. Rate Limiting
API’ni spam yoki brute-force’dan himoya qilish uchun rate limit kerak.
Masalan:
login endpoint: 5 request / minute
SMS send endpoint: 3 request / minute
public search: 60 request / minuteJava/Spring’da ishlatilishi mumkin:
Bucket4j
Resilience4j RateLimiter
API Gateway rate limit
Nginx rate limit
Cloudflare rate limit28. API Response structure
Kichik loyihalarda to‘g‘ridan-to‘g‘ri DTO qaytarish normal:
{
"id": 1,
"name": "Ali"
}Lekin ba’zi jamoalar umumiy wrapper ishlatadi:
{
"success": true,
"data": {
"id": 1,
"name": "Ali"
}
}Bu shart emas. Muhimi - consistent bo‘lish.
Bir endpoint wrapper bilan, boshqasi wrappersiz bo‘lsa yomon.
29. Naming convention
Field nomlari odatda JSON’da camelCase bo‘ladi:
{
"firstName": "Ali",
"createdAt": "2026-05-20T10:00:00Z"
}Java’da ham:
public record UserDto(
String firstName,
Instant createdAt
) {
}30. Date/Time API Design
Date/time’da timezone muhim.
Yaxshi format:
{
"createdAt": "2026-05-20T10:15:30Z"
}Backend’da:
Instant createdAt;Agar local sana kerak bo‘lsa:
LocalDate birthDate;Tavsiya:
Holat | Java type |
|---|---|
Audit time |
|
Birth date |
|
Business local time |
|
Scheduled event |
|
31. Id format
Oddiy ichki API’da numeric id:
GET /api/users/123Public API’da ba’zida UUID yaxshi:
GET /api/orders/8f5a6a7b-6420-4c20-9cb6-2fd2f3d5e123Numeric ID muammosi:
incremental id taxmin qilinadi
scraping osonlashadi
business hajm sezilishi mumkinLekin ichki systemlarda numeric ID normal.
32. HATEOAS
HATEOAS - response ichida keyingi mumkin bo‘lgan linklar berish.
Misol:
{
"id": 1,
"status": "NEW",
"_links": {
"self": {
"href": "/api/orders/1"
},
"cancel": {
"href": "/api/orders/1/cancel"
},
"pay": {
"href": "/api/orders/1/pay"
}
}
}Afzalligi:
client keyingi actionlarni response’dan biladi
API discoverable bo‘ladiKamchiligi:
ko‘p backend loyihalarda ortiqcha murakkablik
frontend/mobile uchun har doim ham kerak emasAmaliyotda ko‘p jamoalar to‘liq HATEOAS ishlatmaydi. Lekin conceptni bilish kerak.
33. Action endpointlar
REST’da action endpointlar ham bo‘ladi, lekin ehtiyot bilan.
Masalan, order cancel qilish:
Variant 1:
PATCH /api/orders/1/status{
"status": "CANCELLED"
}Variant 2:
POST /api/orders/1/cancelIkkinchi variant ham amaliyotda ko‘p ishlatiladi, chunki cancel oddiy status update emas, business action bo‘lishi mumkin:
refund qilish
stock qaytarish
notification yuborish
audit yozishDemak, action endpoint ishlatish yomon emas. Faqat nomi aniq va consistent bo‘lsin.
34. File upload API
File upload uchun multipart/form-data ishlatiladi.
@PostMapping(value = "/avatar", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public UserDto uploadAvatar(
@RequestParam("file") MultipartFile file
) {
return userService.uploadAvatar(file);
}Muhim tekshiruvlar:
file size
file extension
MIME type
virus scan
storage path traversal
public/private access35. Bulk API
Bir nechta itemni bitta requestda yaratish:
POST /api/products/bulk{
"items": [
{
"name": "Product 1",
"price": 100
},
{
"name": "Product 2",
"price": 200
}
]
}Response partial success bo‘lishi mumkin:
{
"successCount": 1,
"failedCount": 1,
"errors": [
{
"index": 1,
"message": "Price invalid"
}
]
}Bulk API’da transaction strategiyani oldindan hal qilish kerak:
hammasi muvaffaqiyatli bo‘lsa commit
yoki ayrimlari fail bo‘lsa ham qolganlari saqlansin36. API Contract Testing
Agar backend API’dan frontend/mobile yoki boshqa service foydalansa, contract muhim.
Contract testing uchun:
Spring Cloud Contract
Pact
OpenAPI schema validationMaqsad:
Backend response structure’ni o‘zgartirib, clientni buzib qo‘ymaslik37. Logging va Correlation ID
Har requestga correlationId berish debuggingni osonlashtiradi.
Header:
X-Correlation-ID: 9f8d7a6cResponse’da ham qaytarish mumkin.
Log:
correlationId=9f8d7a6c userId=123 action=createOrderFilter:
@Component
public class CorrelationIdFilter extends OncePerRequestFilter {
private static final String HEADER = "X-Correlation-ID";
@Override
protected void doFilterInternal(
HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain
) throws ServletException, IOException {
String correlationId = request.getHeader(HEADER);
if (correlationId == null || correlationId.isBlank()) {
correlationId = UUID.randomUUID().toString();
}
MDC.put("correlationId", correlationId);
response.setHeader(HEADER, correlationId);
try {
filterChain.doFilter(request, response);
} finally {
MDC.remove("correlationId");
}
}
}38. API Design’da ko‘p uchraydigan xatolar
1. Verb bilan URL yozish
Yomon:
POST /api/createUser
POST /api/deleteOrder
GET /api/getProductsYaxshi:
POST /api/users
DELETE /api/orders/1
GET /api/products2. Har doim 200 OK qaytarish
Yomon:
200 OK{
"success": false,
"message": "User not found"
}Yaxshi:
404 Not Found{
"type": "https://api.example.com/errors/user-not-found",
"title": "User not found",
"status": 404,
"detail": "User not found with id: 10"
}3. Entity qaytarish
Yomon:
public User getUser() {}Yaxshi:
public UserDto getUser() {}4. Pagination yo‘qligi
Yomon:
GET /api/ordersYaxshi:
GET /api/orders?page=0&size=205. Error format inconsistent
Yomon:
{
"error": "not found"
}Boshqa endpoint:
{
"message": "validation failed",
"fields": []
}Yaxshi: hamma error bitta formatda.
6. Breaking change’ni eski versionga qilish
Yomon:
/api/v1/users response fieldlarini o‘zgartirishYaxshi:
/api/v2/users chiqarish39. Real Order API design
Order yaratish
POST /api/v1/ordersRequest:
{
"userId": 10,
"items": [
{
"productId": 5,
"quantity": 2
}
],
"paymentType": "CLICK"
}Response:
201 Created
Location: /api/v1/orders/100{
"id": 100,
"status": "NEW",
"totalAmount": 250000,
"createdAt": "2026-05-20T10:15:30Z"
}Order list
GET /api/v1/orders?status=PAID&page=0&size=20&sort=createdAt,descResponse:
{
"content": [
{
"id": 100,
"status": "PAID",
"totalAmount": 250000,
"createdAt": "2026-05-20T10:15:30Z"
}
],
"page": 0,
"size": 20,
"totalElements": 120,
"totalPages": 6,
"last": false
}Order detail
GET /api/v1/orders/100Response:
{
"id": 100,
"status": "PAID",
"totalAmount": 250000,
"items": [
{
"productId": 5,
"productName": "Keyboard",
"quantity": 2,
"price": 125000
}
],
"createdAt": "2026-05-20T10:15:30Z"
}Order cancel
POST /api/v1/orders/100/cancelRequest:
{
"reason": "User requested cancellation"
}Response:
{
"id": 100,
"status": "CANCELLED"
}40. Controller + Service structure
Controller yupqa bo‘lsin:
@RestController
@RequestMapping("/api/v1/orders")
public class OrderController {
private final OrderService orderService;
public OrderController(OrderService orderService) {
this.orderService = orderService;
}
@PostMapping
public ResponseEntity<OrderDto> create(@Valid @RequestBody CreateOrderRequest request) {
OrderDto created = orderService.create(request);
return ResponseEntity
.created(URI.create("/api/v1/orders/" + created.id()))
.body(created);
}
@GetMapping("/{id}")
public OrderDetailDto getById(@PathVariable Long id) {
return orderService.getDetail(id);
}
@PostMapping("/{id}/cancel")
public OrderDto cancel(
@PathVariable Long id,
@Valid @RequestBody CancelOrderRequest request
) {
return orderService.cancel(id, request);
}
}Service business logicni ushlaydi:
@Service
public class OrderService {
@Transactional
public OrderDto create(CreateOrderRequest request) {
// validate user
// validate products
// create order
// calculate total
// save
// publish event
return result;
}
@Transactional(readOnly = true)
public OrderDetailDto getDetail(Long id) {
// fetch order with items
return result;
}
@Transactional
public OrderDto cancel(Long id, CancelOrderRequest request) {
// business cancel logic
return result;
}
}41. Interview savollari
REST nima?
HTTP methodlar orqali resource’lar bilan ishlash uslubi.
GET, POST, PUT, PATCH, DELETE farqi?
GET o‘qish, POST yaratish, PUT to‘liq update, PATCH qisman update, DELETE o‘chirish.
401 va 403 farqi?
401 - user authenticated emas yoki token noto‘g‘ri.403 - user authenticated, lekin ruxsati yo‘q.
400 va 422 farqi?
400 - request syntax/format noto‘g‘ri.422 - request format to‘g‘ri, lekin semantic/business validationdan o‘tmadi.
Ko‘p loyihalar validation uchun 400 ishlatadi. Muhimi - consistent bo‘lish.
PUT va PATCH farqi?
PUT resource’ni to‘liq almashtiradi.PATCH resource’ni qisman yangilaydi.
RFC 7807 nima?
HTTP API errorlarni standart Problem Details formatida qaytarish uslubi.
OpenAPI nima?
API contract va documentation format. Swagger UI orqali endpointlarni ko‘rish va test qilish mumkin.
API versioning nima uchun kerak?
Eski clientlarni buzmasdan API’ni o‘zgartirish uchun.
Idempotency nima?
Bir xil request takror yuborilsa ham, nojo‘ya takroriy effect bo‘lmasligi.
HATEOAS nima?
Response ichida resource bilan bog‘liq link/actionlarni qaytarish yondashuvi.
42. Java Developer checklist
REST & API Design bo‘yicha siz quyidagilarni bilishingiz kerak:
REST resource naming
HTTP methods
status codes
request/response DTO
validation
global exception handler
RFC 7807 Problem Details
pagination
filtering
sorting
keyset pagination
idempotency
PUT vs PATCH
API versioning
backward compatibility
OpenAPI/Swagger
HTTP caching headers
ETag
security basics in API design
rate limiting
correlation ID
HATEOAS conceptQisqa xulosa
REST & API Design - endpoint ochishdan kattaroq mavzu.
Junior ko‘pincha shunday qiladi:
POST /createOrder
GET /getOrders
POST /deleteOrderMiddle esa shunday loyihalaydi:
POST /api/v1/orders
GET /api/v1/orders?page=0&size=20
GET /api/v1/orders/100
POST /api/v1/orders/100/cancel
DELETE /api/v1/orders/100Eng muhim 5 ta joy:
1. Resource-oriented URL
2. To‘g‘ri HTTP method va status code
3. DTO + validation + consistent error response
4. Pagination/filter/sort
5. Versioning + OpenAPI documentation