# Partner API

## Basic information:

* Sandbox:&#x20;

```
https://gateway-dev.palm.id.vn/api/private/partner/
```

### Authenticating Requests with an API Key

To authenticate requests with an API key, follow these steps:

1. Retrieve your API key from the developer portal or your account settings.
2. Include the API key in the headers of your HTTP request. Typically, this is achieved by adding a header field`x-api-key`.
3. Ensure the API key is kept secure to prevent unauthorized access.

Example in a cURL command:

```bash
curl -X GET "https://gateway-dev.palm.id.vn/private/api/partner/locker" -H "x-api-key: YOUR_API_KEY"
```

Replace `YOUR_API_KEY` with your actual API key.

### Webhook with Secret Key and HMAC-SH256 Signature

To ensure secure communication when receiving webhooks, you can use HMAC-SHA256 signatures. This approach allows you to verify the integrity and authenticity of the payload using a secret key shared between you and the sender.

#### Generating a Signature

When a webhook is sent, the payload is signed using your secret key. This signature is typically included in the request headers.

#### Verifying the Signature in Node.js

To verify the HMAC-SHA512 signature in Node.js:

1. Collect the incoming payload and the signature from the request header.
2. Use the secret key to generate a hash of the payload.
3. Compare the generated hash with the signature from the header.

Here's an example:

```javascript
const crypto = require('crypto');

const secretKey = 'YOUR_SECRET_KEY';
const receivedSignature = req.headers['x-signature'];
const payload = JSON.stringify(req.body);

const hash = crypto
  .createHmac('sha256', secretKey)
  .update(payload)
  .digest('hex');

if (hash === receivedSignature) {
  console.log('Signature is valid.');
} else {
  console.log('Invalid signature.');
}
```

Replace `YOUR_SECRET_KEY` with your actual secret key. Make sure to handle the payload and signature verification securely to prevent unauthorized access.

## List devices

#### API Description: List Devices

This API endpoint allows you to retrieve a list of devices. It is designed following RESTful principles.

**Endpoint**

`GET /locker`

**Parameters**

* `size` (optional): The number of records to return per page for pagination. Default is 10.
* `page` (optional): The index of the page to retrieve for pagination, starting at 0.
* `longtitude` (optional) longtitude to search
* `latitude`  (optional) latitude to search
* `distance` (optional) the radius (in km) to search with center point is (latitude, longtitude). Default value is 5
* `city` (optional) city
* `dist` (optional) district
* `ward` (optional) ward
* `format` (optional) format of data. You can use `compact` or `full` format. Default value is `compact` .

Note:

* You must search by `[longtitude, latitude, distance]` or `[city, dist, ward]`&#x20;
* System will use `[longtitude, latitude, distance]` if you send both param groups.
* If search by `[longtitude, latitude, distance]` does not return the result, you can try again by increase `distance` value.

**Response**

Returns a JSON object containing device details and pagination information.

#### Example Response of compact format

