HOCO B2B
SRSAPI reference

Me, devices, app config & reference data

The signed-in user's profile and devices, the start-up configuration of each app (version policy, maintenance, public settings) and the cacheable reference data: wilayas, communes and reference lists.

This group holds what every client loads before its first business screen:

  • me.get / me.update — the signed-in user as the Me object (defined once on the authentication page): identity, account status, roles, permissions, customer type, support region, reseller or delegate context.
  • me.devices.* — the push registration of each mobile install (Firebase Cloud Messaging token, app version, locale).
  • appConfig.get — public, called on the splash screen before sign-in: version policy, maintenance flag and the public business settings the apps need to render rules (minimum order, GPS tolerance, support contacts…). Guests use it too.
  • reference.* — wilayas and communes (public, ETag cached) and the reference lists behind every dropdown (session required).
MethodPathOperationAccessAppsRelease
GET/meme.get
My profile, roles, permissions, scope (reseller or delegate context) and account status
sessionRA · RW · DA · BOV1
PATCH/meme.update
Update my name, locale or avatar
sessionRA · RW · DA · BOV1
POST/me/deletion-requestme.deleteAccount
Request deletion of my account (Play policy): sessions revoked, personal data anonymised after the legal retention period; business records kept
session
Idempotency-Key
RA · RWV1
POST/me/devicesme.devices.register
Register or refresh this device's FCM token and app version
session
Idempotency-Key
RA · DAV1
DELETE/me/devices/{deviceId}me.devices.remove
Unregister a device
sessionRA · DAV1
GET/app-configappConfig.get
Version policy (min/latest/forced), maintenance flag and public business settings for an app/platform
publicRA · RW · DAV1
GET/reference/wilayasreference.wilayas
Wilayas (code, FR/AR names); cacheable with ETag
publicRA · RW · DA · BOV1
GET/reference/wilayas/{wilayaCode}/communesreference.communes
Communes of a wilaya; cacheable with ETag
publicRA · RW · DA · BOV1
GET/reference/listsreference.lists
Reference lists (business types, potentials, visit types, not-done reasons, issue tags, ticket types, payment methods); cacheable
sessionRA · RW · DA · BOV1

