> For the complete documentation index, see [llms.txt](https://iflow21.gitbook.io/ecommerce/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://iflow21.gitbook.io/ecommerce/integracion-con-carriers/integracion-por-api-rest.md).

# Integración por API REST

## Introducción a la Integración con iFLOW

Bienvenido a la documentación de integración por API con **iFLOW**.\
Aquí encontrarás los endpoints necesarios para conectar tu sistema con nuestra plataforma y así gestionar envíos, consultar órdenes y reportar eventos de manera segura y estandarizada.

#### ¿Qué necesitas saber antes de comenzar?

* **Entorno de pruebas (testing):** Todos los ejemplos de esta documentación utilizan credenciales y URLs de prueba.
* **Entorno productivo:** Antes de salir a producción deberás actualizar las URLs y credenciales correspondientes.
* **Autenticación:** El primer paso será realizar el **Login** para obtener un `access token`, el cual deberás enviar en cada solicitud.
* **Tokens:** El `refresh token` permite mantener la sesión activa sin necesidad de volver a loguearse constantemente.

#### Flujo básico de integración

1. **Login** → obtén tu `access token` y `refresh token`.
2. **Refresh Token** → renueva tu sesión antes de que expire.
3. **Get Shipments** → consulta los envíos asignados a tu carrier.
4. **Report Events** → informa los estados y eventos de cada envío (ejemplo: entregado, en tránsito, incidencias, etc.).

⚠️ **Importante:**

* No utilices las credenciales de prueba en producción.
* En producción debes reemplazar:
  * `https://usr.jointheplanet.app` → por → `https://usr.jointheplanetproject.app`
  * `https://api.jointheplanet.app` → por → `https://api.jointheplanetproject.app`&#x20;

### Login

Este endpoint permite a los **carriers** iniciar sesión en el sistema y obtener un **access token**, que será necesario para acceder a los demás endpoints disponibles en la API.

El token generado debe ser almacenado y utilizado como mecanismo de autenticación en las solicitudes posteriores.

<mark style="color:green;">`POST`</mark> [`https://usr.jointheplanet.app/api/Login/LoginUser`](https://usr.jointheplanet.app/api/Login/LoginUser)

<details>

<summary>Headers</summary>

Content-Type: application/json

</details>

**Ejemplo**

{% tabs %}
{% tab title="cULR" %}

```json
curl --location 'https://usr.jointheplanet.app/api/Login/LoginUser' \
--data '{
    "userLoginInfo": {
        "userName": "será indicado por iFLOW",
        "password": "será indicado por iFLOW",
        "application": {
            "appKey": "ok"
        }
    }
}'
```

{% endtab %}
{% endtabs %}

**Response**

{% tabs %}
{% tab title="🟢 200" %}

```json
{
  "data": {
    "userLogged": {
      "user": {
        "userId": "1",
        "userUuid": "123ab1a1-9874-6541-54a1-1478045f8532"
      },
      "userToken": {
        "appToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJOaGFMaDRIYnNya2FCUFNGWU05VXNUbzQxaUVIa3Z1aG41c0JHUlI3WFZlcHgyK1ZDd2JhUlE9PSIsInVzZXJVdWlkIjoieXc4dTBSYzByZm1wd1d3bXBGdDUxcmdTRFVCcFl3UTcvOElCK0ZzU1pEVG4yaldsSzEwMEQxSjFHUmFycXZxL0hTRUNyUmhVOExKcW8weHo1aXMxMTZidkJEaXByTVphck1Nc2hCSDNIRFE9IiwiYXBwS2V5IjoidEZMcGd4enllNUhyWGtxcERPQUR3bHY4UGxKbEhrTVFVV0VXMnRtNnlubUJ3b0RhTTNlS0xnPT0iLCJ0a1R5cGUiOiJxUmdXbTAxK21KNTBpU0VZU2U2K3I3V2M4cmRWdDFBQTNPRXdyZHV5Y3JuZEVGVEhJbFlKOWx3YzJLaVBDNGd3IiwiZXhwIjoxNzM3NTA2MDg5LCJpc3MiOiJTdHVkaW9NaXN0LmlvIiwiYXVkIjoiU3R1ZGlvTWlzdCJ9.d0liah5ZCbJTtu73JyemN4YKs-1YAm1XwQB09kPvPdM",
        "expiresInSeconds": 21600
      },
      "refreshToken": {
        "appToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIwaU1vZ3h6ZjZEWjdtanEwQk5aUmNVTGt6Qi9MRGZuSGQvRWlTTkpqRG51aHRabWUreFFDNHc9PSIsInVzZXJVdWlkIjoieXc4dTBSYzByZm1wd1d3bXBGdDUxcmdTRFVCcFl3UTcvOElCK0ZzU1pEUVFlTGgyY2VzOFpTVkZIWWtjM0NGclBnMWJqMTZTVG54dStVM0tDaE9zMnBEdFBWUTVUcUcrdGtmYmdnZXl0Wkk9IiwiYXBwS2V5IjoiREI2amZJVXZoQjI4bURmUXp5ZDVPa01yK1Mwa2ZhQlExK0tETmFVdk9iZkNoK0EvRXlURFpBPT0iLCJ0a1R5cGUiOiIwWWNFd2JtWiswK0MyQXNKSllGY2RSN2hyRnNobVFrOTRISGVCLzluYkdMay9yUjkyOTQrTDZ4bkZRWC9hZ21hIiwiZXhwIjoxNzM3OTE2NDg5LCJpc3MiOiJTdHVkaW9NaXN0LmlvIiwiYXVkIjoiU3R1ZGlvTWlzdCJ9.jBmHwhMfjBrweIuE_khOJUz2SVM45xDPq5ajvwKrf5M",
        "expiresInSeconds": 0
      }
    }
  },
  "server_info": {
    "serverDebugInfo": []
  }
} 
```

{% endtab %}

{% tab title="🟡400 (credenciales Invalidas)" %}

```json
{
    "errors": {
        "systemError": true,
        "location": "khs.api.usr.Controllers.LoginController - Void MoveNext()",
        "description": "Invalid Username or Password",
        "systemDebugError": [
            {
                "location": "Object - 3543ca67-3730-4837-90d1-77bb9e0c394c",
                "description": "khs.blo.trk.Event.Login - Invalid Username or Password"
            }
        ]
    },
    "server_info": {
        "serverDebugInfo": []
    }
}
```

{% endtab %}
{% endtabs %}

### Refresh Token

#### Manejo del Refresh Token

Una vez completado el proceso de login, se debe almacenar el **refresh token** que se recibe en la respuesta. Este token es esencial, ya que debe enviarse como un **header** en la solicitud para obtener un nuevo **access token** mediante el endpoint de refresh token.

El **refresh token** tiene una validez de **5 días**, lo que permite evitar realizar el login nuevamente dentro de ese período. Asegúrate de administrarlo correctamente para mantener la sesión activa y minimizar interrupciones en el flujo de autenticación.

<mark style="color:green;">`POST`</mark> [`https://usr.jointheplanet.app/api/Login/refreshUserToken`](https://usr.jointheplanet.app/api/Login/refreshUserToken)

<details>

<summary>Autorization</summary>

Bearer TokenToken: \<token>

</details>

<details>

<summary>Headers</summary>

Content-Type: application/json

</details>

**Ejemplo**

{% tabs %}
{% tab title="cULR" %}

```json
curl --location 'https://usr.jointheplanet.app/api/Login/refreshUserToken' \
--data '{
    "userInfo": {
        "user": {
            "userId": "1",
            "userUuid": "123ab1a1-9874-6541-54a1-1478045f8532"
        },
        "application": {
            "appKey": "appKey"
        }
    }
}'
```

{% endtab %}
{% endtabs %}

**Response**

{% tabs %}
{% tab title="🟢 200" %}

```json
{
  "data": {
    "userLogged": {
      "user": {
            "userId": "1",
            "userUuid": "123ab1a1-9874-6541-54a1-1478045f8532"
      },
      "userToken": {
        "appToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJScG94QllYTWhYa1Z2dkxNZ2JCNGh3M2JORmZVL2VvejJNQWNqbnA0VUN4c3IwTUtkRGJIOVE9PSIsInVzZXJVdWlkIjoieXc4dTBSYzByZm1wd1d3bXBGdDUxcmdTRFVCcFl3UTcvOElCK0ZzU1pEVDFHRXJpSTNxYnNFVk1ZZVFmU25xSWJqZGZlV0E1bG9WSVlQNVBzQUxQS29IaXFDdmJpM1lubDhpQzB6VTh6YTQ9IiwiYXBwS2V5IjoiV3NIbSs2ZjRLdVRwK0t4dXA4UnpWRkMxQkFRT1hBTTB0YWpHaHdiZzV2Q3V4RVEvaG5EZHNRPT0iLCJ0a1R5cGUiOiJ4cUE3RFA0RFpIY0QxRkdpNGYxR1ZJVDQwVUxxNnNUSGVhQUhxMUlSOFN4SVNjWDliNUM1Nzgxem1UcjJGdURsIiwiZXhwIjoxNzM3NTA2MTY0LCJpc3MiOiJTdHVkaW9NaXN0LmlvIiwiYXVkIjoiU3R1ZGlvTWlzdCJ9.Q502E17UGzaHO1dRbIY8e1VR-5Y5hTKoRBsAglbhkKI",
        "expiresInSeconds": 21600
      },
      "refreshToken": {
        "appToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI4SHJtUEF4NFMydlhIOXNuSGd6a1diRkRTZ3MwS3FTUEdBYSsyYkh1aGRaRjFFalJMRUFjS3c9PSIsInVzZXJVdWlkIjoieXc4dTBSYzByZm1wd1d3bXBGdDUxcmdTRFVCcFl3UTcvOElCK0ZzU1pEVFF1MjU5ajRVY2NaZW9laG40TXF5dXArTVNpV1RLWkhyTXVXVDBoREZKVU5FUGJYWjlIaGs1aFZGb0l4amYrQ0k9IiwiYXBwS2V5IjoidGtJOS9WZ2M2SFhPQThudkZVWHRTa05WZjdQRjlEeUN3SnVEdWVWK080UEVyek9DdDR5M1FBPT0iLCJ0a1R5cGUiOiJvcXpNNkkvTlFxdzJhNGRkK3ptMHE2YlNRWWxMZ3BDdmR3c0VvSTNGN0dYZzQ2L0wwdGxyeU5lNXg3VElOWWpNIiwiZXhwIjoxNzM3OTE2NTY0LCJpc3MiOiJTdHVkaW9NaXN0LmlvIiwiYXVkIjoiU3R1ZGlvTWlzdCJ9.PdSE085ggipAbR_mprc3G5moAxJfXR0TV8a_8Whv3EQ",
        "expiresInSeconds": 0
      }
    }
  },
  "server_info": {
    "serverDebugInfo": []
  }
}
```

{% endtab %}
{% endtabs %}

### Get Shipments of Carrier

Este endpoint permite a los **carriers** obtener las órdenes que tienen asignadas con estado **"Programado"**.

El **carrier** debe enviar su `pvdCarrierId` en el request para asegurarse de recibir únicamente las órdenes correspondientes a su empresa.

**Nota:** Una vez que el carrier informe el estado **"Registrado"** en una orden, la misma dejara de aparecer en la lista.

<mark style="color:green;">`POST`</mark> [`https://api.jointheplanet.app/api/Provider/std-get-shipments-by-carrier?pageNumber=1&pageSize=10`](https://api.jointheplanet.app/api/Provider/std-get-shipments-by-carrier?pageNumber=1\&pageSize=10)

<details>

<summary>Autorization</summary>

Bearer TokenToken: \<token>

</details>

<details>

<summary>Headers</summary>

Content-Type: application/json

</details>

<details>

<summary>Params</summary>

pageNumber: 1

pageSize: 10

</details>

**Ejemplo**

{% tabs %}
{% tab title="cULR" %}

```json
curl --location 'https://api.jointheplanet.app/api/Provider/std-get-shipments-by-carrier?pageNumber=1&pageSize=10' \
--data '{
  "userInfo": {
    "user": {
      "userId": "userId",
      "userUuid": "userUuid"
    },
    "application": {
      "appKey": "appKey"
    }
  },
  "pvdCarrierId": //será indicado por iFLOW
}'
```

{% endtab %}
{% endtabs %}

**Response**

{% tabs %}
{% tab title="🟢 200" %}

```json
{
  "data": {
    "shipments": [
      {
        "shipment": {
          "shpShipmentId": 819,
          "shpTrackingCode": "FRA0000000065215",
          "sorOrderNumber": "FRA0000000065215",
          "sorOrderReference": "00000789",
          "svcServiceIdDefault": 1,
          "shpValueItemsTotal": 1,
          "currentState": "PROGRAMADO",
          "shipmentEntitities": [
            {
              "steName": "Consignee",
              "senFirstName": "Jose",
              "senEmail": "test@test.com",
              "senLastName": "Martinez",
              "entityAddresses": [
                {
                  "eadName": "Jose",
                  "eadLastName": "Martinez",
                  "eadCountry": "AR",
                  "eadStateProvinceRegion": "CORDOBA",
                  "eadCity": "CORDOBA",
                  "eadZipCode": "5000",
                  "eadPhoneNumber": "",
                  "eadStreetAddress01": "Venezuela 2578",
                  "gctName": "Argentina"
                }
              ]
            }
          ],
          "shipmentWeight": [
            {
              "stwName": "Kilograms",
              "stwCode": "kg",
              "swtWeight": 0.001
            }
          ],
          "shipmentDimensions": [
            {
              "sdmWidth": 1,
              "sdmLength": 1,
              "sdmHeight": 1,
              "stdCode": "cm",
              "stdName": "Centimeters"
            }
          ]
        }
      }
    ]
  },
  "server_info": {
    "serverDebugInfo": []
  }
}
}
```

{% endtab %}
{% endtabs %}

### Get Shipments of Carrier by status

Este endpoint permite a los **carriers** filtrar las órdenes que tienen asignadas por un estado especifico.

El **carrier** debe enviar su `pvdCarrierId` y el `statusId` por el cual desea filtrar.

**Nota:** Si no se envía el `statusId`, el endpoint devolverá todas las órdenes que aún no tengan el estado **"Registrado"**, como se mencionó anteriormente.

<mark style="color:green;">`POST`</mark>[`https://api.jointheplanet.app/api/Provider/std-get-shipments-by-carrier?pageNumber=1&pageSize=10`](https://api.jointheplanet.app/api/Provider/std-get-shipments-by-carrier?pageNumber=1\&pageSize=10)

<details>

<summary>Autorization</summary>

Bearer TokenToken: \<token>

</details>

<details>

<summary>Headers</summary>

Content-Type: application/json

</details>

<details>

<summary>Params</summary>

pageNumber: 1

pageSize: 10

</details>

**Ejemplo**

{% tabs %}
{% tab title="cULR" %}

```json
curl --location 'https://api.jointheplanet.app/api/Provider/std-get-shipments-by-carrier?pageNumber=1&pageSize=10' \
--data '{
  "userInfo": {
    "user": {
      "userId": "userId",
      "userUuid": "userUuid"
    },
    "application": {
      "appKey": "appKey"
    }
  },
  "pvdCarrierId": "será indicado por iFLOW", 
  "statusId": 35 //Seran indicados por IFLOW
}'
```

{% endtab %}
{% endtabs %}

**Response**

{% tabs %}
{% tab title="🟢 200" %}

```json
{
  "data": {
    "shipments": [
      {
        "shipment": {
          "shpShipmentId": 817,
          "shpTrackingCode": "FRA0000000065213",
          "sorOrderNumber": "FRA0000000065213",
          "sorOrderReference": "00000135468",
          "svcServiceIdDefault": 1,
          "shpValueItemsTotal": 1,
          "currentState": "NO ENTREGADO",
          "shipmentEntitities": [
            {
              "steName": "Consignee",
              "senFirstName": "Jose",
              "senEmail": "Test@test.com",
              "senLastName": "Martinez",
              "entityAddresses": [
                {
                  "eadName": "Jose",
                  "eadLastName": "Martinez",
                  "eadCountry": "AR",
                  "eadStateProvinceRegion": "CORDOBA",
                  "eadCity": "CORDOBA",
                  "eadZipCode": "5000",
                  "eadPhoneNumber": "",
                  "eadStreetAddress01": "Venezuela 2578",
                  "gctName": "Argentina"
                }
              ]
            }
          ],
          "shipmentWeight": [
            {
              "stwName": "Kilograms",
              "stwCode": "kg",
              "swtWeight": 0.001
            }
          ],
          "shipmentDimensions": [
            {
              "sdmWidth": 1,
              "sdmLength": 1,
              "sdmHeight": 1,
              "stdCode": "cm",
              "stdName": "Centimeters"
            }
          ]
        }
      }
    ]
  },
  "server_info": {
    "serverDebugInfo": []
  }
}
```

{% endtab %}
{% endtabs %}

### New Carrier Event

Este endpoint permite a los **carriers** actualizar el estado de las órdenes asignadas.

Para realizar la actualización, se deben enviar los siguientes datos:

* **TrackingNumber**: Número de seguimiento del envío.
* **pvdCarrierId**: Identificador del carrier.
* **trackingEvents**: Uno o más eventos de seguimiento asociados al envío.

Este endpoint asegura que los eventos se registren correctamente para mantener actualizada la información del estado de las órdenes.

Los eventos que se deben informar son los siguientes:

| sveOriginalCode           | Descripción               |
| ------------------------- | ------------------------- |
| PEDIDO EN DISTRIBUCIÓN    | PEDIDO EN DISTRIBUCIÓN    |
| ENTREGADO                 | ENTREGADO                 |
| ARRIBO A NODO             | ARRIBO A NODO             |
| CONTINGENCIA              | CONTINGENCIA              |
| NO ENTREGADO              | NO ENTREGADO              |
| DESPACHADO A NODO INTERNO | DESPACHADO A NODO INTERNO |
| REGISTRADO                | REGISTRADO POR CARRIER    |
| DESPACHADO                | DESPACHADO                |
| RECIBIDO EN CD            | RECIBIDO EN CD            |
| DEVOLUCION A CENTRAL      | DEVOLUCION A CENTRAL      |

Si un evento o motivo no se encuentra registrado en la base de datos, el sistema generará un error al intentar ingresarlo.

**Nota:** El primer evento que se debe informar es el evento **"REGISTRADO"**, tal como se muestra en el ejemplo que sigue, que indica que dicha orden fue registrada en el sistema del carrier.

<mark style="color:green;">`POST`</mark> [`https://api.jointheplanet.app/api/Partner/std-new-event-process-carrier`](https://api.jointheplanet.app/api/Partner/std-new-event-process-carrier)

<details>

<summary>Autorization</summary>

Bearer TokenToken: \<token>

</details>

<details>

<summary>Headers</summary>

Content-Type: application/json

</details>

**Ejemplo**

{% tabs %}
{% tab title="cULR" %}

```json
curl --location 'http://localhost:5291/api/Partner/std-new-event-process-carrier' \
--data '{
  "userInfo": {
    "user": {
        "userId": "userId",
        "userUuid": "userUuid"
    },
    "application": {
      "appKey": "appKey"
    }
  },
  "TrackingNumber": "FRA0000000065213",
  "pvdCarrierId": "será indicado por iFLOW",
  "trackingEvents": [
    {
      "sveOriginalCode": "NO ENTREGADO",
      "sveEventDateOriginal": "2025-01-21 13:48:55",
      "sveComments": "",
      "rsnReasonCode": "1"
    }
  ]
}'
```

{% endtab %}
{% endtabs %}

**Response**

{% tabs %}
{% tab title="🟢 200" %}

```json
{
  "data": {
    "data": [
      {
        "updated_rows": 1,
        "available_rows": 1
      }
    ],
    "server_info": {
      "serverDebugInfo": []
    }
  },
  "server_info": {
    "serverDebugInfo": []
  }
}
```

{% endtab %}
{% endtabs %}

### New Carrier Event with Reason

Este endpoint es el mismo que el anterior, pero con ejemplos enviando motivos.

Los motivos que se deben informar son los siguientes:

| rsnReasonCode | Descripción            |
| ------------- | ---------------------- |
| 1             | CERRADO-AUSENTE        |
| 76            | MAL GEOREFERENCIADO    |
| 1003          | DIRECCION INSUFICIENTE |
| 78            | RECHAZADO              |
| 58            | ZONA PELIGROSA         |
| 50            | NO VISITO              |
| 59            | SIN ETIQUETA           |

Si un evento o motivo no se encuentra registrado en la base de datos, el sistema generará un error al intentar ingresarlo.

<mark style="color:green;">`POST`</mark>[`https://api.jointheplanet.app/api/Partner/std-new-event-process-carrier`](https://api.jointheplanet.app/api/Partner/std-new-event-process-carrier)

<details>

<summary>Autorization</summary>

Bearer TokenToken: \<token>

</details>

<details>

<summary>Headers</summary>

Content-Type: application/json

</details>

**Ejemplo**

{% tabs %}
{% tab title="cULR" %}

```json
curl --location 'http://localhost:5291/api/Partner/std-new-event-process-carrier' \
--data '{
  "userInfo": {
    "user": {
        "userId": "userId",
        "userUuid": "userUuid"
    },
    "application": {
      "appKey": "appKey"
    }
  },
  "TrackingNumber": "FRA0000000065213",
  "pvdCarrierId": "será indicado por iFLOW",
  "trackingEvents": [
    {
      "sveOriginalCode": "NO ENTREGADO",
      "sveEventDateOriginal": "2025-01-21 13:48:55",
      "sveComments": "",
      "rsnReasonCode": "1"
    }
  ]
}'
```

{% endtab %}
{% endtabs %}

**Response**

{% tabs %}
{% tab title="🟢 200" %}

```json
{
  "data": {
    "data": [
      {
        "updated_rows": 1,
        "available_rows": 1
      }
    ],
    "server_info": {
      "serverDebugInfo": []
    }
  },
  "server_info": {
    "serverDebugInfo": []
  }
}
```

{% endtab %}
{% endtabs %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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://iflow21.gitbook.io/ecommerce/integracion-con-carriers/integracion-por-api-rest.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.