```
{
    "data": {
        "items": [
            {
                "id": "131f3e80-29f7-49e9-bd1d-3c8ae5a766b6",
                "name": "Tủ đồ iHub 2",
                "address": "Park 5, 458 Minh Khai",
                "city": "Hà Nội",
                "dist": "Hai Bà Trưng",
                "ward": "Vĩnh Tuy",
                "longtitude": 105.794,
                "latitude": 21.0027,
                "createdAt": "2025-06-28T03:41:57.000Z",
                "stacks": [
                    {
                        "boxSize": "s",
                        "availableBox": 0,
                        "info": "24x12x48 cm"
                    },
                    {
                        "boxSize": "m",
                        "availableBox": 0,
                        "info": "55x12x48 cm"
                    },
                    {
                        "boxSize": "l",
                        "availableBox": 0,
                        "info": "55x24x48 cm"
                    },
                    {
                        "boxSize": "xl",
                        "availableBox": 0,
                        "info": "55x50x48 cm"
                    }
                ]
            },
            {
                "id": "8677c797-c7d0-4b92-b5bb-ead8d6a5980f",
                "name": "Tủ đồ 01",
                "address": "Chân toà nhà SHOW TIME",
                "city": null,
                "dist": null,
                "ward": null,
                "longtitude": null,
                "latitude": null,
                "createdAt": "2025-05-14T02:09:05.000Z",
                "stacks": [
                    {
                        "boxSize": "s",
                        "availableBox": 0,
                        "info": "24x12x48 cm"
                    },
                    {
                        "boxSize": "m",
                        "availableBox": 0,
                        "info": "55x12x48 cm"
                    },
                    {
                        "boxSize": "l",
                        "availableBox": 0,
                        "info": "55x24x48 cm"
                    },
                    {
                        "boxSize": "xl",
                        "availableBox": 0,
                        "info": "55x50x48 cm"
                    }
                ]
            },
            {
                "id": "585f7d7c-af7a-4892-b1a9-95dba4545040",
                "name": "chi chi",
                "address": "123123",
                "city": null,
                "dist": null,
                "ward": null,
                "longtitude": null,
                "latitude": null,
                "createdAt": "2025-03-26T14:33:57.000Z",
                "stacks": [
                    {
                        "boxSize": "s",
                        "availableBox": 4,
                        "info": "24x12x48 cm"
                    },
                    {
                        "boxSize": "m",
                        "availableBox": 0,
                        "info": "55x12x48 cm"
                    },
                    {
                        "boxSize": "l",
                        "availableBox": 0,
                        "info": "55x24x48 cm"
                    },
                    {
                        "boxSize": "xl",
                        "availableBox": 0,
                        "info": "55x50x48 cm"
                    }
                ]
            },
            {
                "id": "eb60ef05-5e7f-49c1-a564-11d4fe184cef",
                "name": "chindl tủ A",
                "address": "test",
                "city": null,
                "dist": null,
                "ward": null,
                "longtitude": null,
                "latitude": null,
                "createdAt": "2025-03-26T14:29:17.000Z",
                "stacks": [
                    {
                        "boxSize": "s",
                        "availableBox": 0,
                        "info": "24x12x48 cm"
                    },
                    {
                        "boxSize": "m",
                        "availableBox": 0,
                        "info": "55x12x48 cm"
                    },
                    {
                        "boxSize": "l",
                        "availableBox": 0,
                        "info": "55x24x48 cm"
                    },
                    {
                        "boxSize": "xl",
                        "availableBox": 0,
                        "info": "55x50x48 cm"
                    }
                ]
            },
            {
                "id": "59e83826-796b-420c-ac68-9c2ffc3e8000",
                "name": "thêm tủ mới",
                "address": "201 trường chinh",
                "city": null,
                "dist": null,
                "ward": null,
                "longtitude": null,
                "latitude": null,
                "createdAt": "2025-03-26T13:43:22.000Z",
                "stacks": [
                    {
                        "boxSize": "s",
                        "availableBox": 4,
                        "info": "24x12x48 cm"
                    },
                    {
                        "boxSize": "m",
                        "availableBox": 2,
                        "info": "55x12x48 cm"
                    },
                    {
                        "boxSize": "l",
                        "availableBox": 0,
                        "info": "55x24x48 cm"
                    },
                    {
                        "boxSize": "xl",
                        "availableBox": 0,
                        "info": "55x50x48 cm"
                    }
                ]
            },
            {
                "id": "cfa88e99-4aa7-4ad0-8512-5bf4850621f4",
                "name": "New Locker - ttyS4",
                "address": "Showtimes-F3",
                "city": null,
                "dist": null,
                "ward": null,
                "longtitude": null,
                "latitude": null,
                "createdAt": "2025-03-21T07:05:16.000Z",
                "stacks": [
                    {
                        "boxSize": "s",
                        "availableBox": 0,
                        "info": "24x12x48 cm"
                    },
                    {
                        "boxSize": "m",
                        "availableBox": 1,
                        "info": "55x12x48 cm"
                    },
                    {
                        "boxSize": "l",
                        "availableBox": 0,
                        "info": "55x24x48 cm"
                    },
                    {
                        "boxSize": "xl",
                        "availableBox": 0,
                        "info": "55x50x48 cm"
                    }
                ]
            },
            {
                "id": "4b20b55e-b0e2-48d1-b269-82cdc2039288",
                "name": "Test 125HN",
                "address": "125HN",
                "city": null,
                "dist": null,
                "ward": null,
                "longtitude": null,
                "latitude": null,
                "createdAt": "2025-03-18T04:32:27.000Z",
                "stacks": [
                    {
                        "boxSize": "s",
                        "availableBox": 36,
                        "info": "24x12x48 cm"
                    },
                    {
                        "boxSize": "m",
                        "availableBox": 25,
                        "info": "55x12x48 cm"
                    },
                    {
                        "boxSize": "l",
                        "availableBox": 6,
                        "info": "55x24x48 cm"
                    },
                    {
                        "boxSize": "xl",
                        "availableBox": 2,
                        "info": "55x50x48 cm"
                    }
                ]
            },
            {
                "id": "84ae520e-0b72-4f8d-b68f-dd0f104e9af1",
                "name": "tesst",
                "address": "1",
                "city": "Hà Nội",
                "dist": "Quận Hai Bà Trưng",
                "ward": "Bạch Đằng",
                "longtitude": 105.821,
                "latitude": 21.0272,
                "createdAt": "2025-03-16T14:17:29.000Z",
                "stacks": [
                    {
                        "boxSize": "s",
                        "availableBox": 27,
                        "info": "24x12x48 cm"
                    },
                    {
                        "boxSize": "m",
                        "availableBox": 0,
                        "info": "55x12x48 cm"
                    },
                    {
                        "boxSize": "l",
                        "availableBox": 0,
                        "info": "55x24x48 cm"
                    },
                    {
                        "boxSize": "xl",
                        "availableBox": 0,
                        "info": "55x50x48 cm"
                    }
                ]
            },
            {
                "id": "bf4b1f7d-0cbc-4e41-b7d2-9001ace6cd44",
                "name": "test",
                "address": "qweqưe",
                "city": null,
                "dist": null,
                "ward": null,
                "longtitude": null,
                "latitude": null,
                "createdAt": "2025-03-13T15:09:55.000Z",
                "stacks": [
                    {
                        "boxSize": "s",
                        "availableBox": 0,
                        "info": "24x12x48 cm"
                    },
                    {
                        "boxSize": "m",
                        "availableBox": 0,
                        "info": "55x12x48 cm"
                    },
                    {
                        "boxSize": "l",
                        "availableBox": 0,
                        "info": "55x24x48 cm"
                    },
                    {
                        "boxSize": "xl",
                        "availableBox": 0,
                        "info": "55x50x48 cm"
                    }
                ]
            },
            {
                "id": "72238f70-1f36-4ab6-8f30-d19d2d246ba8",
                "name": "Tủ đồ sảnh",
                "address": "Sảnh",
                "city": null,
                "dist": null,
                "ward": null,
                "longtitude": null,
                "latitude": null,
                "createdAt": "2025-03-12T02:00:14.000Z",
                "stacks": [
                    {
                        "boxSize": "s",
                        "availableBox": 4,
                        "info": "24x12x48 cm"
                    },
                    {
                        "boxSize": "m",
                        "availableBox": 0,
                        "info": "55x12x48 cm"
                    },
                    {
                        "boxSize": "l",
                        "availableBox": 0,
                        "info": "55x24x48 cm"
                    },
                    {
                        "boxSize": "xl",
                        "availableBox": 0,
                        "info": "55x50x48 cm"
                    }
                ]
            }
        ],
        "page": 0,
        "size": 10,
        "total": 24
    }
}
```

