Location
The location module stores addresses (individual or organization) in the addresses table. Most address columns are stored encrypted (@EncryptedColumn) and come out as plaintext in the response. The controller is registered at /addresses; all endpoints require Bearer JWT plus an ACL permission.
| Property | Value |
|---|---|
| Base URL | {HOST}/v1 |
| Auth | Bearer JWT (header Authorization) or access_token cookie |
| Content-Type | application/json |
| Error envelope | { "message": string | string[], "statusCode": number, "error": string } |
| Validation | Global ValidationPipe · whitelist: true, forbidNonWhitelisted: true |
| Related modules | users, organizations, onboarding |
| Document version | v1 · 2026-05-20 |
| Audience | Internal FE devs (mobile + web) |
Summary
Section titled “Summary”Four endpoints: register a new address (for the logged-in user), get address detail by ID, list all addresses (Moria-only), and update an address. An ACL permission is used for each operation: create-address, read-address, update-address. Only the list endpoint is additionally restricted via @Roles(UserType.MORIA).
| Method | Path | Auth | Summary |
|---|---|---|---|
| POST | /v1/addresses | bearer | Register a new address for the logged-in user |
| GET | /v1/addresses/:address_id | bearer | Detail of one address (UUID) |
| GET | /v1/addresses | bearer | List all addresses — Moria admins only |
| PATCH | /v1/addresses/:address_id | bearer | Update an address (all fields optional) |
POST /v1/addresses bearer
Section titled “POST /v1/addresses ”Register a new address. The server reads user from the token (@AuthUser()) to determine the address owner.
Request body — CreateAddressDto
Section titled “Request body — CreateAddressDto”| Field | Type | Required | Notes |
|---|---|---|---|
province | string | ✓ | Example DKI JAKARTA |
city | string | ✓ | |
country | string | ✓ | |
district | string | optional | Kecamatan |
subdistrict | string | optional | Kelurahan |
street | string | optional | |
village | string | optional | |
rt | string | optional | RT, example 01 |
rw | string | optional | RW, example 02 |
postal_code | string | optional | |
unit_number | string | optional | Unit number |
building_number | string | optional | Building number |
label | string | optional | Custom label (e.g. Home, Office) |
address_type | enum AddressType | optional | individual | organization; default individual |
Example request
Section titled “Example request”{ "province": "DKI JAKARTA", "city": "Jakarta Utara", "country": "Indonesia", "district": "Pademangan", "subdistrict": "Pademangan Barat", "street": "Jl. Sudirman", "postal_code": "14410", "rt": "01", "rw": "02", "label": "Home", "address_type": "individual"}Response — 201 Created
Section titled “Response — 201 Created”{ "status": "success", "statusCode": 201, "message": "address registered successfully", "data": { "address": { "id": "550e8400-e29b-41d4-a716-446655440000", "user_id": "660e8400-e29b-41d4-a716-446655440111", "organization_id": null, "province": "DKI JAKARTA", "city": "Jakarta Utara", "country": "Indonesia", "district": "Pademangan", "subdistrict": "Pademangan Barat", "street": "Jl. Sudirman", "village": null, "rt": "01", "rw": "02", "postal_code": "14410", "unit_number": null, "building_number": null, "label": "Home", "address_type": "individual", "created_by": "660e8400-e29b-41d4-a716-446655440111", "updated_by": "660e8400-e29b-41d4-a716-446655440111", "deleted_by": null, "created_at": "2026-05-20T08:30:00.000Z", "updated_at": "2026-05-20T08:30:00.000Z" } }}Errors
Section titled “Errors”| Status | When it occurs |
|---|---|
400 Bad Request | Validation failure (required field missing, unknown enum, non-whitelisted field) |
401 Unauthorized | Bearer/cookie is invalid |
403 Forbidden | Missing the create-address permission |
GET /v1/addresses/:address_id bearer
Section titled “GET /v1/addresses/:address_id ”Retrieve the detail of one address by ID. address_id is validated via ParseUUIDPipe.
Path params
Section titled “Path params”| Param | Type | Notes |
|---|---|---|
address_id | UUID | Must be UUID v4 |
Response — 200 OK
Section titled “Response — 200 OK”{ "status": "success", "statusCode": 200, "message": "address fetched successfully", "data": { "address": { "...": "shape matches AddressDto from POST" } }}Errors
Section titled “Errors”| Status | When it occurs |
|---|---|
400 Bad Request | address_id is not a UUID |
401 Unauthorized | Bearer/cookie is invalid |
403 Forbidden | Missing the read-address permission |
404 Not Found | Address not found |
GET /v1/addresses bearer
Section titled “GET /v1/addresses ”List all addresses with pagination. Admin endpoint — restricted to the MORIA role.
Query params — QueryParamsDto
Section titled “Query params — QueryParamsDto”| Param | Type | Default | Notes |
|---|---|---|---|
page | number | 1 | Numeric string (auto-cast); 0 is rejected |
limit | number | 10 | Numeric string; 0 is rejected |
order | 'asc' | 'desc' | desc | Order |
| others | — | — | Other fields in QueryParamsDto (e.g. user_id, organization_id) are not processed by this endpoint — ignored without error |
Response — 200 OK
Section titled “Response — 200 OK”{ "status": "success", "statusCode": 200, "message": "addresses are fetched successfully", "data": { "limit": 10, "count": 124, "currentPage": 1, "totalPages": 13, "addresses": [ { "...": "AddressDto" } ] }}Errors
Section titled “Errors”| Status | When it occurs |
|---|---|
401 Unauthorized | Bearer/cookie is invalid |
403 Forbidden | Role is not MORIA, or missing the read-address permission |
PATCH /v1/addresses/:address_id bearer
Section titled “PATCH /v1/addresses/:address_id ”Update an address. The DTO is PartialType(CreateAddressDto) — all fields optional. The server performs the update and returns the latest record.
Path params
Section titled “Path params”| Param | Type | Notes |
|---|---|---|
address_id | UUID | Must be UUID v4 |
Request body — UpdateAddressDto
Section titled “Request body — UpdateAddressDto”Same fields as CreateAddressDto, but all optional (send only what changed).
Example request
Section titled “Example request”{ "label": "Office", "address_type": "organization"}Response — 200 OK
Section titled “Response — 200 OK”{ "status": "success", "statusCode": 200, "message": "address updated successfully", "data": { "address": { "...": "full AddressDto after update" } }}Errors
Section titled “Errors”| Status | When it occurs |
|---|---|
400 Bad Request | address_id is not a UUID, or body contains non-whitelisted field |
401 Unauthorized | Bearer/cookie is invalid |
403 Forbidden | Missing the update-address permission |
404 Not Found | Address not found |
Reference
Section titled “Reference”Enum: AddressType
Section titled “Enum: AddressType”individual— personal user addressorganization— organization entity address
Permissions used
Section titled “Permissions used”create-addressread-addressupdate-address
Standard error envelope
Section titled “Standard error envelope”{ "message": "address_id must be a UUID", "statusCode": 400, "error": "Bad Request"}Common HTTP codes
Section titled “Common HTTP codes”400body/query/param validation401missing / expired token403role/permission mismatch404address not found