Besides the errors listed per operation, every operation can answer 426 UPGRADE_REQUIRED (except appConfig.get, auth.logout and, for 72 hours after the minimum was raised, the delegate app's sync.batch — AUTH-09), 429 RATE_LIMITED, 500 INTERNAL_ERROR and 503 MAINTENANCE; session operations also 401 UNAUTHENTICATED and 403 ACCOUNT_SUSPENDED. See the error registry.

Start-up sequence

Splash (RA-01, DA-01). GET /app-config?app=RESELLER_APP&platform=android&version=1.4.2. If forceUpdate → forced-update screen (RA-36 / DA-28) with storeUrl; if maintenance.enabled → maintenance screen with message and until; if updateAvailable → dismissible banner.

Session check. With a stored token: GET /me. 401 → clear the token; the reseller app continues as a guest (RA-02 / RA-41), the delegate app goes to sign-in (DA-02). 403 PASSWORD_CHANGE_REQUIRED or user.mustChangePassword → change-password screen.

Device. Signed in on mobile: POST /me/devices with the current FCM token (every start, cheap and idempotent).

Reference data. Revalidate the cached wilayas, communes and lists with If-None-Match (usually 304). The delegate app also stores the communes of its zone's wilayas for offline prospect creation.

Operations

GET /me

me.get · Access session (any user type) · Apps RA, RW, DA, BO · Idempotency-Key — · Release V1 · Requirements ACL-02, ACL-03, AUTH-08

Purpose. Returns the signed-in user with everything the client needs to route and gate its screens: status, roles, permissions, customer type, support region and the reseller or delegate context.

Request — no parameters.

Response — 200 OK, Cache-Control: private, no-store. Body: a Me object (examples for the three user types on the authentication page).

{
  "id": "01a19c3e-5a10-7b21-8f4e-2c6d9a1b3e57",
  "type": "RESELLER",
  "displayName": "Mohamed Benali",
  "phone": "+213555123456",
  "phoneVerified": true,
  "email": null,
  "locale": "fr",
  "status": "ACTIVE",
  "roles": ["RESELLER"],
  "permissions": [],
  "mustChangePassword": false,
  "avatar": null,
  "consents": {
    "termsVersion": "2026-11",
    "termsAcceptedAt": "2026-11-03T08:12:00Z",
    "locationTrackingVersion": null,
    "locationTrackingAcceptedAt": null
  },
  "supportRegion": { "id": "01a0c7e2-41d0-7a6b-9c3e-5f1a2b3c4d5e", "name": "Ouest", "whatsappNumber": "+213770900310" },
  "reseller": {
    "id": "01a17f02-93c4-7e8a-b1d2-4f5a6b7c8d90",
    "number": "REV-000123",
    "storeName": "Magasin El Wafa",
    "customerType": "DEMI_GROS",
    "status": "FIRST_ORDER",
    "validationStatus": "APPROVED",
    "rejectionReason": null,
    "canResubmit": false,
    "wilayaCode": "31",
    "assignedDelegate": { "id": "01a0f2b1-7d3c-7a45-9e61-0b2c3d4e5f60", "displayName": "Yacine Belkacem", "phone": "+213770123456" }
  },
  "createdAt": "2026-11-03T08:12:00Z",
  "lastLoginAt": "2026-11-05T07:45:10Z"
}

Errors — none specific (401 UNAUTHENTICATED with details.reason when the session is gone).

Rules & side effects

  1. Read-only, computed on every call (never cached by the server across users). Mapping: displayName ← User.name; email is null for the placeholder addresses of phone-only users; avatar ← User.avatarFileId; consents ← User.termsVersion/termsAcceptedAt and DelegateProfile.locationConsentVersion/locationConsentAt; the reseller context ← Reseller; supportRegion ← SupportRegionWilaya of the reseller's wilaya; delegate ← DelegateProfile (its id equals User.id) and DelegateZone.
  2. Clients refresh Me at start-up, when the app returns to the foreground after more than 15 minutes, and when they receive a notification whose eventKey starts with account. (validation, rejection, customer-type change, suspension).

Used by — splash of RA-01 and DA-01; account hubs RA-27 and DA-24; RA-06 (pending / rejected state); the back-office shell BO-03 (navigation by permission); RW-12.

PATCH /me

me.update · Access session (any user type) · Apps RA, RW, DA, BO · Idempotency-Key optional · Release V1 · Requirements NFR-06

Purpose. Lets users change their own name, language and avatar, change their phone after an OTP check, and record consents (terms, delegate location tracking).

Request

interface MeUpdateRequest {
  displayName?: string;              // 2–80 characters
  locale?: "fr" | "ar" | "en";
  avatarFileId?: Uuid | null;        // a completed File of purpose AVATAR uploaded by the caller; null removes it
  phone?: string;                    // new phone — requires phoneVerificationToken
  phoneVerificationToken?: string;   // auth.otp.verify, purpose PHONE_CHANGE, same phone
  consents?: {
    terms?: { version: string };                                   // resellers: re-acceptance of updated terms
    locationTracking?: { accepted: boolean; version: string };     // delegates (DA-04)
  };
}
{
  "locale": "ar",
  "avatarFileId": "01a1a0b9-4c2d-7e6f-8a1b-2c3d4e5f6a7b"
}

Response — 200 OK: the updated Me.

Errors

StatusCodeWhen
400VALIDATION_FAILEDField errors (TOO_SHORT, INVALID_ENUM, INVALID_PHONE); phone without phoneVerificationToken; consents.locationTracking sent by a non-delegate or consents.terms by a non-reseller.
404NOT_FOUNDavatarFileId unknown or uploaded by someone else.
422FILE_NOT_READYThe avatar file was never completed (files.completeUpload).
409PHONE_ALREADY_EXISTSThe new phone belongs to another account or another point of sale.
422FILE_PURPOSE_MISMATCHThe file's purpose is not AVATAR.
422VERIFICATION_TOKEN_INVALIDToken expired, used, of another purpose, issued for another phone or to another user.
422TERMS_NOT_ACCEPTEDconsents.terms.version is not the current legal.termsVersion of appConfig.get.

Rules & side effects

  1. Name. displayName is stored as User.name. For a reseller it is the store manager's name: it is written to User.name and the reseller's owner name in one transaction (the same mirroring applies when the owner name changes through the reseller profile).
  2. Locale. Drives the language of push, SMS and email templates and the default of Accept-Language-less calls. V1 ships French; ar and en are accepted from day one (NFR-06) and offered once their translations ship (D-09).
  3. Phone change. User.phone changes; for a reseller the main phone of the Reseller changes too (uniqueness re-checked, previous value kept in the history). Other sessions stay valid. security.phone_changed is sent by SMS to the old number and in-app (Assumption — event to add to the notifications matrix).
  4. Consents. Terms go to User.termsVersion / termsAcceptedAt; location consent to DelegateProfile.locationConsentVersion / locationConsentAt. A delegate withdrawing location consent (accepted: false) clears them: the app stops sending pings and a tour cannot start until consent is given again (SEC-07).
  5. Not editable here: email (staff: by an administrator; resellers: store profile), customer type (back-office only — AUTH-11), roles and status.
  6. Audit UPDATE with the changed fields (password and tokens are never logged).

Used by — settings RA-35 (language, phone), DA-26, RW-12, BO-68; avatar on RA-27 and DA-24; location consent on DA-04 (« J'accepte »).

POST /me/devices

me.devices.register · Access session (RESELLER, DELEGATE) · Apps RA, DA · Idempotency-Key required · Release V1 · Requirements AUTH-09, NOT-02

Purpose. Registers this app install for push notifications, or refreshes its FCM token, app version and locale.

Request

interface DeviceRegistration {
  deviceId: string;                  // install id — must equal the X-Device-Id header
  platform: "android" | "ios";
  pushToken: string | null;          // FCM registration token (Device.fcmToken); null when notification permission is denied
  appId: "RESELLER_APP" | "DELEGATE_APP";   // ClientApp
  appVersion: string;                // semver, "1.4.2"
  locale: "fr" | "ar" | "en";        // device language, informative (Me.locale drives templates)
  osVersion?: string;                // "Android 14"
  model?: string;                    // "Samsung SM-A155F"
}
{
  "deviceId": "5f8c2a1e-7b3d-4e9f-a6c0-1d2e3f4a5b6c",
  "platform": "android",
  "pushToken": "fJ3k9L0aQ2W:APA91bH7xY4Zr2mTq8VwN1cPs5dE6gK0uB3oR9tL7yX2nM4",
  "appId": "RESELLER_APP",
  "appVersion": "1.4.2",
  "locale": "fr",
  "osVersion": "Android 14",
  "model": "Samsung SM-A155F"
}

Response — 201 Created on the first registration of this install, 200 OK on a refresh.

{
  "deviceId": "5f8c2a1e-7b3d-4e9f-a6c0-1d2e3f4a5b6c",
  "platform": "android",
  "appId": "RESELLER_APP",
  "appVersion": "1.4.2",
  "pushEnabled": true,
  "registeredAt": "2026-11-03T08:12:04Z",
  "lastSeenAt": "2026-11-05T07:45:12Z"
}

Errors

StatusCodeWhen
400VALIDATION_FAILEDdeviceId differs from X-Device-Id (field code DEVICE_ID_MISMATCH), bad semver, unknown platform.
403WRONG_APPappId does not match the user type (a reseller registering DELEGATE_APP).

Rules & side effects

  1. Upsert on (userId, deviceId). A device belongs to one user at a time: if the same install id is bound to another user (shared phone, previous user signed out offline), that binding is removed and the previous user stops receiving push on it. platform is stored as ANDROID/IOS; pushEnabled is true when a token is present.
  2. The device is bound to the current session: revoking the session (sign-out, password change, auth.sessions.revoke, suspension) clears its push token.
  3. An FCM token already registered on another device id is removed there (tokens are unique).
  4. Call it after every sign-in, at each app start, on FCM onTokenRefresh, after an app update and when the user changes the notification permission. pushToken: null keeps the device known for version statistics (BO-66) without push.
  5. FCM answers UNREGISTERED for a dead token → the notification worker deletes it; the app re-registers on its next start. Devices not seen for 90 days are pruned.

Used by — after sign-in on RA-07, RA-05 and DA-02; app start; the « Notifications sur cet appareil » switch of RA-35 and DA-26.

DELETE /me/devices/{deviceId}

me.devices.remove · Access session (RESELLER, DELEGATE; own devices) · Apps RA, DA · Idempotency-Key optional · Release V1 · Requirements AUTH-09

Purpose. Stops push notifications to one install without signing it out.

Request

Path parameterTypeNotes
deviceIdstringThe install id (X-Device-Id), not a server id.

Response — 204 No Content, also when the device is already absent (idempotent).

Errors — none specific.

Rules & side effects — the Device row is deleted, so no push reaches this install; the session on that device stays valid (use auth.sessions.revoke to sign it out). The in-app inbox keeps receiving every notification.

Used by — the « Notifications sur cet appareil » switch turned off in RA-35 and DA-26.

GET /app-config

appConfig.get · Access public (guests included) · Apps RA, RW, DA · Idempotency-Key — · Release V1 · Requirements ADM-07, ADM-03

Purpose. Gives an app, before anything else, its version policy (minimum, latest, forced update), the maintenance state and the public business settings it needs to display rules and contacts.

Request

Query parameterRequiredValuesNotes
appyesRESELLER_APP, DELEGATE_APP, RESELLER_WEBClientApp value.
platformyesandroid, ios, web
versionnosemver (1.4.2)When given, the server computes forceUpdate and updateAvailable.

Response — 200 OK, Cache-Control: public, max-age=300, ETag; 304 Not Modified on a matching If-None-Match.

interface AppConfig {
  app: "RESELLER_APP" | "DELEGATE_APP" | "RESELLER_WEB";
  platform: "android" | "ios" | "web";
  minVersion: string;                // AppVersionPolicy.minVersion
  latestVersion: string;
  forceUpdate: boolean;              // version < minVersion
  updateAvailable: boolean;          // minVersion <= version < latestVersion
  storeUrl: string | null;           // null for the web
  maintenance: {
    enabled: boolean;
    message: string | null;          // AppVersionPolicy message in the request locale
    until: Iso | null;
  };
  settings: PublicSettings;          // public subset of the settings catalogue, see the table
  signup: {                          // reseller apps only — sign-up happens before any session
    customerTypes: ("SUPER_GROS" | "DEMI_GROS" | "DETAIL")[];
    businessTypes: { code: string; label: string; sortOrder: number }[];   // BUSINESS_TYPE items
  } | null;
  legal: { termsUrl: string; privacyUrl: string; termsVersion: string } | null;   // reseller apps only
  serverTime: Iso;                   // lets the app detect a wrong device clock
}
{
  "app": "RESELLER_APP",
  "platform": "android",
  "minVersion": "1.3.0",
  "latestVersion": "1.5.0",
  "forceUpdate": false,
  "updateAvailable": true,
  "storeUrl": "https://play.google.com/store/apps/details?id=dz.hoco.reseller",
  "maintenance": { "enabled": false, "message": null, "until": null },
  "settings": {
    "currency": "DZD",
    "pricing": { "displayTaxMode": "TTC" },
    "orders": {
      "minAmount": 1000000,
      "minQtyPerLine": 1,
      "maxQtyPerLine": null,
      "cancelAllowedStatuses": ["SUBMITTED", "PENDING"],
      "assistedConfirmationHours": 72
    },
    "returns": { "windowDays": 7 },
    "afterSales": { "windowDays": 30 },
    "catalog": { "pricesVisibleBeforeValidation": true },
    "payments": { "enabledMethods": ["CASH_ON_DELIVERY", "BANK_TRANSFER", "CCP", "BARIDIMOB"] },
    "delivery": { "feeMode": "FREE", "freeThreshold": null },
    "support": { "defaultWhatsappNumber": "+213770900300" }
  },
  "signup": {
    "customerTypes": ["SUPER_GROS", "DEMI_GROS", "DETAIL"],
    "businessTypes": [
      { "code": "PHONE_SHOP", "label": "Boutique de téléphonie", "sortOrder": 10 },
      { "code": "ACCESSORIES_SHOP", "label": "Accessoires mobiles", "sortOrder": 20 },
      { "code": "MULTISERVICE", "label": "Multiservices / taxiphone", "sortOrder": 30 },
      { "code": "ELECTRONICS", "label": "Électronique / électroménager", "sortOrder": 40 },
      { "code": "WHOLESALER", "label": "Grossiste", "sortOrder": 50 },
      { "code": "OTHER", "label": "Autre", "sortOrder": 90 }
    ]
  },
  "legal": {
    "termsUrl": "https://app.hoco.dz/conditions",
    "privacyUrl": "https://app.hoco.dz/confidentialite",
    "termsVersion": "2026-11"
  },
  "serverTime": "2026-11-05T07:45:02Z"
}

Public settings (settings) — the settings of the settings catalogue marked as needed by the apps, nested by their dotted key (orders.minAmount → settings.orders.minAmount). The catalogue is the reference for types, defaults and allowed values; changes are made on BO-64.

KeyDefaultSent toUse in the app
currencyDZDallFormatting (1 250,00 DA). Constant.
pricing.displayTaxModeTTCRA, RW, DAWhich value of Price is shown large (D-17).
orders.minAmount0 (none) — the example shows a configured 10 000,00 DARA, RW, DACart progress bar « Plus que 1 545,00 DA pour commander »; enforced by cart.checkout (D-19).
orders.minQtyPerLine, orders.maxQtyPerLine1, nullRA, RW, DAQuantity stepper bounds (variants may override).
orders.cancelAllowedStatusesSUBMITTED, PENDINGRA, RWShows or hides « Annuler la commande ».
orders.assistedConfirmationHours72RA, RW, DACountdown on assisted orders (RA-23, DA-17) — D-23.
returns.windowDays7RA, RWDays after delivery during which « Demander un retour » is offered (422 RETURN_WINDOW_EXPIRED after) — D-35.
afterSales.windowDays30RA, RWDays after delivery for an after-sales claim (422 AFTER_SALES_WINDOW_EXPIRED after) — D-35 may replace it by the product warranty.
catalog.pricesVisibleBeforeValidationtrueRA, RWWhether a PENDING_VALIDATION reseller sees the prices of their declared type (D-18); guests never see prices.
payments.enabledMethodsall fiveRA, RW, DAPayment choices at checkout and in payment declarations (D-03).
delivery.feeMode, delivery.freeThresholdFREE, nullRA, RW, DA« Livraison offerte dès … » hint; the cart computes the actual fee (D-20).
support.defaultWhatsappNumberto provide by HOCORA, RWLast fallback of the WhatsApp button when neither Me.supportRegion nor support.whatsapp gives a number.
field.gpsToleranceMeters150DACheck-in radius drawn on the map (DA-08, DA-10) — D-06.
field.gpsMaxAccuracyMeters100DAA fix less precise than this is not used for check-in; the app waits for a better one.
field.allowOutOfToleranceCheckInfalseDAWhether DA-28 offers a justified check-in outside the radius.
field.locationIntervalSeconds, field.locationDistanceMeters300, 200DALocation sampling while a tour is IN_PROGRESS — D-07.
field.locationRetentionDays90DAShown on the consent screen DA-04 (SEC-07, D-11).
field.reportRequiredToEndVisit, field.closingRequiresSynctrue, trueDAVisit end and tour closing guards (DA-12, DA-20).
invitations.validityDays30DA« Lien valable 30 jours » on DA-16.

field.* and invitations.* are only sent to DELEGATE_APP; returns.*, afterSales.*, catalog.*, support.*, signup and legal only to the reseller apps. Back-office-only settings (stock rules, credit policy, numbering, quiet hours…) are never sent. Stock is never exposed as a number, so there is no stock display setting (STK-07). Platform constants are not settings and are not sent: OTP of 6 digits, 60 s resend cooldown, occurredAt accepted up to 72 hours old.

Other blockNotes
signup.businessTypesThe BUSINESS_TYPE reference list in the request language — sign-up happens before any session, so it cannot use reference.lists. customerTypes lists the offered values; labels come from the app's l10n (Super-gros, Demi-gros, Détail).
legalSign-up consent (Law 18-07) and the re-acceptance check against Me.consents.termsVersion. Assumption — stored as settings legal.termsUrl, legal.privacyUrl, legal.termsVersion, to add to the catalogue.
maintenance.untilAppVersionPolicy.maintenanceUntil (SRV-42): the expected end set on BO-66, null when none or when maintenance is off. Informative — the app keeps polling appConfig.get.

Errors

StatusCodeWhen
400VALIDATION_FAILEDUnknown app or platform, version not semver.

Rules & side effects

  1. Values come from AppVersionPolicy (per app and platform, edited on BO-66 through admin.appVersions.crud) and Setting (edited on BO-64). Changes are visible within 5 minutes (cache).
  2. This operation never answers 426 or 503: it is how an outdated or blocked app learns what to show. The other operations enforce the policy (AUTH-09): X-App-Version below minVersion — or missing on a mobile session — → 426 UPGRADE_REQUIRED (details.minVersion, details.storeUrl), except auth.logout and, during the 72 hours after the minimum was raised, sync.batch (field work recorded offline is never stranded); maintenance → 503 MAINTENANCE (details.until, details.message). Versions compare semantically (1.10.0 is above 1.9.3). Maintenance is per app — the back-office is never put in maintenance by this flag.
  3. Clients call it on cold start, when resuming after more than an hour, and whenever any call answers 426 or 503 MAINTENANCE. The « Une mise à jour est disponible » prompt is shown at most once per day for a given version.
  4. serverTime: if the device clock differs by more than 5 minutes, the delegate app warns the user (offline actions are timestamped with the device clock).

Used by — splash RA-01, DA-01 and the web layout of RW-01; system states RA-36 and DA-28; sign-up form RA-05; consent DA-04.

GET /reference/wilayas

reference.wilayas · Access public (guests included) · Apps RA, RW, DA, BO · Idempotency-Key — · Release V1 · Requirements GEO-01

Purpose. Returns the official list of wilayas with French and Arabic names, for address forms, filters and zones.

Request

HeaderNotes
If-None-MatchThe ETag of the cached copy.

Response — 200 OK with ETag: "geo-2026.1" and Cache-Control: public, max-age=86400; 304 Not Modified (empty body) when the copy is current. Not paginated, ordered by code.

{
  "version": "geo-2026.1",
  "items": [
    { "code": "01", "nameFr": "Adrar", "nameAr": "أدرار", "communeCount": 16 },
    { "code": "16", "nameFr": "Alger", "nameAr": "الجزائر", "communeCount": 57 },
    { "code": "31", "nameFr": "Oran", "nameAr": "وهران", "communeCount": 26 },
    { "code": "46", "nameFr": "Aïn Témouchent", "nameAr": "عين تموشنت", "communeCount": 28 }
  ]
}

(Excerpt: the response lists every active wilaya of the seeded official reference — 69 since the 2026 territorial reorganisation, see the geography model.)

Errors — none specific.

Rules & side effects

  1. The data is the seeded official reference (Wilaya, active rows only), changed only by a migration when the administrative division changes; version (= ETag) changes with it.
  2. Clients store the list (shared preferences / drift) and revalidate at start-up; the display name follows the app language (nameAr in Arabic, nameFr otherwise).

Used by — wilaya pickers of RA-05, RA-19, DA-14, RW-01, the guest region picker of the WhatsApp button, and back-office filters and the zone editor BO-19.

GET /reference/wilayas/{wilayaCode}/communes

reference.communes · Access public (guests included) · Apps RA, RW, DA, BO · Idempotency-Key — · Release V1 · Requirements GEO-01

Purpose. Returns the communes of one wilaya, for the commune picker that follows the wilaya picker.

Request

Path parameterTypeNotes
wilayaCodestringTwo digits, "31".

If-None-Match as for wilayas.

Response — 200 OK, ETag, Cache-Control: public, max-age=86400; 304 when current. Ordered by French name.

{
  "wilayaCode": "31",
  "version": "geo-2026.1",
  "items": [
    { "id": "01a0c3e1-5d20-7a10-8b31-310900000009", "code": "3109", "nameFr": "Aïn El Turk", "nameAr": "عين الترك" },
    { "id": "01a0c3e1-5d20-7a10-8b31-310600000006", "code": "3106", "nameFr": "Arzew", "nameAr": "أرزيو" },
    { "id": "01a0c3e1-5d20-7a10-8b31-310300000003", "code": "3103", "nameFr": "Bir El Djir", "nameAr": "بئر الجير" },
    { "id": "01a0c3e1-5d20-7a10-8b31-310500000005", "code": "3105", "nameFr": "Es Senia", "nameAr": "السانية" },
    { "id": "01a0c3e1-5d20-7a10-8b31-310100000001", "code": "3101", "nameFr": "Oran", "nameAr": "وهران" }
  ]
}

(Excerpt.)

FieldNotes
idThe communeId used by addresses, sign-up and zones (Commune.id).
codeOfficial commune code (wilaya code + 2-digit rank), informative — never use it as a key.

Errors

StatusCodeWhen
400VALIDATION_FAILEDwilayaCode is not two digits.
404NOT_FOUNDNo such wilaya.

Rules & side effects — the delegate app downloads the communes of every wilaya of its zones at sign-in (from Me.delegate.zones[].wilayaCodes) so that prospects can be created offline (FLD-11).

Used by — commune pickers of RA-05, RA-19, DA-14, DA-15, RW-01, RW-12 and the back-office forms.

GET /reference/lists

reference.lists · Access session (any user type; lists filtered by user type) · Apps RA, RW, DA, BO · Idempotency-Key — · Release V1 · Requirements ADM-05

Purpose. Returns the option lists behind the apps' dropdowns and chips — business types, not-done reasons, issue tags, visit types, ticket types, payment methods… — in the caller's language, in the order configured by the back-office.

Request

Query parameterRequiredNotes
listKeynoRepeatable (?listKey=VISIT_NOT_DONE_REASON&listKey=VISIT_ISSUE_TAG). Omitted → every list available to the caller.

Accept-Language selects the labels; If-None-Match revalidates.

Response — 200 OK, ETag, Vary: Accept-Language, Cache-Control: private, max-age=3600; 304 when current.

interface ReferenceListsResponse {
  version: string;
  lists: {
    listKey: string;
    kind: "DATA" | "ENUM";           // DATA: editable items (labels are data); ENUM: an enum's offered values
    items: {
      code: string;
      label: string;                 // localised
      sortOrder: number;
      meta?: Record<string, unknown>;   // list-specific attributes, see the table
    }[];
  }[];
}
{
  "version": "ref-2026-11-02T16:40:00Z",
  "lists": [
    {
      "listKey": "VISIT_NOT_DONE_REASON",
      "kind": "DATA",
      "items": [
        { "code": "SHOP_CLOSED", "label": "Magasin fermé", "sortOrder": 10 },
        { "code": "OWNER_ABSENT", "label": "Responsable absent", "sortOrder": 20 },
        { "code": "VISIT_REFUSED", "label": "Visite refusée", "sortOrder": 30 },
        { "code": "ADDRESS_NOT_FOUND", "label": "Adresse introuvable", "sortOrder": 40 },
        { "code": "RESCHEDULED", "label": "Reportée à la demande du client", "sortOrder": 50 },
        { "code": "OTHER", "label": "Autre (préciser)", "sortOrder": 90, "meta": { "requiresComment": true } }
      ]
    },
    {
      "listKey": "VISIT_TYPE",
      "kind": "DATA",
      "items": [
        { "code": "PROSPECTION", "label": "Prospection", "sortOrder": 10, "meta": { "photoRequired": true, "reportRequired": true } },
        { "code": "FOLLOW_UP", "label": "Suivi commercial", "sortOrder": 20, "meta": { "photoRequired": false, "reportRequired": true } },
        { "code": "MERCHANDISING", "label": "Merchandising", "sortOrder": 30, "meta": { "photoRequired": true, "reportRequired": false } }
      ]
    },
    {
      "listKey": "POTENTIAL",
      "kind": "ENUM",
      "items": [
        { "code": "LOW", "label": "Faible", "sortOrder": 10 },
        { "code": "MEDIUM", "label": "Moyen", "sortOrder": 20 },
        { "code": "HIGH", "label": "Élevé", "sortOrder": 30 }
      ]
    }
  ]
}

Available lists

listKeyKindSourceAvailable toNotes
BUSINESS_TYPEDATAReferenceItemallSeed: PHONE_SHOP, ACCESSORIES_SHOP, MULTISERVICE, ELECTRONICS, WHOLESALER, OTHER.
PERSON_ROLEDATAReferenceItemDA, BOPerson met in a visit report: OWNER, MANAGER, EMPLOYEE, OTHER.
VISIT_NOT_DONE_REASONDATAReferenceItemDA, BOmeta.requiresComment (ReferenceItem.requiresComment, e.g. OTHER).
VISIT_ISSUE_TAGDATAReferenceItemDA, BOPRICE_TOO_HIGH, STOCK_SHORTAGE, DELIVERY_DELAY, PRODUCT_DEFECT, COMPETITION, PAYMENT_TERMS, NEEDS_DISPLAY, OTHER.
TOUR_SUSPEND_REASONDATAReferenceItemDA, BOBREAK, VEHICLE_ISSUE, WEATHER, MEETING, EMERGENCY, OTHER.
ORDER_CANCEL_REASONDATAReferenceItemRA, RW, BOORDERED_BY_MISTAKE, CHANGE_QUANTITIES, DELAY_TOO_LONG, FOUND_ELSEWHERE, OTHER.
ORDER_REFUSAL_REASONDATAReferenceItemBOUsed by the order confirmation queue.
PAYMENT_REJECT_REASONDATAReferenceItemBOUsed when verifying declared payments.
ASSISTED_REJECT_REASONDATAReferenceItemRA, RW, BOWRONG_ITEMS, TOO_EXPENSIVE, NOT_REQUESTED, LATER, OTHER — orders.rejectAssisted. Contract 1.1.0
RETURN_REASONDATAReferenceItemRA, RW, BODAMAGED_ON_DELIVERY, DEFECTIVE, WRONG_ITEM, NOT_AS_DESCRIBED, OVERSTOCK, OTHER — returns.create. Contract 1.1.0
VISIT_TYPEDATAVisitTypeDA, BOmeta.photoRequired, meta.reportRequired (FLD-08, FLD-10).
POTENTIALENUMPotentialDA, BO
INTEREST_LEVELENUMInterestLevelDA, BO
NEXT_ACTIONENUMNextActionDA, BO
TASK_TYPEENUMTaskTypeDA, BO
PHOTO_KINDENUMPhotoKindRA, RW, DA, BO
DOCUMENT_TYPEENUMDocumentTypeRA, RW, DA, BO
TICKET_TYPEENUMTicketTypeRA, RW, BOIncludes AFTER_SALES (SUP-04).
AFTER_SALES_ISSUEENUMAfterSalesIssueRA, RW, BOIssue of an after-sales claim.
CUSTOMER_TYPEENUMCustomerTypeDA, BODelegates may record a declared type on a prospect.
PAYMENT_METHODENUMPaymentMethodRA, RW, DA, BOOnly the methods enabled in the business settings.

Errors

StatusCodeWhen
400VALIDATION_FAILEDUnknown listKey (field code INVALID_ENUM).
403PERMISSION_DENIEDA requested list is not available to the caller's user type (details.listKey).

Rules & side effects

  1. DATA lists are edited on BO-65 (admin.referenceLists.crud) and visit types on BO-26; labels are stored per language and fall back to French. The seed codes above are proposals to validate with HOCO.
  2. ENUM lists exist so that dropdowns follow the configuration (enabled payment methods, order); their labels equal the apps' l10n labels from enums.json. Resource fields still carry enum values only — the "no labels on enum fields" rule of the conventions is unchanged.
  3. Only active items are returned. Records keep the code of an item deactivated later; clients show the code's last known label (from their cache) or the raw code.
  4. Any change to a list changes version. The delegate app stores the lists in its local database for offline use and revalidates at sign-in and once a day.

Used by — DA-11 (not-done reasons), DA-12 (person met, interest, issues, next action), DA-14 (business type, potential, customer type), DA-06 (suspend reasons); RA-22 (cancel reasons), RA-28 (document types), RA-31 (payment methods), RA-33 (ticket types and after-sales issues); the equivalent RW pages and back-office forms.

POST /me/deletion-request

me.deleteAccount · Access session (reseller) · Apps RA, RW · Idempotency-Key required · Release V1 · Requirements SEC-08, AUTH-06

Purpose — Google Play requires an in-app way to request account deletion. The reseller confirms with their password; the account is closed and personal data is anonymised once the legal retention period of business records (orders, invoices) has passed.

Request

interface DeletionRequestBody {
  password: string;
  reason?: string; // free text, ≤ 500 chars
}
{ "password": "••••••••", "reason": "Je ferme mon magasin." }

Response 202 Accepted

{ "status": "SCHEDULED", "accountStatus": "DISABLED", "anonymiseAfter": "2036-12-31" }

Errors

StatusCodeWhen
401INVALID_CURRENT_PASSWORDWrong password
409OPEN_ORDERS_EXISTOrders not yet DELIVERED, CANCELLED or REFUSED, or an open return/claim

Rules & side effects

  1. Every session is revoked, devices unregistered, the account set to DISABLED (history kept — SEC-06).
  2. Contact data is anonymised by the retention job when the retention period of the linked financial records ends (cahier §10, Law 18-07 — durations to validate with HOCO's counsel).
  3. Audit entry DELETE on User; the back-office is notified (account.deletion_requested).

Used by — RA-35, RW-12.

On this page