#### Example Response of full format

```
{
    "data": {
        "items": [
            {
                "id": "083c5896-a074-4ede-92de-fe9b74aca3d7",
                "name": "Tủ 001",
                "address": "289 Khuất Duy Tiến",
                "city": "Hà Nội",
                "dist": "Cầu Giấy",
                "ward": "Trung Hòa",
                "longtitude": 105.794,
                "latitude": 21.0026,
                "distance_km": 9.721785537106374,
                "stacks": [
                    {
                        "id": "207cbd4e-2969-46fb-8d75-584aef0a2a16",
                        "size": "m",
                        "position": 4,
                        "isUsed": false,
                        "status": true
                    },
                    {
                        "id": "0892384f-9e76-4da9-ba1e-fdbef40f86c6",
                        "size": "m",
                        "position": 5,
                        "isUsed": false,
                        "status": true
                    },
                    {
                        "id": "ceceff85-697f-4132-a8e2-659e30ef440d",
                        "size": "s",
                        "position": 6,
                        "isUsed": false,
                        "status": true
                    },
                    {
                        "id": "5fe52a78-af1c-4e48-a2bf-edd954426815",
                        "size": "l",
                        "position": 7,
                        "isUsed": false,
                        "status": true
                    },
                    {
                        "id": "c443985c-c38a-48bb-a593-64c31cc91b09",
                        "size": "l",
                        "position": 8,
                        "isUsed": false,
                        "status": true
                    },
                    {
                        "id": "0807dd5c-42c2-443e-b280-45ee4bc9a0d5",
                        "size": "l",
                        "position": 9,
                        "isUsed": false,
                        "status": true
                    },
                    {
                        "id": "aecc7cc9-5873-440f-b89d-c02c0a332d94",
                        "size": "l",
                        "position": 10,
                        "isUsed": false,
                        "status": true
                    },
                    {
                        "id": "48006f1e-ffdc-442f-b6fc-0e99441010ad",
                        "size": "m",
                        "position": 11,
                        "isUsed": false,
                        "status": true
                    },
                    {
                        "id": "bd4a1a82-77f9-4cf6-9d7b-cc57e872e204",
                        "size": "m",
                        "position": 12,
                        "isUsed": false,
                        "status": true
                    },
                    {
                        "id": "e62b5bdf-fa3c-4a55-bbd8-5764df8f841b",
                        "size": "m",
                        "position": 13,
                        "isUsed": false,
                        "status": true
                    },
                    {
                        "id": "abb39f55-5f93-4b1e-b844-16019b36ceb0",
                        "size": "m",
                        "position": 14,
                        "isUsed": false,
                        "status": true
                    },
                    {
                        "id": "f815b823-515c-4321-9b7c-9a6d49c3da13",
                        "size": "m",
                        "position": 15,
                        "isUsed": false,
                        "status": true
                    },
                    {
                        "id": "400d9585-feb4-45f9-8766-5e38afc3ffd8",
                        "size": "m",
                        "position": 16,
                        "isUsed": false,
                        "status": true
                    },
                    {
                        "id": "324e186a-d413-4f92-b45a-d699379bb33e",
                        "size": "m",
                        "position": 17,
                        "isUsed": false,
                        "status": true
                    },
                    {
                        "id": "580a2043-ce84-45b8-b1b6-7337ddecdcd8",
                        "size": "m",
                        "position": 18,
                        "isUsed": false,
                        "status": true
                    },
                    {
                        "id": "ddcf082b-4e7e-4668-91d5-ae82d6985f1f",
                        "size": "m",
                        "position": 19,
                        "isUsed": false,
                        "status": true
                    },
                    {
                        "id": "8668b95f-786f-4206-88f6-db28f927667d",
                        "size": "m",
                        "position": 21,
                        "isUsed": false,
                        "status": true
                    },
                    {
                        "id": "690d44ac-e16f-4412-9728-f62c608cb70c",
                        "size": "m",
                        "position": 22,
                        "isUsed": false,
                        "status": true
                    },
                    {
                        "id": "f29a62fa-2828-4bd5-aaa8-f25f26a03776",
                        "size": "m",
                        "position": 25,
                        "isUsed": false,
                        "status": true
                    },
                    {
                        "id": "48af7432-8c87-4268-a7ca-eeb288310186",
                        "size": "s",
                        "position": 31,
                        "isUsed": false,
                        "status": true
                    }
                ],
                "stackCount": 20,
                "sizeStack": {
                    "s": "24x12x48 cm",
                    "m": "55x12x48 cm",
                    "l": "55x24x48 cm",
                    "xl": "55x50x48 cm"
                }
            },
            {
                "id": "131f3e80-29f7-49e9-bd1d-3c8ae5a766b6",
                "name": "Tủ đồ iHub 2",
                "address": "Park 5, 458 Minh Khai",
                "city": "Hà Nội",
                "dist": "Hai Bà Trưng",
                "ward": "Vĩnh Tuy",
                "longtitude": 105.794,
                "latitude": 21.0027,
                "distance_km": 9.734654071951898,
                "stacks": [],
                "stackCount": 0,
                "sizeStack": {
                    "s": "24x12x48 cm",
                    "m": "55x12x48 cm",
                    "l": "55x24x48 cm",
                    "xl": "55x50x48 cm"
                }
            }
        ],
        "page": 0,
        "size": 10
    }
}
```

