{"openapi":"3.0.0","paths":{"/files/{id}":{"get":{"operationId":"Files_serve","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"signature","required":false,"in":"query","description":"Private files only.","schema":{}},{"name":"expires","required":false,"in":"query","description":"Private files only.","schema":{}},{"$ref":"#/components/parameters/AcceptLanguage"}],"responses":{"200":{"description":"The file, with its stored content type."},"400":{"description":"VALIDATION_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"VALIDATION_FAILED":{"value":{"code":"VALIDATION_FAILED","message":"The request data is invalid","details":[{"field":"mobile","code":"isSaudiMobileRequired","message":"Mobile number must be entered."}],"requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"404":{"description":"NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"NOT_FOUND":{"value":{"code":"NOT_FOUND","message":"The requested item was not found","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Download a file\n\nPublic files (gallery media, icons, avatars) need nothing else. Private\nfiles (CR images, work documents) need the `expires` and `signature` from their URL; an invalid or\nexpired link answers 404. Supports `Range` for video seeking.","tags":["System"],"x-public":true,"security":[]}},"/health":{"get":{"operationId":"Health_check","parameters":[{"$ref":"#/components/parameters/AcceptLanguage"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponseDto"}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"503":{"description":"The database is down.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponseDto"}}}}},"summary":"Readiness: MySQL and Redis\n\n200 while the API can serve requests (`ok`, or `degraded` when only the\ncache is down), 503 when the database is unreachable. The Docker image's\nHEALTHCHECK calls this.","tags":["System"],"x-public":true,"security":[]}},"/health/live":{"get":{"operationId":"Health_live","parameters":[{"$ref":"#/components/parameters/AcceptLanguage"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LivenessResponseDto"}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Liveness: the process is up","tags":["System"],"x-public":true,"security":[]}},"/v1/user/auth/register":{"post":{"description":"Checks the registration form, saves it as an unverified sign-up and sends a 4-digit code to the mobile. The account works only once `register/verify` confirms the code; until then it can’t log in. Registering the same number again replaces the unverified form. `MOBILE_ALREADY_REGISTERED` means the app should offer login.","operationId":"UserAuth_register","parameters":[{"$ref":"#/components/parameters/AcceptLanguage"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerificationSentDto"}}}},"400":{"description":"VALIDATION_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"VALIDATION_FAILED":{"value":{"code":"VALIDATION_FAILED","message":"The request data is invalid","details":[{"field":"mobile","code":"isSaudiMobileRequired","message":"Mobile number must be entered."}],"requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"409":{"description":"MOBILE_ALREADY_REGISTERED, EMAIL_ALREADY_REGISTERED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"MOBILE_ALREADY_REGISTERED":{"value":{"code":"MOBILE_ALREADY_REGISTERED","message":"The mobile number is already in use, please verify the number.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}},"EMAIL_ALREADY_REGISTERED":{"value":{"code":"EMAIL_ALREADY_REGISTERED","message":"This email is already in use.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"429":{"description":"OTP_RESEND_TOO_SOON, TOO_MANY_REQUESTS","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"OTP_RESEND_TOO_SOON":{"value":{"code":"OTP_RESEND_TOO_SOON","message":"You can request a new code in {seconds} seconds.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}},"TOO_MANY_REQUESTS":{"value":{"code":"TOO_MANY_REQUESTS","message":"Too many requests, please try again shortly","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"503":{"description":"SMS_SEND_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"SMS_SEND_FAILED":{"value":{"code":"SMS_SEND_FAILED","message":"The verification code could not be sent. Please try again.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Register","tags":["User · Auth"],"x-public":true,"security":[]}},"/v1/user/auth/register/resend-otp":{"post":{"description":"Once `resendAfterSeconds` have passed: a new code for the `verificationId` from `register`, which stays the same.","operationId":"UserAuth_resendRegisterCode","parameters":[{"$ref":"#/components/parameters/AcceptLanguage"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResendCodeDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerificationSentDto"}}}},"400":{"description":"VERIFICATION_INVALID, VALIDATION_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"VERIFICATION_INVALID":{"value":{"code":"VERIFICATION_INVALID","message":"This verification is no longer valid. Please request a new code.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}},"VALIDATION_FAILED":{"value":{"code":"VALIDATION_FAILED","message":"The request data is invalid","details":[{"field":"mobile","code":"isSaudiMobileRequired","message":"Mobile number must be entered."}],"requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"429":{"description":"OTP_RESEND_TOO_SOON, TOO_MANY_REQUESTS","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"OTP_RESEND_TOO_SOON":{"value":{"code":"OTP_RESEND_TOO_SOON","message":"You can request a new code in {seconds} seconds.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}},"TOO_MANY_REQUESTS":{"value":{"code":"TOO_MANY_REQUESTS","message":"Too many requests, please try again shortly","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"503":{"description":"SMS_SEND_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"SMS_SEND_FAILED":{"value":{"code":"SMS_SEND_FAILED","message":"The verification code could not be sent. Please try again.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Resend the registration code","tags":["User · Auth"],"x-public":true,"security":[]}},"/v1/user/auth/register/verify":{"post":{"description":"The `verificationId` from `register` and the code: activates the account and starts a session (the app then shows Home).","operationId":"UserAuth_verifyRegistration","parameters":[{"$ref":"#/components/parameters/AcceptLanguage"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyCodeDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserSessionDto"}}}},"400":{"description":"VERIFICATION_INVALID, OTP_INVALID, OTP_EXPIRED, VALIDATION_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"VERIFICATION_INVALID":{"value":{"code":"VERIFICATION_INVALID","message":"This verification is no longer valid. Please request a new code.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}},"OTP_INVALID":{"value":{"code":"OTP_INVALID","message":"The verification code is incorrect.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}},"OTP_EXPIRED":{"value":{"code":"OTP_EXPIRED","message":"The verification code is invalid or expired. Please request a new one.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}},"VALIDATION_FAILED":{"value":{"code":"VALIDATION_FAILED","message":"The request data is invalid","details":[{"field":"mobile","code":"isSaudiMobileRequired","message":"Mobile number must be entered."}],"requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"429":{"description":"OTP_TOO_MANY_ATTEMPTS","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"OTP_TOO_MANY_ATTEMPTS":{"value":{"code":"OTP_TOO_MANY_ATTEMPTS","message":"Too many incorrect attempts. Please request a new code.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Verify the registration","tags":["User · Auth"],"x-public":true,"x-session-token":{"namespace":"user","field":"accessToken"},"security":[]}},"/v1/user/auth/login":{"post":{"description":"Sends a 4-digit code by SMS to a registered, active account (BRD 4.1.3) and answers its `verificationId`. `MOBILE_NOT_REGISTERED` means the app should offer registration.","operationId":"UserAuth_login","parameters":[{"$ref":"#/components/parameters/AcceptLanguage"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserLoginDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerificationSentDto"}}}},"400":{"description":"VALIDATION_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"VALIDATION_FAILED":{"value":{"code":"VALIDATION_FAILED","message":"The request data is invalid","details":[{"field":"mobile","code":"isSaudiMobileRequired","message":"Mobile number must be entered."}],"requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"403":{"description":"ACCOUNT_DISABLED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"ACCOUNT_DISABLED":{"value":{"code":"ACCOUNT_DISABLED","message":"This user is disabled, please contact the administration.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"404":{"description":"MOBILE_NOT_REGISTERED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"MOBILE_NOT_REGISTERED":{"value":{"code":"MOBILE_NOT_REGISTERED","message":"No account is registered with this number. Please make sure the mobile number is correct.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"429":{"description":"OTP_RESEND_TOO_SOON, TOO_MANY_REQUESTS","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"OTP_RESEND_TOO_SOON":{"value":{"code":"OTP_RESEND_TOO_SOON","message":"You can request a new code in {seconds} seconds.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}},"TOO_MANY_REQUESTS":{"value":{"code":"TOO_MANY_REQUESTS","message":"Too many requests, please try again shortly","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"503":{"description":"SMS_SEND_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"SMS_SEND_FAILED":{"value":{"code":"SMS_SEND_FAILED","message":"The verification code could not be sent. Please try again.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Log in","tags":["User · Auth"],"x-public":true,"security":[]}},"/v1/user/auth/login/resend-otp":{"post":{"description":"Once `resendAfterSeconds` have passed: a new code for the `verificationId` from `login`, which stays the same.","operationId":"UserAuth_resendLoginCode","parameters":[{"$ref":"#/components/parameters/AcceptLanguage"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResendCodeDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerificationSentDto"}}}},"400":{"description":"VERIFICATION_INVALID, VALIDATION_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"VERIFICATION_INVALID":{"value":{"code":"VERIFICATION_INVALID","message":"This verification is no longer valid. Please request a new code.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}},"VALIDATION_FAILED":{"value":{"code":"VALIDATION_FAILED","message":"The request data is invalid","details":[{"field":"mobile","code":"isSaudiMobileRequired","message":"Mobile number must be entered."}],"requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"429":{"description":"OTP_RESEND_TOO_SOON, TOO_MANY_REQUESTS","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"OTP_RESEND_TOO_SOON":{"value":{"code":"OTP_RESEND_TOO_SOON","message":"You can request a new code in {seconds} seconds.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}},"TOO_MANY_REQUESTS":{"value":{"code":"TOO_MANY_REQUESTS","message":"Too many requests, please try again shortly","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"503":{"description":"SMS_SEND_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"SMS_SEND_FAILED":{"value":{"code":"SMS_SEND_FAILED","message":"The verification code could not be sent. Please try again.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Resend the login code","tags":["User · Auth"],"x-public":true,"security":[]}},"/v1/user/auth/login/verify":{"post":{"description":"The `verificationId` from `login` and the code: starts a session.","operationId":"UserAuth_verifyLogin","parameters":[{"$ref":"#/components/parameters/AcceptLanguage"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyCodeDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserSessionDto"}}}},"400":{"description":"VERIFICATION_INVALID, OTP_INVALID, OTP_EXPIRED, VALIDATION_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"VERIFICATION_INVALID":{"value":{"code":"VERIFICATION_INVALID","message":"This verification is no longer valid. Please request a new code.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}},"OTP_INVALID":{"value":{"code":"OTP_INVALID","message":"The verification code is incorrect.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}},"OTP_EXPIRED":{"value":{"code":"OTP_EXPIRED","message":"The verification code is invalid or expired. Please request a new one.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}},"VALIDATION_FAILED":{"value":{"code":"VALIDATION_FAILED","message":"The request data is invalid","details":[{"field":"mobile","code":"isSaudiMobileRequired","message":"Mobile number must be entered."}],"requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"403":{"description":"ACCOUNT_DISABLED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"ACCOUNT_DISABLED":{"value":{"code":"ACCOUNT_DISABLED","message":"This user is disabled, please contact the administration.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"404":{"description":"MOBILE_NOT_REGISTERED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"MOBILE_NOT_REGISTERED":{"value":{"code":"MOBILE_NOT_REGISTERED","message":"No account is registered with this number. Please make sure the mobile number is correct.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"429":{"description":"OTP_TOO_MANY_ATTEMPTS","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"OTP_TOO_MANY_ATTEMPTS":{"value":{"code":"OTP_TOO_MANY_ATTEMPTS","message":"Too many incorrect attempts. Please request a new code.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Verify the login","tags":["User · Auth"],"x-public":true,"x-session-token":{"namespace":"user","field":"accessToken"},"security":[]}},"/v1/user/auth/logout":{"post":{"description":"Ends the session of the token sent; it stops working immediately. Other devices stay signed in.","operationId":"UserSession_logout","parameters":[{"$ref":"#/components/parameters/AcceptLanguage"}],"responses":{"204":{"description":"Logged out."},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"UNAUTHORIZED":{"value":{"code":"UNAUTHORIZED","message":"Please log in to complete this action.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"403":{"description":"ACCOUNT_DISABLED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"ACCOUNT_DISABLED":{"value":{"code":"ACCOUNT_DISABLED","message":"This user is disabled, please contact the administration.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Log out","tags":["User · Auth"],"security":[{"user":[]}]}},"/v1/user/account":{"get":{"operationId":"UserAccount_get","parameters":[{"$ref":"#/components/parameters/AcceptLanguage"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserDto"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"UNAUTHORIZED":{"value":{"code":"UNAUTHORIZED","message":"Please log in to complete this action.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"403":{"description":"ACCOUNT_DISABLED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"ACCOUNT_DISABLED":{"value":{"code":"ACCOUNT_DISABLED","message":"This user is disabled, please contact the administration.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"My account","tags":["User · Account"],"security":[{"user":[]}]},"patch":{"description":"The \"Change language\" screen (`ar`, `en`). Requests without `Accept-Language` or `?lang=` are answered in it from the next request, and SMS and email messages use it.","operationId":"UserAccount_update","parameters":[{"$ref":"#/components/parameters/AcceptLanguage"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAccountDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserDto"}}}},"400":{"description":"VALIDATION_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"VALIDATION_FAILED":{"value":{"code":"VALIDATION_FAILED","message":"The request data is invalid","details":[{"field":"mobile","code":"isSaudiMobileRequired","message":"Mobile number must be entered."}],"requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"UNAUTHORIZED":{"value":{"code":"UNAUTHORIZED","message":"Please log in to complete this action.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"403":{"description":"ACCOUNT_DISABLED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"ACCOUNT_DISABLED":{"value":{"code":"ACCOUNT_DISABLED","message":"This user is disabled, please contact the administration.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Change my language","tags":["User · Account"],"security":[{"user":[]}]},"delete":{"description":"Call after the app's confirmation dialog; there is no code. Your details and files are removed, every device is signed out (this one included), and your number, email (and Iqama or CR number) can register a new, empty account.","operationId":"UserAccount_delete","parameters":[{"$ref":"#/components/parameters/AcceptLanguage"}],"responses":{"204":{"description":"The account was deleted."},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"UNAUTHORIZED":{"value":{"code":"UNAUTHORIZED","message":"Please log in to complete this action.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"403":{"description":"ACCOUNT_DISABLED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"ACCOUNT_DISABLED":{"value":{"code":"ACCOUNT_DISABLED","message":"This user is disabled, please contact the administration.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Delete my account","tags":["User · Account"],"security":[{"user":[]}]}},"/v1/user/account/change-mobile":{"post":{"description":"Step 1 of changing the mobile number: the code goes to the new number, and the answer carries the `verificationId` for step 2. Resend with `POST account/change-mobile/resend-otp`.","operationId":"UserAccount_requestCode","parameters":[{"$ref":"#/components/parameters/AcceptLanguage"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeMobileOtpDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerificationSentDto"}}}},"400":{"description":"MOBILE_UNCHANGED, VALIDATION_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"MOBILE_UNCHANGED":{"value":{"code":"MOBILE_UNCHANGED","message":"This is already your number","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}},"VALIDATION_FAILED":{"value":{"code":"VALIDATION_FAILED","message":"The request data is invalid","details":[{"field":"mobile","code":"isSaudiMobileRequired","message":"Mobile number must be entered."}],"requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"UNAUTHORIZED":{"value":{"code":"UNAUTHORIZED","message":"Please log in to complete this action.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"403":{"description":"ACCOUNT_DISABLED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"ACCOUNT_DISABLED":{"value":{"code":"ACCOUNT_DISABLED","message":"This user is disabled, please contact the administration.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"409":{"description":"MOBILE_ALREADY_REGISTERED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"MOBILE_ALREADY_REGISTERED":{"value":{"code":"MOBILE_ALREADY_REGISTERED","message":"The mobile number is already in use, please verify the number.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"429":{"description":"OTP_RESEND_TOO_SOON, TOO_MANY_REQUESTS","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"OTP_RESEND_TOO_SOON":{"value":{"code":"OTP_RESEND_TOO_SOON","message":"You can request a new code in {seconds} seconds.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}},"TOO_MANY_REQUESTS":{"value":{"code":"TOO_MANY_REQUESTS","message":"Too many requests, please try again shortly","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"503":{"description":"SMS_SEND_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"SMS_SEND_FAILED":{"value":{"code":"SMS_SEND_FAILED","message":"The verification code could not be sent. Please try again.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Send a code to a new number","tags":["User · Account"],"security":[{"user":[]}]}},"/v1/user/account/change-mobile/resend-otp":{"post":{"description":"Once `resendAfterSeconds` have passed: a new code for the `verificationId` from `account/change-mobile`, which stays the same.","operationId":"UserAccount_resendCode","parameters":[{"$ref":"#/components/parameters/AcceptLanguage"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResendCodeDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerificationSentDto"}}}},"400":{"description":"VERIFICATION_INVALID, VALIDATION_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"VERIFICATION_INVALID":{"value":{"code":"VERIFICATION_INVALID","message":"This verification is no longer valid. Please request a new code.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}},"VALIDATION_FAILED":{"value":{"code":"VALIDATION_FAILED","message":"The request data is invalid","details":[{"field":"mobile","code":"isSaudiMobileRequired","message":"Mobile number must be entered."}],"requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"UNAUTHORIZED":{"value":{"code":"UNAUTHORIZED","message":"Please log in to complete this action.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"403":{"description":"ACCOUNT_DISABLED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"ACCOUNT_DISABLED":{"value":{"code":"ACCOUNT_DISABLED","message":"This user is disabled, please contact the administration.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"429":{"description":"OTP_RESEND_TOO_SOON, TOO_MANY_REQUESTS","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"OTP_RESEND_TOO_SOON":{"value":{"code":"OTP_RESEND_TOO_SOON","message":"You can request a new code in {seconds} seconds.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}},"TOO_MANY_REQUESTS":{"value":{"code":"TOO_MANY_REQUESTS","message":"Too many requests, please try again shortly","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"503":{"description":"SMS_SEND_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"SMS_SEND_FAILED":{"value":{"code":"SMS_SEND_FAILED","message":"The verification code could not be sent. Please try again.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Resend the code to the new number","tags":["User · Account"],"security":[{"user":[]}]}},"/v1/user/account/change-mobile/verify":{"post":{"description":"Step 2: the `verificationId` and the code sent to the new number; swaps it in, and the old number no longer signs in. Every other device is signed out; this one stays signed in. A wrong code keeps the old number.","operationId":"UserAccount_changeMobile","parameters":[{"$ref":"#/components/parameters/AcceptLanguage"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeMobileDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserDto"}}}},"400":{"description":"MOBILE_UNCHANGED, VERIFICATION_INVALID, OTP_INVALID, OTP_EXPIRED, VALIDATION_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"MOBILE_UNCHANGED":{"value":{"code":"MOBILE_UNCHANGED","message":"This is already your number","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}},"VERIFICATION_INVALID":{"value":{"code":"VERIFICATION_INVALID","message":"This verification is no longer valid. Please request a new code.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}},"OTP_INVALID":{"value":{"code":"OTP_INVALID","message":"The verification code is incorrect.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}},"OTP_EXPIRED":{"value":{"code":"OTP_EXPIRED","message":"The verification code is invalid or expired. Please request a new one.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}},"VALIDATION_FAILED":{"value":{"code":"VALIDATION_FAILED","message":"The request data is invalid","details":[{"field":"mobile","code":"isSaudiMobileRequired","message":"Mobile number must be entered."}],"requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"UNAUTHORIZED":{"value":{"code":"UNAUTHORIZED","message":"Please log in to complete this action.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"403":{"description":"ACCOUNT_DISABLED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"ACCOUNT_DISABLED":{"value":{"code":"ACCOUNT_DISABLED","message":"This user is disabled, please contact the administration.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"409":{"description":"MOBILE_ALREADY_REGISTERED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"MOBILE_ALREADY_REGISTERED":{"value":{"code":"MOBILE_ALREADY_REGISTERED","message":"The mobile number is already in use, please verify the number.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"429":{"description":"OTP_TOO_MANY_ATTEMPTS","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"OTP_TOO_MANY_ATTEMPTS":{"value":{"code":"OTP_TOO_MANY_ATTEMPTS","message":"Too many incorrect attempts. Please request a new code.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Change my mobile number","tags":["User · Account"],"security":[{"user":[]}]}},"/v1/user/account/profile":{"patch":{"description":"JSON, only the fields that changed (the lab’s `ProfileDetails`): name, WhatsApp, email, photo, gender, date of birth. Optional fields sent empty or `null` are cleared. A new photo is a `user_avatar` file id from `POST /uploads`; the old photo is deleted. All or nothing: a refused field changes nothing. The answer is the account, as `GET /account`. The mobile changes through `account/change-mobile`.","operationId":"UserProfile_update","parameters":[{"$ref":"#/components/parameters/AcceptLanguage"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateProfileDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserDto"}}}},"400":{"description":"FILE_NOT_AVAILABLE, VALIDATION_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"FILE_NOT_AVAILABLE":{"value":{"code":"FILE_NOT_AVAILABLE","message":"This file can't be used. Please upload it again.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}},"VALIDATION_FAILED":{"value":{"code":"VALIDATION_FAILED","message":"The request data is invalid","details":[{"field":"mobile","code":"isSaudiMobileRequired","message":"Mobile number must be entered."}],"requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"UNAUTHORIZED":{"value":{"code":"UNAUTHORIZED","message":"Please log in to complete this action.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"403":{"description":"ACCOUNT_DISABLED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"ACCOUNT_DISABLED":{"value":{"code":"ACCOUNT_DISABLED","message":"This user is disabled, please contact the administration.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"409":{"description":"EMAIL_ALREADY_REGISTERED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"EMAIL_ALREADY_REGISTERED":{"value":{"code":"EMAIL_ALREADY_REGISTERED","message":"This email is already in use.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Save my profile","tags":["User · Account"],"security":[{"user":[]}]}},"/v1/user/regions":{"get":{"description":"The active tree in one answer (the lab’s `regions()`): regions, their cities, and the cities’ neighbourhoods, in the admin’s order, each name in Arabic and English. Public. The location screen, the ad form and the search filters pick from it (BRD v1.1: lists, no map). A neighbourhood is optional; many cities have none listed.","operationId":"UserPlaces_list","parameters":[{"$ref":"#/components/parameters/AcceptLanguage"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegionListDto"}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Regions, cities and neighbourhoods","tags":["User · Places"],"x-public":true,"security":[]}},"/v1/user/account/place":{"put":{"description":"The Location screen (BRD 4.1.7 v1.1: a region, a city in it, and optionally a neighbourhood, picked from `GET /regions`; the lab’s `updatePlace`). Home and the \"near me\" filter use it. Each refusal names its field: `REGION_NOT_AVAILABLE`, `CITY_NOT_AVAILABLE` (not active, or not in the region) or `NEIGHBORHOOD_NOT_AVAILABLE` (not active, or not in the city). Answers the account with its new `place`.","operationId":"UserPlace_set","parameters":[{"$ref":"#/components/parameters/AcceptLanguage"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetPlaceDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserDto"}}}},"400":{"description":"REGION_NOT_AVAILABLE, CITY_NOT_AVAILABLE, NEIGHBORHOOD_NOT_AVAILABLE, VALIDATION_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"REGION_NOT_AVAILABLE":{"value":{"code":"REGION_NOT_AVAILABLE","message":"This region is not available. Please choose another.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}},"CITY_NOT_AVAILABLE":{"value":{"code":"CITY_NOT_AVAILABLE","message":"This city is not available. Please choose another.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}},"NEIGHBORHOOD_NOT_AVAILABLE":{"value":{"code":"NEIGHBORHOOD_NOT_AVAILABLE","message":"This neighbourhood is not available. Please choose another.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}},"VALIDATION_FAILED":{"value":{"code":"VALIDATION_FAILED","message":"The request data is invalid","details":[{"field":"mobile","code":"isSaudiMobileRequired","message":"Mobile number must be entered."}],"requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"UNAUTHORIZED":{"value":{"code":"UNAUTHORIZED","message":"Please log in to complete this action.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"403":{"description":"ACCOUNT_DISABLED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"ACCOUNT_DISABLED":{"value":{"code":"ACCOUNT_DISABLED","message":"This user is disabled, please contact the administration.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Save my place","tags":["User · Account"],"security":[{"user":[]}]}},"/v1/user/uploads":{"post":{"description":"One file per request, as multipart/form-data in the `file` field (the lab’s `uploadMedia`). Its type is read from its bytes, not its name:\n\n- `ad_image`: PNG or JPG, up to 5 MB (10 per ad)\n- `ad_video`: MP4 or MOV, up to 20 MB (one per ad, instead of photos); answers a poster in `thumbnailUrl`\n- `user_avatar`: PNG or JPG, up to 5 MB\n\nThen send the `id` with the ad or the profile; only the account that uploaded a file can use it, once. Uploads unused after 24 hours are deleted. `TOO_MANY_REQUESTS` (with `Retry-After`) past the hourly limit.","operationId":"UserUploads_upload","parameters":[{"name":"purpose","required":true,"in":"query","description":"What the file is for; decides its types and size limit.","schema":{"type":"string","enum":["ad_image","ad_video","user_avatar"]}},{"$ref":"#/components/parameters/AcceptLanguage"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["file"],"properties":{"file":{"type":"string","format":"binary"}}}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadedMediaDto"}}}},"400":{"description":"FILE_REQUIRED, VALIDATION_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"FILE_REQUIRED":{"value":{"code":"FILE_REQUIRED","message":"No file was attached.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}},"VALIDATION_FAILED":{"value":{"code":"VALIDATION_FAILED","message":"The request data is invalid","details":[{"field":"mobile","code":"isSaudiMobileRequired","message":"Mobile number must be entered."}],"requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"UNAUTHORIZED":{"value":{"code":"UNAUTHORIZED","message":"Please log in to complete this action.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"403":{"description":"ACCOUNT_DISABLED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"ACCOUNT_DISABLED":{"value":{"code":"ACCOUNT_DISABLED","message":"This user is disabled, please contact the administration.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"413":{"description":"FILE_TOO_LARGE","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"FILE_TOO_LARGE":{"value":{"code":"FILE_TOO_LARGE","message":"File size exceeds the allowed limit ({maxMb} MB).","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"415":{"description":"FILE_TYPE_NOT_ALLOWED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"FILE_TYPE_NOT_ALLOWED":{"value":{"code":"FILE_TYPE_NOT_ALLOWED","message":"Unsupported file type. Allowed: {allowed}","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"429":{"description":"TOO_MANY_REQUESTS","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"TOO_MANY_REQUESTS":{"value":{"code":"TOO_MANY_REQUESTS","message":"Too many requests, please try again shortly","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Upload a photo or video","tags":["User · Uploads"],"security":[{"user":[]}]}},"/v1/user/account/identity/nafath":{"post":{"description":"Optional (BRD 4.1.5, v1.1; the lab’s `startNafath`). Sends a request to the user’s Nafath app and answers the two-digit `number` to show, with `expiresInSeconds` (120). An open request comes back as it is. The account’s `identity` becomes `pending`. Then poll `GET …/{id}` every 3 seconds. `TOO_MANY_ATTEMPTS` after three requests in 15 minutes, with `Retry-After` in seconds (the app shows the time). On test servers the fake Nafath answers after a few seconds: an ID ending in 1 is declined, 2 doesn’t match, 3 expires, any other is approved.","operationId":"Nafath_start","parameters":[{"$ref":"#/components/parameters/AcceptLanguage"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartNafathDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NafathRequestDto"}}}},"400":{"description":"VALIDATION_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"VALIDATION_FAILED":{"value":{"code":"VALIDATION_FAILED","message":"The request data is invalid","details":[{"field":"mobile","code":"isSaudiMobileRequired","message":"Mobile number must be entered."}],"requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"UNAUTHORIZED":{"value":{"code":"UNAUTHORIZED","message":"Please log in to complete this action.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"403":{"description":"ACCOUNT_DISABLED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"ACCOUNT_DISABLED":{"value":{"code":"ACCOUNT_DISABLED","message":"This user is disabled, please contact the administration.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"409":{"description":"ALREADY_VERIFIED, IDENTITY_ALREADY_USED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"ALREADY_VERIFIED":{"value":{"code":"ALREADY_VERIFIED","message":"Your identity is already verified.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}},"IDENTITY_ALREADY_USED":{"value":{"code":"IDENTITY_ALREADY_USED","message":"This ID number has already verified another account.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"429":{"description":"TOO_MANY_ATTEMPTS","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"TOO_MANY_ATTEMPTS":{"value":{"code":"TOO_MANY_ATTEMPTS","message":"Too many attempts. You can try again in {minutes} minutes.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Verify my identity with Nafath","tags":["User · Account"],"security":[{"user":[]}]}},"/v1/user/account/identity/nafath/{id}":{"get":{"description":"The waiting screen’s poll (the lab’s `nafathStatus`). Once `accepted`, the account is `verified` and shows the badge; `rejected`, `failed` and `expired` leave it unverified (its `identity` says which).","operationId":"Nafath_status","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"$ref":"#/components/parameters/AcceptLanguage"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NafathRequestDto"}}}},"400":{"description":"VALIDATION_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"VALIDATION_FAILED":{"value":{"code":"VALIDATION_FAILED","message":"The request data is invalid","details":[{"field":"mobile","code":"isSaudiMobileRequired","message":"Mobile number must be entered."}],"requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"UNAUTHORIZED":{"value":{"code":"UNAUTHORIZED","message":"Please log in to complete this action.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"403":{"description":"ACCOUNT_DISABLED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"ACCOUNT_DISABLED":{"value":{"code":"ACCOUNT_DISABLED","message":"This user is disabled, please contact the administration.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"404":{"description":"NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"NOT_FOUND":{"value":{"code":"NOT_FOUND","message":"The requested item was not found","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Check a Nafath request","tags":["User · Account"],"security":[{"user":[]}]}},"/v1/user/categories":{"get":{"description":"The active sections in the admin’s order (the lab’s `categories()`; BRD 4.1.8), each with its active subcategories and its own fields for the ad form and the ad’s specifications (D13): `number` (with an optional unit), `choice` (with options) or `text`. Names are in Arabic and English. Public. `iconUrl` is null until an admin uploads one; the app shows its bundled icon for `code` meanwhile.","operationId":"UserCategories_list","parameters":[{"$ref":"#/components/parameters/AcceptLanguage"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CategoryListDto"}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Sections, subcategories and their fields","tags":["User · Sections"],"x-public":true,"security":[]}},"/v1/user/settings":{"get":{"description":"What the admin controls and the app shows (the lab’s `settings()`): free ads per month, the auto-stop report count, VAT, the contribution switch, rates and text, the boost switch, and the store links. Rates are basis points (50 = 0.5%). Public and cached. The app never hard-codes these.","operationId":"UserSettings_read","parameters":[{"$ref":"#/components/parameters/AcceptLanguage"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppSettingsDto"}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Read app settings","tags":["User · Settings"],"x-public":true,"security":[]}},"/v1/user/content/pages/{kind}":{"get":{"description":"`about`, `terms`, `privacy` or `posting_guidelines` (the add-ad form’s link), as the admin last saved them (the lab’s `staticPage`; BRD 4.1.22, 4.3.20). Both languages at once, in the lab’s light markup: blank lines between paragraphs, `## ` headings, `- ` bullets. Public.","operationId":"UserPages_read","parameters":[{"name":"kind","required":true,"in":"path","schema":{"example":"terms","type":"string","enum":["about","terms","privacy","posting_guidelines"]}},{"$ref":"#/components/parameters/AcceptLanguage"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StaticPageDto"}}}},"400":{"description":"VALIDATION_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"VALIDATION_FAILED":{"value":{"code":"VALIDATION_FAILED","message":"The request data is invalid","details":[{"field":"mobile","code":"isSaudiMobileRequired","message":"Mobile number must be entered."}],"requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"404":{"description":"NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"NOT_FOUND":{"value":{"code":"NOT_FOUND","message":"The requested item was not found","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Read a static page","tags":["User · Content"],"x-public":true,"security":[]}},"/v1/user/contact":{"get":{"description":"The administration’s email, phone numbers and social accounts (the lab’s `contactInfo()`; only those the admin entered), and the message types with their names in Arabic and English. Public.","operationId":"UserContact_info","parameters":[{"$ref":"#/components/parameters/AcceptLanguage"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactInfoDto"}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Contact us screen","tags":["User · Contact"],"x-public":true,"security":[]}},"/v1/user/contact/messages":{"post":{"description":"To the administration (BRD 4.1.22; the lab’s `sendContactMessage`): type, name (2–50), email, Saudi mobile and the text (up to 500), all required. Guests can send; with a valid token the message is linked to the account, and a missing or expired token sends as a guest. At most 3 an hour per account (or mobile, for guests) and 5 an hour per network. On 201 the app shows `message`.","operationId":"UserContact_send","parameters":[{"$ref":"#/components/parameters/AcceptLanguage"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendContactMessageDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageSentDto"}}}},"400":{"description":"VALIDATION_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"VALIDATION_FAILED":{"value":{"code":"VALIDATION_FAILED","message":"The request data is invalid","details":[{"field":"mobile","code":"isSaudiMobileRequired","message":"Mobile number must be entered."}],"requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"429":{"description":"TOO_MANY_REQUESTS","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"TOO_MANY_REQUESTS":{"value":{"code":"TOO_MANY_REQUESTS","message":"Too many requests, please try again shortly","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Send a message","tags":["User · Contact"],"x-public":true,"security":[]}},"/v1/user/banners":{"get":{"description":"The banners running today (BRD 4.1.6, 4.3.13: active and inside their dates), in display order (the lab’s `PromoBanner`); an image or a video each, with the video’s poster. `link.type` says what a tap opens: an ad (`adId`), a section’s ads (`categoryId`), a web page (`url`) or nothing. Empty when none is running: the app hides the space. Also part of the home feed (API-051). Public.","operationId":"UserBanners_list","parameters":[{"$ref":"#/components/parameters/AcceptLanguage"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BannerListDto"}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Banners","tags":["User · Home"],"x-public":true,"security":[]}},"/v1/user/account/balance":{"get":{"description":"The free ads this month (the admin’s `freeAdsPerMonth`; unused ones don’t carry over) and the package’s ads (the lab’s `balance()`; BRD 4.1.13, 4.1.22).","operationId":"Credit_balance","parameters":[{"$ref":"#/components/parameters/AcceptLanguage"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BalanceDto"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"UNAUTHORIZED":{"value":{"code":"UNAUTHORIZED","message":"Please log in to complete this action.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"403":{"description":"ACCOUNT_DISABLED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"ACCOUNT_DISABLED":{"value":{"code":"ACCOUNT_DISABLED","message":"This user is disabled, please contact the administration.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"My ad balance","tags":["User · Ads"],"security":[{"user":[]}]}},"/v1/user/my-ads/posting-status":{"get":{"description":"Checked when the user taps \"Add an ad\" and after sending one (the lab’s `postingStatus()`): how many they can post, or why they can’t (`no_credit`, `package_expired`).","operationId":"Credit_postingStatus","parameters":[{"$ref":"#/components/parameters/AcceptLanguage"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostingStatusDto"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"UNAUTHORIZED":{"value":{"code":"UNAUTHORIZED","message":"Please log in to complete this action.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"403":{"description":"ACCOUNT_DISABLED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"ACCOUNT_DISABLED":{"value":{"code":"ACCOUNT_DISABLED","message":"This user is disabled, please contact the administration.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Can I post an ad?","tags":["User · Ads"],"security":[{"user":[]}]}},"/v1/user/my-ads":{"get":{"description":"The seller’s ads in every status, newest change first (BRD 4.1.14; the lab’s `myAds`), each with its allowed `actions`. `status` keeps one status (an active ad past its end date counts as `ended`). `counts` covers all the seller’s ads whatever the filter, for the tabs. Deleted ads are gone.","operationId":"MyAds_list","parameters":[{"name":"status","required":false,"in":"query","description":"Only ads with this status (an active ad past its end date is `ended`).","schema":{"type":"string","enum":["active","rejected","pending_review","paused","ended"]}},{"$ref":"#/components/parameters/AcceptLanguage"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MyAdsDto"}}}},"400":{"description":"VALIDATION_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"VALIDATION_FAILED":{"value":{"code":"VALIDATION_FAILED","message":"The request data is invalid","details":[{"field":"mobile","code":"isSaudiMobileRequired","message":"Mobile number must be entered."}],"requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"UNAUTHORIZED":{"value":{"code":"UNAUTHORIZED","message":"Please log in to complete this action.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"403":{"description":"ACCOUNT_DISABLED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"ACCOUNT_DISABLED":{"value":{"code":"ACCOUNT_DISABLED","message":"This user is disabled, please contact the administration.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"My ads","tags":["User · My ads"],"security":[{"user":[]}]},"post":{"description":"The add-ad form (BRD 4.1.13; the lab’s `submitAd`). Upload each photo or the video first (`POST /uploads`), then send their ids in `media`, in order. Takes one credit (free ads first, then the package) and creates the ad `pending_review`; an admin approves it (on test servers it may be approved automatically after a few seconds). Every field problem comes back at once in `details`. `NO_CREDIT` / `PACKAGE_EXPIRED` (402) when nothing is left: nothing is saved. Contact numbers come from the seller’s profile.","operationId":"MyAds_submit","parameters":[{"$ref":"#/components/parameters/AcceptLanguage"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdDraftDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MyAdDto"}}}},"400":{"description":"REGION_NOT_AVAILABLE, CITY_NOT_AVAILABLE, NEIGHBORHOOD_NOT_AVAILABLE, VALIDATION_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"REGION_NOT_AVAILABLE":{"value":{"code":"REGION_NOT_AVAILABLE","message":"This region is not available. Please choose another.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}},"CITY_NOT_AVAILABLE":{"value":{"code":"CITY_NOT_AVAILABLE","message":"This city is not available. Please choose another.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}},"NEIGHBORHOOD_NOT_AVAILABLE":{"value":{"code":"NEIGHBORHOOD_NOT_AVAILABLE","message":"This neighbourhood is not available. Please choose another.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}},"VALIDATION_FAILED":{"value":{"code":"VALIDATION_FAILED","message":"The request data is invalid","details":[{"field":"mobile","code":"isSaudiMobileRequired","message":"Mobile number must be entered."}],"requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"UNAUTHORIZED":{"value":{"code":"UNAUTHORIZED","message":"Please log in to complete this action.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"402":{"description":"NO_CREDIT, PACKAGE_EXPIRED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"NO_CREDIT":{"value":{"code":"NO_CREDIT","message":"You have used all your free ads for this month. Subscribe to a package to post more, or wait for next month.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}},"PACKAGE_EXPIRED":{"value":{"code":"PACKAGE_EXPIRED","message":"Your package has ended and this month's free ads are used up. Renew a package to post more, or wait for next month.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"403":{"description":"ACCOUNT_DISABLED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"ACCOUNT_DISABLED":{"value":{"code":"ACCOUNT_DISABLED","message":"This user is disabled, please contact the administration.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Send an ad for review","tags":["User · My ads"],"security":[{"user":[]}]}},"/v1/user/my-ads/{id}":{"get":{"description":"The seller’s ad in any status, with why it was rejected or stopped, featured-until, counters and allowed `actions` (the lab’s `allowedActions`). Anyone else’s ad, or a deleted one, is `NOT_FOUND`.","operationId":"MyAds_one","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"$ref":"#/components/parameters/AcceptLanguage"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MyAdDto"}}}},"400":{"description":"VALIDATION_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"VALIDATION_FAILED":{"value":{"code":"VALIDATION_FAILED","message":"The request data is invalid","details":[{"field":"mobile","code":"isSaudiMobileRequired","message":"Mobile number must be entered."}],"requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"UNAUTHORIZED":{"value":{"code":"UNAUTHORIZED","message":"Please log in to complete this action.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"403":{"description":"ACCOUNT_DISABLED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"ACCOUNT_DISABLED":{"value":{"code":"ACCOUNT_DISABLED","message":"This user is disabled, please contact the administration.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"404":{"description":"NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"NOT_FOUND":{"value":{"code":"NOT_FOUND","message":"The requested item was not found","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"One of my ads","tags":["User · My ads"],"security":[{"user":[]}]},"patch":{"description":"The whole form again, with the add-ad rules (BRD 4.1.17; the lab’s `updateAd`), free of charge. `media` may keep the ad’s current photos and add new uploads, in the new order; photos left out are deleted. An active ad stays published with the changes (D5: the admin sees it was edited); a rejected one goes back to review; a pending one keeps waiting. Paused and ended ads can’t be edited: `AD_ACTION_NOT_ALLOWED`.","operationId":"MyAds_edit","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"$ref":"#/components/parameters/AcceptLanguage"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdDraftDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MyAdDto"}}}},"400":{"description":"REGION_NOT_AVAILABLE, CITY_NOT_AVAILABLE, NEIGHBORHOOD_NOT_AVAILABLE, VALIDATION_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"REGION_NOT_AVAILABLE":{"value":{"code":"REGION_NOT_AVAILABLE","message":"This region is not available. Please choose another.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}},"CITY_NOT_AVAILABLE":{"value":{"code":"CITY_NOT_AVAILABLE","message":"This city is not available. Please choose another.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}},"NEIGHBORHOOD_NOT_AVAILABLE":{"value":{"code":"NEIGHBORHOOD_NOT_AVAILABLE","message":"This neighbourhood is not available. Please choose another.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}},"VALIDATION_FAILED":{"value":{"code":"VALIDATION_FAILED","message":"The request data is invalid","details":[{"field":"mobile","code":"isSaudiMobileRequired","message":"Mobile number must be entered."}],"requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"UNAUTHORIZED":{"value":{"code":"UNAUTHORIZED","message":"Please log in to complete this action.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"403":{"description":"ACCOUNT_DISABLED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"ACCOUNT_DISABLED":{"value":{"code":"ACCOUNT_DISABLED","message":"This user is disabled, please contact the administration.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"404":{"description":"NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"NOT_FOUND":{"value":{"code":"NOT_FOUND","message":"The requested item was not found","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"409":{"description":"AD_ACTION_NOT_ALLOWED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"AD_ACTION_NOT_ALLOWED":{"value":{"code":"AD_ACTION_NOT_ALLOWED","message":"You can't do this.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Edit my ad","tags":["User · My ads"],"security":[{"user":[]}]},"delete":{"description":"Deletes the ad whatever its status (BRD 4.1.18; the lab’s `deleteAd`): it leaves every list and favourite, and its photos are deleted. Answers what the contribution sheet needs, as ending does.","operationId":"MyAds_delete","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"$ref":"#/components/parameters/AcceptLanguage"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeletedAdDto"}}}},"400":{"description":"VALIDATION_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"VALIDATION_FAILED":{"value":{"code":"VALIDATION_FAILED","message":"The request data is invalid","details":[{"field":"mobile","code":"isSaudiMobileRequired","message":"Mobile number must be entered."}],"requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"UNAUTHORIZED":{"value":{"code":"UNAUTHORIZED","message":"Please log in to complete this action.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"403":{"description":"ACCOUNT_DISABLED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"ACCOUNT_DISABLED":{"value":{"code":"ACCOUNT_DISABLED","message":"This user is disabled, please contact the administration.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"404":{"description":"NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"NOT_FOUND":{"value":{"code":"NOT_FOUND","message":"The requested item was not found","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Delete my ad","tags":["User · My ads"],"security":[{"user":[]}]}},"/v1/user/my-ads/{id}/end":{"post":{"description":"Marks an active ad as ended (BRD 4.1.18; the lab’s `endAd`); it leaves every list at once. Only an active ad: `AD_ACTION_NOT_ALLOWED`. Answers the ad and what the contribution sheet needs (BRD 4.1.19): skip it when `contribution.enabled` is false.","operationId":"MyAds_end","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"$ref":"#/components/parameters/AcceptLanguage"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndedAdDto"}}}},"400":{"description":"VALIDATION_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"VALIDATION_FAILED":{"value":{"code":"VALIDATION_FAILED","message":"The request data is invalid","details":[{"field":"mobile","code":"isSaudiMobileRequired","message":"Mobile number must be entered."}],"requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"UNAUTHORIZED":{"value":{"code":"UNAUTHORIZED","message":"Please log in to complete this action.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"403":{"description":"ACCOUNT_DISABLED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"ACCOUNT_DISABLED":{"value":{"code":"ACCOUNT_DISABLED","message":"This user is disabled, please contact the administration.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"404":{"description":"NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"NOT_FOUND":{"value":{"code":"NOT_FOUND","message":"The requested item was not found","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"409":{"description":"AD_ACTION_NOT_ALLOWED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"AD_ACTION_NOT_ALLOWED":{"value":{"code":"AD_ACTION_NOT_ALLOWED","message":"You can't do this.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"End my ad (sold)","tags":["User · My ads"],"security":[{"user":[]}]}},"/v1/user/home":{"get":{"description":"Everything the home screen shows in one request (BRD 4.1.6; the lab’s `homeFeed`): the running banners, the active sections, and up to 10 ads in each of Featured (boosted, newest first), Latest and Most viewed. `cityId` keeps the ads to one city: the app sends the city the user chose, else their saved place; without it, every city. Ads are the lab’s `Ad`, as a guest sees them. Public.","operationId":"UserHome_feed","parameters":[{"name":"cityId","required":false,"in":"query","description":"Only ads in this city; all cities when left out.","schema":{"format":"uuid","type":"string"}},{"$ref":"#/components/parameters/AcceptLanguage"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HomeFeedDto"}}}},"400":{"description":"VALIDATION_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"VALIDATION_FAILED":{"value":{"code":"VALIDATION_FAILED","message":"The request data is invalid","details":[{"field":"mobile","code":"isSaudiMobileRequired","message":"Mobile number must be entered."}],"requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Home feed","tags":["User · Home"],"x-public":true,"security":[]}},"/v1/user/ads/suggestions":{"get":{"description":"While the user types (BRD 4.1.9; the lab’s `searchSuggestions`): up to 8 section and subcategory names, then titles of public ads, most viewed first, that contain the text, forgiving how Arabic is typed. Empty for blank text. Guests and signed-in users.","operationId":"UserAds_suggestions","parameters":[{"name":"q","required":false,"in":"query","description":"What the user has typed so far.","schema":{"maxLength":100,"example":"مجا","type":"string"}},{"$ref":"#/components/parameters/AcceptLanguage"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuggestionsDto"}}}},"400":{"description":"VALIDATION_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"VALIDATION_FAILED":{"value":{"code":"VALIDATION_FAILED","message":"The request data is invalid","details":[{"field":"mobile","code":"isSaudiMobileRequired","message":"Mobile number must be entered."}],"requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Search suggestions","tags":["User · Ads"],"x-public":true,"security":[]}},"/v1/user/ads":{"get":{"description":"The lab’s `searchAds(AdQuery)` (BRD 4.1.9, 4.1.10, 4.1.12). `q` is found anywhere in the title, English title or description, forgiving how Arabic is typed (أ/إ/آ = ا, ة = ه, ى/ئ = ي, ؤ = و, diacritics and tatweel ignored) and case. Filters: section, subcategory, region, city, price range (whole riyals, inclusive), advertiser. Order: featured ads first (`featuredFirst=false` for an advertiser’s page), then `sort`, then id. Paged by cursor: send `nextCursor` back with the same query for the next page; `total` comes with the first page. Only public ads. Guests and signed-in users.","operationId":"UserAds_list","parameters":[{"name":"q","required":false,"in":"query","description":"Found in the title, English title or description; forgiving of how Arabic is typed.","schema":{"maxLength":100,"example":"ناقه","type":"string"}},{"name":"categoryId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}},{"name":"subcategoryId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}},{"name":"regionId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}},{"name":"cityId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}},{"name":"minPrice","required":false,"in":"query","description":"Whole riyals, inclusive.","schema":{"minimum":0,"example":5000,"type":"number"}},{"name":"maxPrice","required":false,"in":"query","description":"Whole riyals, inclusive.","schema":{"minimum":0,"example":20000,"type":"number"}},{"name":"sellerId","required":false,"in":"query","description":"One advertiser's ads (their page, BRD 4.1.12).","schema":{"format":"uuid","type":"string"}},{"name":"sort","required":false,"in":"query","schema":{"example":"newest","type":"string","enum":["newest","price_asc","price_desc","most_viewed"]}},{"name":"featuredFirst","required":false,"in":"query","description":"Featured ads on top (BRD 4.1.9); `false` for an advertiser's page. Default true.","schema":{"type":"boolean"}},{"name":"cursor","required":false,"in":"query","description":"The `nextCursor` of the page before; send the same query with it.","schema":{"maxLength":300,"type":"string"}},{"name":"pageSize","required":false,"in":"query","description":"1–50, default 20.","schema":{"minimum":1,"maximum":50,"type":"number"}},{"$ref":"#/components/parameters/AcceptLanguage"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdPageDto"}}}},"400":{"description":"VALIDATION_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"VALIDATION_FAILED":{"value":{"code":"VALIDATION_FAILED","message":"The request data is invalid","details":[{"field":"mobile","code":"isSaudiMobileRequired","message":"Mobile number must be entered."}],"requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Search and browse ads","tags":["User · Ads"],"x-public":true,"security":[]}},"/v1/user/ads/{id}":{"get":{"description":"The ad’s page (BRD 4.1.11; the lab’s `ad(id)`): the lab’s `Ad`. The advertiser (`GET /advertisers/:id`) and the heart (favourites) come from their own routes, and the deals disclaimer is the app’s own text. An ad that isn’t public (waiting, stopped, ended, deleted, or its section or seller hidden) is `AD_UNAVAILABLE` (410), unless it’s the caller’s own (any status but deleted); an unknown id is `NOT_FOUND`. Counts a view: once per viewer per 24 hours (D6), never the seller’s own. Guests: send `X-Device-Id` (a stable id the app makes once) so a guest is one viewer. Guests and signed-in users.","operationId":"UserAds_open","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Device-Id","required":false,"in":"header","description":"A guest’s stable device id (8–64 letters, digits, `-` or `_`).","schema":{"type":"string"}},{"$ref":"#/components/parameters/AcceptLanguage"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdDto"}}}},"400":{"description":"VALIDATION_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"VALIDATION_FAILED":{"value":{"code":"VALIDATION_FAILED","message":"The request data is invalid","details":[{"field":"mobile","code":"isSaudiMobileRequired","message":"Mobile number must be entered."}],"requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"404":{"description":"NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"NOT_FOUND":{"value":{"code":"NOT_FOUND","message":"The requested item was not found","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"410":{"description":"AD_UNAVAILABLE","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"AD_UNAVAILABLE":{"value":{"code":"AD_UNAVAILABLE","message":"This ad is no longer available.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"An ad","tags":["User · Ads"],"x-public":true,"security":[]}},"/v1/user/ads/{id}/events":{"post":{"description":"Send when the user taps Call or WhatsApp on the ad’s page; the seller and the control panel see the counts. Once per viewer per 24 hours (D6); the seller’s own taps aren’t counted. Public ads only (`AD_UNAVAILABLE`). Guests and signed-in users.","operationId":"UserAds_event","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Device-Id","required":false,"in":"header","schema":{"type":"string"}},{"$ref":"#/components/parameters/AcceptLanguage"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdEventDto"}}}},"responses":{"204":{"description":""},"400":{"description":"VALIDATION_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"VALIDATION_FAILED":{"value":{"code":"VALIDATION_FAILED","message":"The request data is invalid","details":[{"field":"mobile","code":"isSaudiMobileRequired","message":"Mobile number must be entered."}],"requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"404":{"description":"NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"NOT_FOUND":{"value":{"code":"NOT_FOUND","message":"The requested item was not found","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"410":{"description":"AD_UNAVAILABLE","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"AD_UNAVAILABLE":{"value":{"code":"AD_UNAVAILABLE","message":"This ad is no longer available.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Count a tap on Call or WhatsApp","tags":["User · Ads"],"x-public":true,"security":[]}},"/v1/user/ads/{id}/share":{"post":{"description":"The ad’s link for the share sheet (BRD 4.1.11; the lab’s `shareLink`), counting a share: once per viewer per 24 hours (D6), the seller’s own included. Public ads only (`AD_UNAVAILABLE`). The link opens the ad’s page or the app (API-074). Guests and signed-in users.","operationId":"UserAds_share","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Device-Id","required":false,"in":"header","schema":{"type":"string"}},{"$ref":"#/components/parameters/AcceptLanguage"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShareLinkDto"}}}},"400":{"description":"VALIDATION_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"VALIDATION_FAILED":{"value":{"code":"VALIDATION_FAILED","message":"The request data is invalid","details":[{"field":"mobile","code":"isSaudiMobileRequired","message":"Mobile number must be entered."}],"requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"404":{"description":"NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"NOT_FOUND":{"value":{"code":"NOT_FOUND","message":"The requested item was not found","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"410":{"description":"AD_UNAVAILABLE","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"AD_UNAVAILABLE":{"value":{"code":"AD_UNAVAILABLE","message":"This ad is no longer available.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Share an ad","tags":["User · Ads"],"x-public":true,"security":[]}},"/v1/user/recent-searches":{"get":{"description":"Newest first, at most 10 (the lab’s `recentSearches`; BRD 4.1.9). Kept on the server for signed-in users so they follow the account (D10); guests keep theirs on the device.","operationId":"RecentSearches_list","parameters":[{"$ref":"#/components/parameters/AcceptLanguage"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecentSearchesDto"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"UNAUTHORIZED":{"value":{"code":"UNAUTHORIZED","message":"Please log in to complete this action.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"403":{"description":"ACCOUNT_DISABLED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"ACCOUNT_DISABLED":{"value":{"code":"ACCOUNT_DISABLED","message":"This user is disabled, please contact the administration.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"My recent searches","tags":["User · Ads"],"security":[{"user":[]}]},"post":{"description":"The lab’s `addRecentSearch`: call it when a search is run. Repeating one (any wording that searches the same: \"ناقه\" = \"ناقة\") moves it to the top with the new wording instead of adding a copy; the oldest beyond 10 go. A blank one is ignored.","operationId":"RecentSearches_add","parameters":[{"$ref":"#/components/parameters/AcceptLanguage"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddRecentSearchDto"}}}},"responses":{"204":{"description":""},"400":{"description":"VALIDATION_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"VALIDATION_FAILED":{"value":{"code":"VALIDATION_FAILED","message":"The request data is invalid","details":[{"field":"mobile","code":"isSaudiMobileRequired","message":"Mobile number must be entered."}],"requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"UNAUTHORIZED":{"value":{"code":"UNAUTHORIZED","message":"Please log in to complete this action.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"403":{"description":"ACCOUNT_DISABLED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"ACCOUNT_DISABLED":{"value":{"code":"ACCOUNT_DISABLED","message":"This user is disabled, please contact the administration.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Remember a search","tags":["User · Ads"],"security":[{"user":[]}]},"delete":{"description":"With `text`, that one search (the lab’s `removeRecentSearch`); without, all of them (`clearRecentSearches`).","operationId":"RecentSearches_remove","parameters":[{"name":"text","required":false,"in":"query","schema":{"maxLength":100,"type":"string"}},{"$ref":"#/components/parameters/AcceptLanguage"}],"responses":{"204":{"description":""},"400":{"description":"VALIDATION_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"VALIDATION_FAILED":{"value":{"code":"VALIDATION_FAILED","message":"The request data is invalid","details":[{"field":"mobile","code":"isSaudiMobileRequired","message":"Mobile number must be entered."}],"requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"UNAUTHORIZED":{"value":{"code":"UNAUTHORIZED","message":"Please log in to complete this action.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"403":{"description":"ACCOUNT_DISABLED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"ACCOUNT_DISABLED":{"value":{"code":"ACCOUNT_DISABLED","message":"This user is disabled, please contact the administration.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Forget recent searches","tags":["User · Ads"],"security":[{"user":[]}]}},"/v1/user/advertisers/{id}":{"get":{"description":"The advertiser’s page (BRD 4.1.12; the lab’s `advertiser(id)`): name, photo, place, when they joined, whether Nafath verified them, how many public ads they have and in which sections. Their ads: `GET /ads?sellerId={id}&featuredFirst=false` (newest first). A disabled account is `ADVERTISER_UNAVAILABLE` (410); an unknown or deleted one is `NOT_FOUND`. Guests and signed-in users.","operationId":"UserAdvertisers_find","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"$ref":"#/components/parameters/AcceptLanguage"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdvertiserDto"}}}},"400":{"description":"VALIDATION_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"VALIDATION_FAILED":{"value":{"code":"VALIDATION_FAILED","message":"The request data is invalid","details":[{"field":"mobile","code":"isSaudiMobileRequired","message":"Mobile number must be entered."}],"requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"404":{"description":"NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"NOT_FOUND":{"value":{"code":"NOT_FOUND","message":"The requested item was not found","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"410":{"description":"ADVERTISER_UNAVAILABLE","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"ADVERTISER_UNAVAILABLE":{"value":{"code":"ADVERTISER_UNAVAILABLE","message":"This advertiser's page isn't available.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"An advertiser","tags":["User · Ads"],"x-public":true,"security":[]}},"/v1/user/favorites":{"get":{"description":"The saved ads, most recently saved first (BRD 4.1.20; the lab’s `favorites`), as the lab’s `Ad`. Ended and deleted ads drop out; one the admin stopped or sent back to review stays with its `status`, for the app to show as unavailable.","operationId":"Favorites_list","parameters":[{"$ref":"#/components/parameters/AcceptLanguage"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FavoriteListDto"}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"UNAUTHORIZED":{"value":{"code":"UNAUTHORIZED","message":"Please log in to complete this action.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"403":{"description":"ACCOUNT_DISABLED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"ACCOUNT_DISABLED":{"value":{"code":"ACCOUNT_DISABLED","message":"This user is disabled, please contact the administration.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"My favourites","tags":["User · Favourites"],"security":[{"user":[]}]}},"/v1/user/favorites/{adId}":{"get":{"description":"The heart on an ad’s page (the lab’s `isFavorite`).","operationId":"Favorites_has","parameters":[{"name":"adId","required":true,"in":"path","schema":{"type":"string"}},{"$ref":"#/components/parameters/AcceptLanguage"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FavoriteStateDto"}}}},"400":{"description":"VALIDATION_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"VALIDATION_FAILED":{"value":{"code":"VALIDATION_FAILED","message":"The request data is invalid","details":[{"field":"mobile","code":"isSaudiMobileRequired","message":"Mobile number must be entered."}],"requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"UNAUTHORIZED":{"value":{"code":"UNAUTHORIZED","message":"Please log in to complete this action.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"403":{"description":"ACCOUNT_DISABLED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"ACCOUNT_DISABLED":{"value":{"code":"ACCOUNT_DISABLED","message":"This user is disabled, please contact the administration.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Is it a favourite?","tags":["User · Favourites"],"security":[{"user":[]}]},"put":{"description":"The heart, on (the lab’s `toggleFavorite` when it isn’t saved). Saving it again changes nothing. Only a public ad: `AD_UNAVAILABLE` otherwise.","operationId":"Favorites_add","parameters":[{"name":"adId","required":true,"in":"path","schema":{"type":"string"}},{"$ref":"#/components/parameters/AcceptLanguage"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FavoriteStateDto"}}}},"400":{"description":"VALIDATION_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"VALIDATION_FAILED":{"value":{"code":"VALIDATION_FAILED","message":"The request data is invalid","details":[{"field":"mobile","code":"isSaudiMobileRequired","message":"Mobile number must be entered."}],"requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"UNAUTHORIZED":{"value":{"code":"UNAUTHORIZED","message":"Please log in to complete this action.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"403":{"description":"ACCOUNT_DISABLED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"ACCOUNT_DISABLED":{"value":{"code":"ACCOUNT_DISABLED","message":"This user is disabled, please contact the administration.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"404":{"description":"NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"NOT_FOUND":{"value":{"code":"NOT_FOUND","message":"The requested item was not found","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"410":{"description":"AD_UNAVAILABLE","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"AD_UNAVAILABLE":{"value":{"code":"AD_UNAVAILABLE","message":"This ad is no longer available.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Save an ad","tags":["User · Favourites"],"security":[{"user":[]}]},"delete":{"description":"The heart, off (the lab’s `toggleFavorite` when it is saved), whatever the ad’s state now. Removing one that isn’t saved changes nothing.","operationId":"Favorites_remove","parameters":[{"name":"adId","required":true,"in":"path","schema":{"type":"string"}},{"$ref":"#/components/parameters/AcceptLanguage"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FavoriteStateDto"}}}},"400":{"description":"VALIDATION_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"VALIDATION_FAILED":{"value":{"code":"VALIDATION_FAILED","message":"The request data is invalid","details":[{"field":"mobile","code":"isSaudiMobileRequired","message":"Mobile number must be entered."}],"requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"UNAUTHORIZED":{"value":{"code":"UNAUTHORIZED","message":"Please log in to complete this action.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"403":{"description":"ACCOUNT_DISABLED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"ACCOUNT_DISABLED":{"value":{"code":"ACCOUNT_DISABLED","message":"This user is disabled, please contact the administration.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Unsave an ad","tags":["User · Favourites"],"security":[{"user":[]}]}},"/v1/user/ads/{id}/reports":{"post":{"description":"The report sheet (BRD 4.1.11; the lab’s `reportAd`): a reason (`inappropriate`, `misleading`, `duplicate`, `prohibited`, `other`) and details (up to 500 characters; required for `other`). One report per user per ad (`ALREADY_REPORTED`); never on your own ad (`AD_ACTION_NOT_ALLOWED`). When an active ad’s open reports reach the admin’s threshold (`auto_block.reports`, 5 by default), it is stopped at once. Signed-in users only (guests sign in first, as in the lab).","operationId":"Reports_report","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"$ref":"#/components/parameters/AcceptLanguage"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportAdDto"}}}},"responses":{"204":{"description":""},"400":{"description":"VALIDATION_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"VALIDATION_FAILED":{"value":{"code":"VALIDATION_FAILED","message":"The request data is invalid","details":[{"field":"mobile","code":"isSaudiMobileRequired","message":"Mobile number must be entered."}],"requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"401":{"description":"UNAUTHORIZED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"UNAUTHORIZED":{"value":{"code":"UNAUTHORIZED","message":"Please log in to complete this action.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"403":{"description":"ACCOUNT_DISABLED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"ACCOUNT_DISABLED":{"value":{"code":"ACCOUNT_DISABLED","message":"This user is disabled, please contact the administration.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"404":{"description":"NOT_FOUND","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"NOT_FOUND":{"value":{"code":"NOT_FOUND","message":"The requested item was not found","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"409":{"description":"ALREADY_REPORTED, AD_ACTION_NOT_ALLOWED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"ALREADY_REPORTED":{"value":{"code":"ALREADY_REPORTED","message":"You have already reported this ad.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}},"AD_ACTION_NOT_ALLOWED":{"value":{"code":"AD_ACTION_NOT_ALLOWED","message":"You can't do this.","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}},"500":{"description":"INTERNAL_ERROR","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"INTERNAL_ERROR":{"value":{"code":"INTERNAL_ERROR","message":"Something went wrong, please try again","requestId":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}}}}},"summary":"Report an ad","tags":["User · Ads"],"security":[{"user":[]}]}}},"info":{"title":"Bayatak API","description":"One API for the two Bayatak clients: the mobile app for guests and signed-in users, who both browse and sell (`/v1/user`), and the admin control panel (`/v1/admin`).\n\n**Authentication.** Each namespace has its own opaque session token, sent as `Authorization: Bearer <token>`. Tokens are revocable server-side; a token from one namespace is rejected by the others. Routes without a lock are public: guests can call them, and some recognise a signed-in caller too.\n\n**Errors.** Every error has the same shape: `{ code, message, details?, requestId }`. Branch on `code`, which is stable; `message` is translated for display. For `VALIDATION_FAILED`, `details` lists each field problem as `{ field, code, message }`, where `code` is the rule that failed (e.g. `isSaudiMobileRequired` for an empty mobile, `isSaudiMobile` for an invalid one), and `message` is the first of them, ready to show, with the field's name in front when the text doesn't say it (\"Mobile number: A valid number must be entered.\").\n\n**Mobile numbers** are accepted as typed (`05XXXXXXXX`, `+9665…`, Arabic-Indic digits) and returned in E.164 (`+9665XXXXXXXX`).\n\n**Language.** Messages are Arabic by default. Send `Accept-Language: en` (or `?lang=en`) for English. When signed in, the account's saved language is used if the request names none. Error responses carry `Content-Language`.\n\n**Request IDs.** Every response has an `X-Request-Id` header; quote it when reporting a problem.","version":"0.0.1","contact":{}},"tags":[{"name":"User · Account"},{"name":"User · Ads"},{"name":"User · Auth"},{"name":"User · Contact"},{"name":"User · Content"},{"name":"User · Favourites"},{"name":"User · Home"},{"name":"User · My ads"},{"name":"User · Places"},{"name":"User · Sections"},{"name":"User · Settings"},{"name":"User · Uploads"},{"name":"System"}],"servers":[],"components":{"securitySchemes":{"user":{"scheme":"bearer","bearerFormat":"opaque session token","type":"http","description":"Session token from the user sign-in."},"admin":{"scheme":"bearer","bearerFormat":"opaque session token","type":"http","description":"Session token from the admin sign-in."}},"schemas":{"DependencyCheckDto":{"type":"object","properties":{"status":{"type":"string","description":"Whether the dependency answered within the timeout.","example":"up","enum":["up","down"]},"latencyMs":{"type":"number","description":"How long the check took, in milliseconds.","example":1.8}},"required":["status","latencyMs"]},"HealthChecksDto":{"type":"object","properties":{"database":{"description":"MySQL (`select 1`). The API can't serve requests without it.","allOf":[{"$ref":"#/components/schemas/DependencyCheckDto"}]},"cache":{"description":"Redis (`PING`). Without it the API still works, uncached.","allOf":[{"$ref":"#/components/schemas/DependencyCheckDto"}]}},"required":["database","cache"]},"HealthResponseDto":{"type":"object","properties":{"status":{"description":"`ok` when everything is up; `degraded` when only the cache is down\n(still 200); `down` when the database is down (503).","example":"ok","enum":["down","ok","degraded"],"type":"string"},"checks":{"$ref":"#/components/schemas/HealthChecksDto"}},"required":["status","checks"]},"LivenessResponseDto":{"type":"object","properties":{"status":{"type":"string","description":"Always `ok` while the process is serving requests.","example":"ok","enum":["ok"]}},"required":["status"]},"RegisterDto":{"type":"object","properties":{"name":{"type":"string","description":"Letters and numbers only, 2–100 characters.","example":"فهد القحطاني"},"mobile":{"type":"string","description":"Saudi mobile number, `05XXXXXXXX`. The code goes here, and it signs in.","example":"0501234567"},"whatsapp":{"type":"string","description":"Optional: the number buyers reach on WhatsApp, `05XXXXXXXX`.","example":"0501234567"},"email":{"type":"string","description":"Optional; unique across accounts, at most 100 characters.","example":"fahad@example.com"},"acceptTerms":{"type":"boolean","description":"The Terms and Conditions checkbox; must be `true`."}},"required":["name","mobile","acceptTerms"]},"VerificationSentDto":{"type":"object","properties":{"verificationId":{"type":"string","description":"Send it back with the code, and to resend the code.","example":"vrf_Zk3n0x8Qy1u4b2V7s9Lr5mT6pWcA0dEfGhIjKlMnOpQ"},"expiresAt":{"format":"date-time","type":"string","description":"When the code stops working (BRD: 60 seconds)."},"resendAfterSeconds":{"type":"number","description":"Seconds until \"resend\" may be offered (the app's countdown).","example":60},"verificationExpiresAt":{"format":"date-time","type":"string","description":"When `verificationId` stops working (10 minutes): after that, start\nagain from the first step."}},"required":["verificationId","expiresAt","resendAfterSeconds","verificationExpiresAt"]},"ResendCodeDto":{"type":"object","properties":{"verificationId":{"type":"string","description":"From the first step's answer."}},"required":["verificationId"]},"VerifyCodeDto":{"type":"object","properties":{"verificationId":{"type":"string","description":"From the first step's answer.","example":"vrf_Zk3n0x8Qy1u4b2V7s9Lr5mT6pWcA0dEfGhIjKlMnOpQ"},"code":{"type":"string","description":"The code from the SMS or email (`1234` while the fake drivers are on).","example":"1234"}},"required":["verificationId","code"]},"PlaceDto":{"type":"object","properties":{"regionId":{"type":"string"},"cityId":{"type":"string"},"neighborhoodId":{"type":"string","nullable":true}},"required":["regionId","cityId","neighborhoodId"]},"UserDto":{"type":"object","properties":{"id":{"type":"string","example":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"},"name":{"type":"string","nullable":true,"example":"فهد القحطاني"},"mobile":{"type":"string","description":"E.164.","example":"+966501234567"},"whatsapp":{"type":"string","nullable":true,"description":"E.164, or null.","example":"+966501234567"},"email":{"type":"string","nullable":true,"example":"fahad@example.com"},"avatarUrl":{"type":"string","nullable":true,"description":"The profile photo; set from the profile (API-025)."},"place":{"nullable":true,"description":"Where the user is (BRD 4.1.7), or null until they pick a place.","type":"object","allOf":[{"$ref":"#/components/schemas/PlaceDto"}]},"gender":{"nullable":true,"example":"male","enum":["male","female"],"type":"string"},"birthDate":{"type":"string","nullable":true,"description":"The day only.","example":"1995-04-12"},"identity":{"description":"Nafath verification (optional, BRD v1.1): `verified` shows the badge.","example":"unverified","enum":["pending","unverified","verified","failed","rejected"],"type":"string"},"verifiedAt":{"format":"date-time","type":"string","nullable":true,"description":"When Nafath confirmed the identity."},"language":{"description":"Used when a request names no language, and for SMS.","example":"ar","enum":["ar","en"],"type":"string"},"joinedAt":{"format":"date-time","type":"string","description":"When the account was created."}},"required":["id","name","mobile","whatsapp","email","avatarUrl","place","gender","birthDate","identity","verifiedAt","language","joinedAt"]},"UserSessionDto":{"type":"object","properties":{"accessToken":{"type":"string","description":"The session token, shown only once. Send it as `Authorization: Bearer …`.","example":"bk_usr_3q2-7wEvxN1c9kP0YyR5bA8dF6gH4jL2mZ1xV7sT0uQ"},"user":{"$ref":"#/components/schemas/UserDto"}},"required":["accessToken","user"]},"UserLoginDto":{"type":"object","properties":{"mobile":{"type":"string","description":"A registered Saudi mobile number, `05XXXXXXXX`.","example":"0501234567"}},"required":["mobile"]},"UpdateAccountDto":{"type":"object","properties":{"language":{"type":"string","description":"The app's language. Requests without `Accept-Language` or `?lang=` are\nanswered in it, and SMS messages are sent in it.","example":"en","enum":["ar","en"]}},"required":["language"]},"ChangeMobileOtpDto":{"type":"object","properties":{"mobile":{"type":"string","description":"Saudi mobile number, `05XXXXXXXX` (`5…` and `+9665…` are accepted too).","example":"0551234567"}},"required":["mobile"]},"ChangeMobileDto":{"type":"object","properties":{"verificationId":{"type":"string","description":"From the first step's answer.","example":"vrf_Zk3n0x8Qy1u4b2V7s9Lr5mT6pWcA0dEfGhIjKlMnOpQ"},"code":{"type":"string","description":"The code from the SMS or email (`1234` while the fake drivers are on).","example":"1234"}},"required":["verificationId","code"]},"UpdateProfileDto":{"type":"object","properties":{"name":{"type":"string","description":"Letters and digits, 2–100 characters.","example":"فهد القحطاني"},"whatsapp":{"type":"string","nullable":true,"description":"The number buyers reach on WhatsApp, `05XXXXXXXX`; empty removes it.","example":"0501234567"},"email":{"type":"string","nullable":true,"description":"Unique across accounts, at most 100 characters; empty removes it.","example":"fahad@example.com"},"avatarFileId":{"type":"string","nullable":true,"description":"A `user_avatar` file from `POST /uploads` (PNG or JPG up to 5 MB); the\nold photo is deleted. Empty or `null` removes the photo."},"gender":{"type":"string","nullable":true,"description":"`male` or `female`; empty or `null` clears it.","enum":["male","female"]},"birthDate":{"type":"string","nullable":true,"description":"`YYYY-MM-DD`, not in the future; empty or `null` clears it.","example":"1995-04-12"}}},"LocalizedTextDto":{"type":"object","properties":{"ar":{"type":"string","example":"الرياض"},"en":{"type":"string","example":"Riyadh"}},"required":["ar","en"]},"NeighborhoodDto":{"type":"object","properties":{"id":{"type":"string","example":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"},"cityId":{"type":"string"},"name":{"$ref":"#/components/schemas/LocalizedTextDto"}},"required":["id","cityId","name"]},"CityDto":{"type":"object","properties":{"id":{"type":"string","example":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"},"regionId":{"type":"string"},"name":{"$ref":"#/components/schemas/LocalizedTextDto"},"neighborhoods":{"description":"Active ones, in the admin's order; often empty (it's optional).","type":"array","items":{"$ref":"#/components/schemas/NeighborhoodDto"}}},"required":["id","regionId","name","neighborhoods"]},"RegionDto":{"type":"object","properties":{"id":{"type":"string","example":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"},"name":{"$ref":"#/components/schemas/LocalizedTextDto"},"cities":{"description":"Active ones, in the admin's order.","type":"array","items":{"$ref":"#/components/schemas/CityDto"}}},"required":["id","name","cities"]},"RegionListDto":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/RegionDto"}}},"required":["items"]},"SetPlaceDto":{"type":"object","properties":{"regionId":{"type":"string","example":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"},"cityId":{"type":"string","example":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7c"},"neighborhoodId":{"type":"string","nullable":true,"description":"Optional; empty or null for none."}},"required":["regionId","cityId"]},"UploadedMediaDto":{"type":"object","properties":{"id":{"type":"string","example":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"},"type":{"type":"string","example":"image","enum":["image","video"]},"url":{"type":"string","example":"https://api.bayatak.sa/files/0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"},"thumbnailUrl":{"type":"string","nullable":true,"description":"A video's poster frame; null for photos, or when none could be made."},"name":{"type":"string","example":"camel.jpg"},"mimeType":{"type":"string","example":"image/jpeg"},"size":{"type":"number","description":"Bytes.","example":482113}},"required":["id","type","url","thumbnailUrl","name","mimeType","size"]},"StartNafathDto":{"type":"object","properties":{"nationalId":{"type":"string","description":"National ID (starts with 1) or residence number (starts with 2), 10\ndigits; Arabic-Indic digits are accepted.","example":"1012345678"}},"required":["nationalId"]},"NafathRequestDto":{"type":"object","properties":{"id":{"type":"string","example":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"},"number":{"type":"number","description":"The number to choose in the Nafath app, 10–99.","example":42},"status":{"description":"`waiting` until Nafath answers; then `accepted` (verified), `rejected`\n(declined in Nafath), `failed` (didn't match) or `expired` (2 minutes\npassed).","example":"waiting","enum":["accepted","failed","rejected","waiting","expired"],"type":"string"},"expiresAt":{"format":"date-time","type":"string"},"expiresInSeconds":{"type":"number","description":"Seconds left when the server answered; the countdown runs from this,\nnot the phone's clock (the lab's `expiresIn`). 0 once answered.","example":120}},"required":["id","number","status","expiresAt","expiresInSeconds"]},"SubcategoryDto":{"type":"object","properties":{"id":{"type":"string","example":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"},"categoryId":{"type":"string"},"name":{"$ref":"#/components/schemas/LocalizedTextDto"},"sortOrder":{"type":"number"}},"required":["id","categoryId","name","sortOrder"]},"FieldOptionDto":{"type":"object","properties":{"id":{"type":"string","description":"What an ad stores for this choice.","example":"female"},"name":{"$ref":"#/components/schemas/LocalizedTextDto"}},"required":["id","name"]},"CategoryFieldDto":{"type":"object","properties":{"id":{"type":"string","description":"The key an ad's `specs` use for this field."},"name":{"$ref":"#/components/schemas/LocalizedTextDto"},"kind":{"type":"string","example":"number","enum":["number","choice","text"]},"unit":{"nullable":true,"description":"After a number (\"years\", \"head\", \"L\"); null when none.","type":"object","allOf":[{"$ref":"#/components/schemas/LocalizedTextDto"}]},"options":{"description":"For `choice` fields, in order; empty otherwise.","type":"array","items":{"$ref":"#/components/schemas/FieldOptionDto"}},"required":{"type":"boolean"}},"required":["id","name","kind","unit","options","required"]},"CategoryDto":{"type":"object","properties":{"id":{"type":"string","example":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"},"code":{"type":"string","nullable":true,"description":"The seed slug (`camels`, `horses`…), for the app's bundled icons until\nan admin uploads one; null for sections admins add.","example":"camels"},"name":{"$ref":"#/components/schemas/LocalizedTextDto"},"iconUrl":{"type":"string","nullable":true,"description":"The admin's icon; null until one is uploaded."},"sortOrder":{"type":"number"},"subcategories":{"description":"Active ones, in the admin's order.","type":"array","items":{"$ref":"#/components/schemas/SubcategoryDto"}},"fields":{"description":"Active ones, in the admin's order (D13).","type":"array","items":{"$ref":"#/components/schemas/CategoryFieldDto"}}},"required":["id","code","name","iconUrl","sortOrder","subcategories","fields"]},"CategoryListDto":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/CategoryDto"}}},"required":["items"]},"AppLinksDto":{"type":"object","properties":{"ios":{"type":"string","nullable":true,"example":"https://apps.apple.com/app/id0000000000"},"android":{"type":"string","nullable":true,"example":"https://play.google.com/store/apps/details?id=sa.bayatak.app"}},"required":["ios","android"]},"AppSettingsDto":{"type":"object","properties":{"freeAdsPerMonth":{"type":"number","description":"Free ads each user gets per calendar month.","example":7},"reportsToAutoBlock":{"type":"number","description":"Reports on one ad after which it is stopped.","example":5},"vatBasisPoints":{"type":"number","description":"VAT added to package and boost prices.","example":1500},"contributionsEnabled":{"type":"boolean","description":"Whether ending or deleting an ad offers a contribution."},"contributionRateBasisPoints":{"type":"number","description":"Suggested contribution, as a share of the sale price.","example":50},"charityShareBasisPoints":{"type":"number","description":"The charity's share of each contribution; the rest supports the app.","example":2500},"contributionText":{"nullable":true,"description":"The admin's encouragement text; null to keep the app's own.","type":"object","allOf":[{"$ref":"#/components/schemas/LocalizedTextDto"}]},"boostsEnabled":{"type":"boolean","description":"Whether ads can be boosted (featured)."},"appLinks":{"description":"The store links; null until published.","allOf":[{"$ref":"#/components/schemas/AppLinksDto"}]}},"required":["freeAdsPerMonth","reportsToAutoBlock","vatBasisPoints","contributionsEnabled","contributionRateBasisPoints","charityShareBasisPoints","contributionText","boostsEnabled","appLinks"]},"StaticPageDto":{"type":"object","properties":{"kind":{"type":"string","example":"terms","enum":["about","terms","privacy","posting_guidelines"]},"body":{"description":"Both languages, in the lab's light markup (D4): blank lines between\nparagraphs, a line starting `## ` is a heading, `- ` a bullet.","allOf":[{"$ref":"#/components/schemas/LocalizedTextDto"}]},"updatedAt":{"format":"date-time","type":"string","description":"The \"last updated\" date the page shows."}},"required":["kind","body","updatedAt"]},"SocialLinksDto":{"type":"object","properties":{"whatsapp":{"type":"string","description":"A WhatsApp number, E.164.","example":"+966551234567"},"x":{"type":"string","example":"https://x.com/bayatak"},"instagram":{"type":"string","example":"https://instagram.com/bayatak"},"snapchat":{"type":"string","example":"https://snapchat.com/add/bayatak"},"tiktok":{"type":"string","example":"https://tiktok.com/@bayatak"},"facebook":{"type":"string","example":"https://facebook.com/bayatak"}}},"ContactTypeDto":{"type":"object","properties":{"id":{"type":"string","example":"inquiry","enum":["request","suggestion","inquiry","complaint","other"]},"name":{"$ref":"#/components/schemas/LocalizedTextDto"}},"required":["id","name"]},"ContactInfoDto":{"type":"object","properties":{"email":{"type":"string","nullable":true,"example":"support@bayatak.sa"},"phones":{"description":"E.164, in the admin's order; empty when none.","example":["+966112345678"],"type":"array","items":{"type":"string"}},"social":{"description":"Configured networks only.","allOf":[{"$ref":"#/components/schemas/SocialLinksDto"}]},"messageTypes":{"description":"The message types, in order.","type":"array","items":{"$ref":"#/components/schemas/ContactTypeDto"}}},"required":["email","phones","social","messageTypes"]},"SendContactMessageDto":{"type":"object","properties":{"type":{"type":"string","description":"One of the types from `GET contact`; required (the lab).","example":"inquiry","enum":["request","suggestion","inquiry","complaint","other"]},"name":{"type":"string","description":"2–50 letters and numbers.","example":"سارة العتيبي"},"email":{"type":"string","example":"sara@example.com"},"mobile":{"type":"string","description":"Saudi mobile, 05XXXXXXXX.","example":"0551234567"},"text":{"type":"string","description":"At most 500 characters.","example":"كيف أوثّق حسابي عبر نفاذ؟"}},"required":["type","name","email","mobile","text"]},"MessageSentDto":{"type":"object","properties":{"id":{"type":"string","example":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"},"message":{"type":"string","description":"What the app shows, in the request language.","example":"تم إرسال رسالتك بنجاح."},"createdAt":{"format":"date-time","type":"string"}},"required":["id","message","createdAt"]},"BannerLinkDto":{"type":"object","properties":{"type":{"type":"string","description":"`ad`: that ad (`adId`); `category`: that section's ads (`categoryId`);\n`external`: the web page `url`; `none`: nothing.","example":"category","enum":["none","external","ad","category"]},"adId":{"type":"string","nullable":true},"categoryId":{"type":"string","nullable":true},"url":{"type":"string","nullable":true,"example":"https://example.com/offer"}},"required":["type","adId","categoryId","url"]},"BannerDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string","example":"موسم الإبل"},"mediaUrl":{"type":"string"},"isVideo":{"type":"boolean"},"posterUrl":{"type":"string","nullable":true,"description":"A video's poster frame, shown before it plays; null for images."},"link":{"$ref":"#/components/schemas/BannerLinkDto"},"endsAt":{"format":"date-time","type":"string","description":"When it stops showing: the end of its last day in Saudi Arabia."}},"required":["id","name","mediaUrl","isVideo","posterUrl","link","endsAt"]},"BannerListDto":{"type":"object","properties":{"items":{"description":"In display order; empty when none is running (the app hides the space).","type":"array","items":{"$ref":"#/components/schemas/BannerDto"}}},"required":["items"]},"PackageBalanceDto":{"type":"object","properties":{"subscriptionId":{"type":"string"},"endsAt":{"format":"date-time","type":"string"},"adsTotal":{"type":"number"},"adsUsed":{"type":"number"},"adsRemaining":{"type":"number","description":"0 once its period ends or its ads run out."}},"required":["subscriptionId","endsAt","adsTotal","adsUsed","adsRemaining"]},"BalanceDto":{"type":"object","properties":{"month":{"type":"string","description":"The first day of the month the free ads count against (Saudi time).","example":"2026-11-01"},"freeAllowance":{"type":"number","example":7},"freeUsed":{"type":"number","example":2},"freeRemaining":{"type":"number","example":5},"package":{"nullable":true,"description":"The current or last package; null when none (API-062).","type":"object","allOf":[{"$ref":"#/components/schemas/PackageBalanceDto"}]},"totalRemaining":{"type":"number","description":"Free and package ads left together.","example":5}},"required":["month","freeAllowance","freeUsed","freeRemaining","package","totalRemaining"]},"PostingStatusDto":{"type":"object","properties":{"remaining":{"type":"number","description":"Free and package ads left together.","example":5},"block":{"type":"string","nullable":true,"description":"Null when they can post; else `no_credit` (free ads used up, no\npackage) or `package_expired` (and the package has ended).","enum":["no_credit","package_expired"]}},"required":["remaining","block"]},"AdMediaDto":{"type":"object","properties":{"type":{"type":"string","example":"image","enum":["image","video"]},"url":{"type":"string"},"thumbnailUrl":{"type":"string","nullable":true,"description":"A video's poster frame; null for photos."}},"required":["type","url","thumbnailUrl"]},"MyAdDto":{"type":"object","properties":{"actions":{"type":"array","description":"The lab's `allowedActions`.","example":["edit","delete"],"items":{"type":"string","enum":["share","end","delete","edit","boost"]}},"id":{"type":"string"},"sellerId":{"type":"string"},"title":{"type":"string","example":"ناقة مجاهيم عمر 4 سنوات"},"titleEn":{"type":"string","nullable":true},"description":{"type":"string"},"categoryId":{"type":"string"},"subcategoryId":{"type":"string","nullable":true},"price":{"type":"number","description":"Whole Saudi riyals.","example":12500},"media":{"description":"In order; the first is the main image.","type":"array","items":{"$ref":"#/components/schemas/AdMediaDto"}},"place":{"$ref":"#/components/schemas/PlaceDto"},"status":{"example":"pending_review","enum":["active","rejected","pending_review","paused","ended"],"type":"string"},"statusReason":{"type":"string","nullable":true,"description":"Why an admin rejected or stopped it. Only its seller sees it."},"createdAt":{"format":"date-time","type":"string"},"updatedAt":{"format":"date-time","type":"string"},"publishedAt":{"format":"date-time","type":"string","nullable":true,"description":"When an admin approved it."},"expiresAt":{"format":"date-time","type":"string","nullable":true,"description":"The seller's end date: the ad ends itself after it."},"featuredUntil":{"format":"date-time","type":"string","nullable":true,"description":"Featured (boosted) until then."},"views":{"type":"number"},"shares":{"type":"number"},"phone":{"type":"string","description":"The seller's mobile, from their profile (BRD 4.1.13). E.164."},"whatsapp":{"type":"string","nullable":true,"description":"The seller's WhatsApp, from their profile; null when none."},"chargedTo":{"nullable":true,"description":"Which balance paid for it; null when not charged. Only its seller sees it.","enum":["free_allowance","package"],"type":"string"},"specs":{"type":"object","additionalProperties":{"type":"string"},"description":"The section's fields: field id → value (a choice as its option id)."}},"required":["actions","id","sellerId","title","titleEn","description","categoryId","subcategoryId","price","media","place","status","statusReason","createdAt","updatedAt","publishedAt","expiresAt","featuredUntil","views","shares","phone","whatsapp","chargedTo","specs"]},"MyAdCountsDto":{"type":"object","properties":{"all":{"type":"number","example":7},"active":{"type":"number","example":3},"pending_review":{"type":"number","example":1},"paused":{"type":"number","example":1},"rejected":{"type":"number","example":0},"ended":{"type":"number","example":2}},"required":["all","active","pending_review","paused","rejected","ended"]},"MyAdsDto":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/MyAdDto"}},"counts":{"$ref":"#/components/schemas/MyAdCountsDto"}},"required":["items","counts"]},"AdDraftDto":{"type":"object","properties":{"title":{"type":"string","description":"3–50 characters.","example":"ناقة مجاهيم عمر 4 سنوات"},"titleEn":{"type":"string","nullable":true,"description":"Optional English title, 3–50 characters.","example":"Majaheem she-camel, 4 years"},"description":{"type":"string","description":"Up to 500 characters."},"price":{"type":"number","description":"Whole Saudi riyals, more than 0. Arabic-Indic digits are accepted in\na string.","example":12500},"categoryId":{"type":"string","description":"A section from `GET /categories`."},"subcategoryId":{"type":"string","nullable":true,"description":"Optional: one of the section's subcategories."},"media":{"description":"In order (the first is the main image): up to 10 `ad_image` uploads,\nor one `ad_video`, from `POST /uploads`.","type":"array","items":{"type":"string"}},"regionId":{"type":"string","description":"From `GET /regions`."},"cityId":{"type":"string","description":"A city in the region."},"neighborhoodId":{"type":"string","nullable":true,"description":"Optional: a neighbourhood in the city."},"expiresOn":{"type":"string","nullable":true,"description":"Optional end date, `YYYY-MM-DD`, after today (Saudi time): the ad\nstops itself at the end of that day. Null or empty for none.","example":"2026-12-31"},"specs":{"type":"object","additionalProperties":true,"description":"The section's own fields, by field id from `GET /categories`: a number\nas digits, a choice as its option id, text as typed (up to 100).","example":{"0199a3c4-…":"female"}}},"required":["title","description","price","categoryId","media","regionId","cityId"]},"ContributionOfferDto":{"type":"object","properties":{"enabled":{"type":"boolean"},"salePrice":{"type":"number","description":"The ad's price, whole riyals.","example":12500},"suggestedHalalas":{"type":"number","description":"The admin's rate of the price, in halalas.","example":6250},"rateBasisPoints":{"type":"number","description":"Basis points.","example":50},"charityShareBasisPoints":{"type":"number","description":"The charity's share of a contribution, basis points.","example":2500}},"required":["enabled","salePrice","suggestedHalalas","rateBasisPoints","charityShareBasisPoints"]},"EndedAdDto":{"type":"object","properties":{"ad":{"$ref":"#/components/schemas/MyAdDto"},"contribution":{"$ref":"#/components/schemas/ContributionOfferDto"}},"required":["ad","contribution"]},"DeletedAdDto":{"type":"object","properties":{"id":{"type":"string"},"contribution":{"$ref":"#/components/schemas/ContributionOfferDto"}},"required":["id","contribution"]},"AdDto":{"type":"object","properties":{"id":{"type":"string"},"sellerId":{"type":"string"},"title":{"type":"string","example":"ناقة مجاهيم عمر 4 سنوات"},"titleEn":{"type":"string","nullable":true},"description":{"type":"string"},"categoryId":{"type":"string"},"subcategoryId":{"type":"string","nullable":true},"price":{"type":"number","description":"Whole Saudi riyals.","example":12500},"media":{"description":"In order; the first is the main image.","type":"array","items":{"$ref":"#/components/schemas/AdMediaDto"}},"place":{"$ref":"#/components/schemas/PlaceDto"},"status":{"example":"pending_review","enum":["active","rejected","pending_review","paused","ended"],"type":"string"},"statusReason":{"type":"string","nullable":true,"description":"Why an admin rejected or stopped it. Only its seller sees it."},"createdAt":{"format":"date-time","type":"string"},"updatedAt":{"format":"date-time","type":"string"},"publishedAt":{"format":"date-time","type":"string","nullable":true,"description":"When an admin approved it."},"expiresAt":{"format":"date-time","type":"string","nullable":true,"description":"The seller's end date: the ad ends itself after it."},"featuredUntil":{"format":"date-time","type":"string","nullable":true,"description":"Featured (boosted) until then."},"views":{"type":"number"},"shares":{"type":"number"},"phone":{"type":"string","description":"The seller's mobile, from their profile (BRD 4.1.13). E.164."},"whatsapp":{"type":"string","nullable":true,"description":"The seller's WhatsApp, from their profile; null when none."},"chargedTo":{"nullable":true,"description":"Which balance paid for it; null when not charged. Only its seller sees it.","enum":["free_allowance","package"],"type":"string"},"specs":{"type":"object","additionalProperties":{"type":"string"},"description":"The section's fields: field id → value (a choice as its option id)."}},"required":["id","sellerId","title","titleEn","description","categoryId","subcategoryId","price","media","place","status","statusReason","createdAt","updatedAt","publishedAt","expiresAt","featuredUntil","views","shares","phone","whatsapp","chargedTo","specs"]},"HomeFeedDto":{"type":"object","properties":{"banners":{"type":"array","items":{"$ref":"#/components/schemas/BannerDto"}},"categories":{"description":"The active sections, in order.","type":"array","items":{"$ref":"#/components/schemas/CategoryDto"}},"featured":{"description":"Featured (boosted) ads, newest first.","type":"array","items":{"$ref":"#/components/schemas/AdDto"}},"latest":{"description":"The newest ads.","type":"array","items":{"$ref":"#/components/schemas/AdDto"}},"mostViewed":{"description":"The most viewed ads.","type":"array","items":{"$ref":"#/components/schemas/AdDto"}}},"required":["banners","categories","featured","latest","mostViewed"]},"SuggestionsDto":{"type":"object","properties":{"items":{"example":["مجاهيم","ناقة مجاهيم للبيع"],"type":"array","items":{"type":"string"}}},"required":["items"]},"AdPageDto":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/AdDto"}},"nextCursor":{"type":"string","nullable":true,"description":"Null on the last page."},"total":{"type":"number","nullable":true,"description":"How many match, on the first page only (null on later pages).","example":137}},"required":["items","nextCursor","total"]},"AdEventDto":{"type":"object","properties":{"type":{"type":"string","example":"call","enum":["whatsapp","call"]}},"required":["type"]},"ShareLinkDto":{"type":"object","properties":{"url":{"type":"string","description":"Opens the ad (in the app when installed).","example":"https://bayatak.sa/s/ads/01a1c560-ecc9-767b-8c68-1c97f2ba2da2"}},"required":["url"]},"RecentSearchesDto":{"type":"object","properties":{"items":{"example":["ناقة مجاهيم","صقر حر"],"type":"array","items":{"type":"string"}}},"required":["items"]},"AddRecentSearchDto":{"type":"object","properties":{"text":{"type":"string","description":"What the user searched for. A blank one is ignored.","example":"ناقة مجاهيم","maxLength":100}},"required":["text"]},"AdvertiserDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string","example":"فهد القحطاني"},"avatarUrl":{"type":"string","nullable":true},"place":{"nullable":true,"description":"Their saved place, when they have one.","type":"object","allOf":[{"$ref":"#/components/schemas/PlaceDto"}]},"joinedAt":{"format":"date-time","type":"string","description":"When they joined."},"verified":{"type":"boolean","description":"Identity verified through Nafath."},"activeAdCount":{"type":"number","description":"How many of their ads are public now.","example":4},"categoryIds":{"description":"The sections of those ads, in section order, for the filter on their page.","type":"array","items":{"type":"string"}}},"required":["id","name","avatarUrl","place","joinedAt","verified","activeAdCount","categoryIds"]},"FavoriteListDto":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/AdDto"}}},"required":["items"]},"FavoriteStateDto":{"type":"object","properties":{"favorite":{"type":"boolean"}},"required":["favorite"]},"ReportAdDto":{"type":"object","properties":{"reason":{"type":"string","example":"misleading","enum":["other","inappropriate","misleading","duplicate","prohibited"]},"details":{"type":"string","nullable":true,"description":"Up to 500 characters; required when the reason is `other`."}},"required":["reason"]},"ErrorResponse":{"type":"object","required":["code","message","requestId"],"properties":{"code":{"type":"string","enum":["VALIDATION_FAILED","INVALID_JSON","UNAUTHORIZED","FORBIDDEN","ACCOUNT_DISABLED","NOT_FOUND","CONFLICT","PAYLOAD_TOO_LARGE","TOO_MANY_REQUESTS","MOBILE_NOT_REGISTERED","MOBILE_ALREADY_REGISTERED","MOBILE_UNCHANGED","ALREADY_VERIFIED","IDENTITY_ALREADY_USED","TOO_MANY_ATTEMPTS","AD_ACTION_NOT_ALLOWED","AD_UNAVAILABLE","ADVERTISER_UNAVAILABLE","ALREADY_REPORTED","NO_CREDIT","PACKAGE_EXPIRED","REGION_NOT_AVAILABLE","CITY_NOT_AVAILABLE","NEIGHBORHOOD_NOT_AVAILABLE","EMAIL_ALREADY_REGISTERED","OTP_INVALID","OTP_EXPIRED","OTP_TOO_MANY_ATTEMPTS","OTP_RESEND_TOO_SOON","VERIFICATION_INVALID","SMS_SEND_FAILED","EMAIL_SEND_FAILED","FILE_REQUIRED","FILE_TOO_LARGE","FILE_TYPE_NOT_ALLOWED","FILE_NOT_AVAILABLE","INTERNAL_ERROR"],"description":"Stable error code. Clients branch on this.","example":"NOT_FOUND"},"message":{"type":"string","description":"Translated message for display.","example":"The requested item was not found"},"details":{"type":"array","description":"Field problems, only for `VALIDATION_FAILED`.","items":{"type":"object","required":["field","code","message"],"properties":{"field":{"type":"string","description":"Dotted path, for example `address.city`.","example":"mobile"},"code":{"type":"string","description":"The rule that failed, e.g. `isSaudiMobileRequired` (empty) or `isSaudiMobile` (invalid).","example":"isSaudiMobileRequired"},"message":{"type":"string","example":"Mobile number must be entered."}}}},"requestId":{"type":"string","description":"Same as the `X-Request-Id` response header.","example":"0199a3c4-5b6e-7f80-9a1b-2c3d4e5f6a7b"}}}},"parameters":{"AcceptLanguage":{"name":"Accept-Language","in":"header","required":false,"description":"Language of messages. Arabic by default.","schema":{"type":"string","enum":["ar","en"],"default":"ar"}}}}}