## Get device's detail

#### Get Device Details by ID

This API endpoint retrieves detailed information about a specific device using its unique device ID.

**Endpoint**

```
GET /locker/{lockerId}
```

**Parameters**

* `lockerIdId` (string, required): The unique identifier of the device whose details are to be retrieved.

**Response**

Returns a JSON object containing details of the specified device including its name, address, and geographical location.

**Example Request**

```
GET /locker/131f3e80-29f7-49e9-bd1d-3c8ae5a766b6
```

**Example Response**

```json
{
    "data": {
        "id": "083c5896-a074-4ede-92de-fe9b74aca3d7",
        "shortId": "083c5896a0744ede92defe9b74aca3d7",
        "name": "Tủ 001",
        "address": "289 Khuất Duy Tiến",
        "city": "Hà Nội",
        "dist": "Cầu Giấy",
        "ward": "Trung Hòa",
        "longtitude": "106.00000000",
        "latitude": "21.00000000",
        "createdAt": "2025-02-13T10:16:38.000Z",
        "stacks": [
            {
                "id": "207cbd4e-2969-46fb-8d75-584aef0a2a16",
                "shortId": "207cbd4e296946fb8d75584aef0a2a16",
                "size": "m",
                "position": 4,
                "isUsed": false,
                "status": true
            },
            {
                "id": "0892384f-9e76-4da9-ba1e-fdbef40f86c6",
                "shortId": "0892384f9e764da9ba1efdbef40f86c6",
                "size": "m",
                "position": 5,
                "isUsed": false,
                "status": true
            }
        ]
    }
}
```

Use this API to access the device information conveniently by its ID.

## Create new order

This API allows you to create a new order by providing relevant details about the sender, receiver, and package.

#### Endpoint

```
POST /order
```

#### Parameters

<table><thead><tr><th>Field</th><th width="113">Type</th><th width="123">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>receiverPhone</code></td><td>string</td><td></td><td>The phone number of the receiver</td></tr><tr><td><code>receiverName</code></td><td>string</td><td></td><td>The name of the receiver</td></tr><tr><td><code>cost</code></td><td>integer</td><td></td><td>The total cost associated with the order</td></tr><tr><td><code>lockerId</code></td><td>string</td><td>x</td><td>The ID of the locker that get from <a href="#get-devices-detail">device's detail</a> request</td></tr><tr><td><code>senderPhone</code></td><td>string</td><td></td><td>The phone number of the sender</td></tr><tr><td><code>stackPosition</code></td><td>number</td><td></td><td>The stack's position in this device. You must use either<code>size</code> or <code>stackPosition</code> when create order</td></tr><tr><td><code>orderType</code></td><td>enum</td><td></td><td>The orderType of order. Default is <code>locker</code></td></tr><tr><td><code>partnerCode</code></td><td>string(6)</td><td></td><td>The code to open stack in case Partner want to retrieve the order. Must using only number [0-9]</td></tr><tr><td><p></p><pre class="language-javascript"><code class="lang-javascript">partnerOutdateThreshold
</code></pre></td><td>number</td><td></td><td>The maximum time in millisecond that Partner wants to keep the order in locker before we start to count fee</td></tr><tr><td><code>size</code></td><td>enum(s,m,l,xl)</td><td></td><td>size of stack. You must use either<code>size</code> or <code>stackPosition</code> when create order</td></tr><tr><td><code>partnerOrderCode</code></td><td>string(256)</td><td></td><td>OrderCode of partner's order</td></tr><tr><td><code>partnerRentCode</code></td><td>string(256)</td><td></td><td>partner's rentCode</td></tr></tbody></table>

#### Example Request and Response

**Request**

```http
POST /order
Content-Type: application/json

{
  "receiverPhone": "1234567890",
  "receiverName": "John Doe",
  "cost": 150,
  "lockerId": "131f3e80-29f7-49e9-bd1d-3c8ae5a766b6",
  "senderPhone": "0987654321",
  "stackPosition": 1,
  "description": "Test package",
  "orderType": "locker",
  "partnerCode": "123456",
  "partnerOutdateThreshold": "10000" //10s
}
```

**Response**

<pre class="language-json"><code class="lang-json"><strong>{
</strong>    "data": {
        "id": "ceba7403-69d6-46ea-97b8-b4165cff76a7",
        "paymentStatus": false,
        "deliveryStatus": false,
        "orderStatus": "init",
        "outdateLength": 0,
        "outdateFee": 0,
        "outdateFeePaid": 0,
        "partnerOutdateThreshold": 0,
        "senderPhone": "0948170098",
        "receiverPhone": "0948170099",
        "cost": 1000,
        "lockerId": "c1568a91-f44b-47f2-b8fe-bfd9292e8ace",
        "orderType": "locker",
        "partnerId": "d4735dce-525d-41fb-931e-52761bd7f723",
        "orderCode": "O1Y2GAEP",
        "orderPass": "548067",
        "updatedAt": "2025-07-01T19:23:53.081Z",
        "createdAt": "2025-07-01T19:23:53.081Z"
    }
}
</code></pre>

## Get order's information

This API allows you to retrieve detailed information about a specific order using a tracking order parameter.

#### Endpoint

```
GET /order/{orderId}
```

#### Parameter:

* orderId: A unique identifier for the order you want to retrieve. This parameter is required to fetch the order's details.

#### Example

```http
GET /order/ceba7403-69d6-46ea-97b8-b4165cff76a7
```

Replace `{orderId}` with the actual order's ID.

#### Response Example

```json
{
    "data": {
        "id": "ceba7403-69d6-46ea-97b8-b4165cff76a7",
        "paymentStatus": false,
        "deliveryStatus": false,
        "orderStatus": "init",
        "outdateLength": 0,
        "outdateFee": 0,
        "outdateFeePaid": 0,
        "partnerOutdateThreshold": 0,
        "senderPhone": "0948170098",
        "receiverPhone": "0948170099",
        "cost": 1000,
        "lockerId": "c1568a91-f44b-47f2-b8fe-bfd9292e8ace",
        "orderType": "locker",
        "partnerId": "d4735dce-525d-41fb-931e-52761bd7f723",
        "orderCode": "O1Y2GAEP",
        "orderPass": "548067",
        "updatedAt": "2025-07-01T19:23:53.081Z",
        "createdAt": "2025-07-01T19:23:53.081Z"
    }
}
```

## List orders

The List Orders API allows you to retrieve a collection of orders based on specified criteria. You can filter orders by status, purpose, and date range, facilitating effective order management. The response will include details of each order, such as the order ID, status, receiver's information, and timestamps.

#### Endpoint

```
GET /order
```

#### Parameters

| Field           | Type                       | Require | Description                                                                                 |
| --------------- | -------------------------- | ------- | ------------------------------------------------------------------------------------------- |
| `page`          | number                     |         | The index of request's item. Default is 0                                                   |
| `size`          | number                     |         | The number item that client want to get per page. Default is 2o                             |
| `orderStatus`   | enum\[success,failed,init] |         | Order's status.  Init - new order, success - user've got order, failed - order is cancelled |
| `receiverPhone` | string                     |         | Phone number of receiver                                                                    |

**Response Example**

The response will include the list of orders matching the specified criteria. Each order in the list will contain details similar to the following:

```json
{
  "orders": [
    {
      "id": "123456",
      "orderStatus": "Delivered",
      "orderType": "Standard",
      "receiverName": "John Doe",
      "receiverPhone": "+1234567890",
      "cost": 10000,
      "orderCode": "ORD789",
      "trackingCode": "TRACK123",
      "createdAt": "2023-10-01T12:34:56Z",
      "updatedAt": "2023-10-02T09:21:18Z"
    },
    ...
  ],
  "totalOrders": 150,
  "currentPage": 1,
  "totalPages": 15
}
```

**Notes**

* Ensure date and time are in ISO 8601 format when specifying the `startTime` and `endTime`.
* The `status` and `purpose` parameters help in filtering the orders based on their current status and intended use.
* Pagination allows you to manage and display orders effectively with the `pageSize` and `pageIndex` parameters.

## Cancel order

The Cancel Order API allows you to cancel an existing order by specifying the order's unique identifier.

**Endpoint**

`PUT /order/cancel`

**Parametersa**

* `id` (string, required): The unique identifier of the order that needs to be canceled.

**Example Request**

```json
{
  "orderId": "123456"
}
```

**Response**

A successful cancellation will return a confirmation with the order details, including its updated status.

## &#x20;Renew Partner Code

This API endpoint allows you to renew the partner code for a specific order by providing the `orderId`. Upon successful renewal, it will return the order details, including the new partner code and the updated status.

**Endpoint**

```
PUT /orders/partnerCode/renew
```

**Request Parameters**

* `orderId` (string, required): The unique identifier of the order for which the partner code needs to be renewed.

**Example Request**

```json
{
  "orderId": "123456"
}
```

**Response**

A successful request will yield a response containing the order details along with the new partner code and a flag indicating whether the update was successful.

**Example Response**

```json
{
    "data": {
            "id": "fcbc1454-b148-4ecd-ad02-525afbc7c910",
            "lockerId": "84ae520e-0b72-4f8d-b68f-dd0f104e9af1",
            "orderCode": "I8ULO36D",
            "remainCost": 0,
            "orderType": "locker",
            "partnerId": "d4735dce-525d-41fb-931e-52761bd7f723",
            "partnerCode": "132592"
    }
}
```

## Renew Order pass

To renew an order code, a POST API is available that takes the parameter `orderId`. This API will return the following:

* **orderPass**: The updated order code after renewal.
* **createdAt**: The timestamp indicating when the new order code was created.
* **updatedAt**: The timestamp showing the last update to the order code.
* **id**: The unique identifier for the renewed order.

**Example Request**

````
POST /partner/order/renew

Headers:
- Content-Type: application/json
- x-api-key: api-key

Body:
```json
{
    "orderId": "fcbc1454-b148-4ecd-ad02-525afbc7c910"
}
````

**Example Response**

```json
{
    "id": "ab123456-1a2b-3c4d-5e6f-7890ghijklmn",
    "orderPass": "NEWCODE123",
    "createdAt": "2023-09-21T10:15:30Z",
    "updatedAt": "2023-09-21T10:15:30Z"
}
```

## Open stack api

Notice:&#x20;

* Only partner who is granted permission can call this API.

To initiate the process of opening a stack, the POST API can be employed, which requires two essential parameters: `orderId` and `lockerId`, both of which are strings. When making a request using this API, these parameters must be included to identify the specific order and locker involved in the transaction. Upon successful execution, the API will return a boolean result of `true`, indicating that the stack has been opened successfully, allowing authorized users or systems to perform further operations with the locker.

````
POST /partner/locker/open

Headers:
- Content-Type: application/json
- x-api-key: api-key

Body:
```json
{
    "orderId": "fcbc1454-b148-4ecd-ad02-525afbc7c910",
    "lockerId": "84ae520e-0b72-4f8d-b68f-dd0f104e9af1"
}
````

Response:

```json
{
    "result": true
}
```

* Make sure your partner ID is authorized for this API.
* Ensure orderId and lockerId are correctly provided to successfully open the locker.

## Update Payment status

To update the payment status of an order, you can use the following API endpoint.

#### Endpoint

```
PUT /partner/payment
```

#### Headers

* `Content-Type`: `application/json`
* `x-api-key`: `your-api-key`

#### Parameters

* `orderId` (string): The unique identifier of the order.
* `paymentStatus` (boolean): The new payment status to be set (e.g., `true` for paid, `false` for unpaid).

#### Example Request

```json
{
    "orderId": "example-order-id",
    "paymentStatus": true
}
```

#### Response

```json
{
    "result": true
}
```

This response indicates whether the payment status was successfully updated.

## User Token Retrieval API

This API allows partners to obtain a user token by providing two parameters: `phoneNumber` and `partnerDetail`.

#### Request

* **Method**: `POST`
* **Endpoint**: `/partner/user/token`
* **Headers**:

  * `Content-Type`: `application/json`

  **Request Body**

  ```json
  {
      "phoneNumber": "string",
      "partnerDetail": "object"
  }
  ```

  #### Response

  The response includes the following fields to inform the partner about the token and permission status.

  **Successful Response Example**

  ```json
  {
      "token": "string", // Token for accessing user's orders
      "needRequestPermission": false // Indicates if permission from the user is required
  }
  ```

  * **`token`**: The access token the partner can use to retrieve user's order data.
  * **`needRequestPermission`**: A boolean flag indicating whether the partner must wait for user consent to access order data.

## Webhook

A webhook is a mechanism that allows you to receive real-time data updates as soon as an event occurs. For order information, your system can subscribe to a webhook that sends data whenever there is a change or update in an order's status.

#### Example Payload

When an order is created or updated, a webhook payload like the following might be sent to your specified URL:

```json
{
    "id": "12345",
    "orderStatus": "success",
    "cost": 10000,
    "paymentStatus": true,
    "deliveryStatus": true,
    "receiverPhone": "0123456789",
    "receiverName": "Nguyen van a",
    "orderCode": "12345",
    "orderType": "locker",
    "senderPhone": "012345678",
    "descripion": "test",
    "createdAt": "2025-02-01",
    "updatedAt": "2025-02-02",
    "userToken": "",//token for owner of this order
    "partnerLocationId": "" //ID of partner's project
}
```

Note: `userToken` is current token of owner of this order. It's used to open a webview that help owner can access all his orders these have not been openned. This token is valid until the next webhook of this owner is created.

#### Verifying the Signature

To ensure the data integrity and authenticity of the received webhook, you should verify its signature using a shared secret key. Here's a basic example of how to check the signature:

1. Calculate the HMAC SHA256 hash of the payload using your secret key.
2. Compare the calculated hash with the signature sent in the webhook headers.
3. ```javascript
   import hmac
   import hashlib

   secret = 'your-secret-key'
   payload = b'{"orderId": "12345", "status": "shipped", "items": [{"itemId": "67890", "quantity": 2}], "total": 100.50, "currency": "USD"}'
   signature = 'expected-signature-from-header'

   # Generate hash
   calculated_signature = hmac.new(bytes(secret, 'utf-8'), payload, hashlib.sha256).hexdigest()

   # Verify signatures match
   if hmac.compare_digest(calculated_signature, signature):
       print("Signature verified.")
   else:
       print("Signature verification failed.")
   ```

   By following these steps, you can ensure that the data received is from a trusted source and hasn't been tampered with.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.palm.id.vn/docs.palm.id.vn/partner-api.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
