Ir al contenido principal

🚗 Creación de un envío

Crea un envío en Moova enviando un POST con los datos del remitente, el destinatario y los bultos.

A
Escrito por Axel Candia

Endpoint

POST /b2b/shippings?appId=TU_APP_ID

Ambiente

URL completa

Testing

https://api-dev.moova.io/b2b/shippings?appId=TU_APP_ID

Producción

https://api-prod.moova.io/b2b/shippings?appId=TU_APP_ID

Headers

Authorization: TU_APP_KEY Content-Type: application/json

ℹ️ El appId viaja en el query string y el appKey en el header Authorization (valor crudo, sin Bearer). Ver la guía de Autenticación y acceso para más detalle.

Respuesta exitosa: 201 Created con el objeto del envío creado (ver Respuesta).

🧾 Antes de empezar

La cotización previa no es obligatoria: el POST de creación cotiza automáticamente en base al origen, destino e items. Podés cotizar antes por separado si querés mostrarle el precio al usuario, pero no es un requisito para crear el envío.


📦 Tipos de envío (type)

Tipo

Descripción

regular

Envío estándar. Se realiza el mismo día si pasa a READY antes de la hora de corte; si no, al día siguiente.

next_day

El paquete se retira, pasa la noche en el warehouse de Moova y se entrega al día siguiente.

minutes_90

Urgente, dentro de 2–3 horas. Requiere flow: automatic y aprobación previa.

food

Envíos de comida o bebida. Requiere flow: automatic.

pickup

Uso interno de Moova para retirar paquetes y llevarlos al depósito. No usar sin coordinación previa.

store_pickup

Destino a una sucursal del seller para que el cliente final lo retire ahí.

mercado_flex

Integraciones con Mercado Libre Flex. Incluye escaneo obligatorio por parte del Moover.

reverse

Envío individual desde el cliente final al depósito de Moova (warehouse), típicamente por devolución.

return

Consolidación de varios envíos reverse en el depósito para luego enviarlos al warehouse del seller (como un pickup inverso).


🔄 Flujos (flow)

Flujo

Descripción

Estado inicial

manual

No se retira hasta que lo pases manualmente a READY. Ideal para generar etiquetas anticipadas.

DRAFT

semi-automatic

Se crea directamente listo para retirar (mismo día si es antes de la hora de corte).

READY

automatic

Solo para minutes_90 o food. El sistema asigna un mensajero automáticamente. Requiere coordinación previa.

READY

warehouse

Para pedidos consolidados en el depósito de Moova. Se crea en READYATSTORE. Si preferís notificar cuando esté listo para pickeo, enviá settings: [10] y actualizá el estado manualmente.

READYATSTORE


🧱 Campos del payload

Obligatorios

Campo

Tipo

Descripción

type

String

Tipo de envío (ver tabla arriba).

flow

String

Flujo del envío (ver tabla arriba).

internalOrderId

String

Tu referencia interna del pedido.

from

Object

Datos del remitente (ver Direcciones).

to

Object

Datos del destinatario (ver Direcciones).

items

Array

Bultos del envío (ver Items). No confundir con packagesCount.

Opcionales

Campo

Tipo

Descripción

scheduledDate

String

Fecha/hora (UTC) en la que el envío pasa automáticamente a READY. Formato: YYYY-MM-DD HH:mm:ss.

deliveryTimeRange

String

Franja horaria preferida: AM o PM (requiere scheduledDate mayor a hoy).

packagesCount

Integer

Cantidad de paquetes físicos (para etiquetas). No es lo mismo que items.

currency

String

Moneda ISO 4217 (ej. ars).

description

String

Descripción visible para el repartidor.

internalCode

String

Código interno. Si usás etiquetas propias, este valor las identifica (ver "Obtener etiquetas").

comments

String

Comentario general del envío.

extra

Object

Información adicional personalizada.

settings

Array

IDs de configuraciones especiales (ver Settings).

conf

Object

Info adicional del objeto enviado (item, assurance).

services

Array

Servicios extra (ver Servicios).

delivery

Object

Validaciones para la entrega, ej. código de seguridad (ver Código de seguridad).


📍 Direcciones (from y to)

Podés indicar la dirección de cuatro formas. El sistema las prioriza en este orden:

googlePlaceId > coordenadas (lat/lng) > address > street + number

⚠️ No mezcles varios formatos en el mismo objeto. Elegí uno.

Dentro de from y to incluí siempre el objeto contact:

Campo

Tipo

Descripción

firstName

String

Nombre.

lastName

String

Apellido.

phone

String

Teléfono (ej. +541112345678).

email

String

Email de contacto.

Incluí todos los que tengas disponibles. En la respuesta, Moova devuelve contact como un único string con nombre y apellido concatenados. En to.message podés dejar un mensaje especial para ese destino.

Las 4 formas de indicar una dirección

1. Con address (texto libre):

"to": { "address": "Av. Callao 1234, CABA, Buenos Aires, Argentina" }

2. Con street + number (desglosado):

"to":{
"street":"Av. Callao",
"number":"1234",
"floor":"3",
"apartment":"B",
"city":"CABA",
"state":"Buenos Aires",
"postalCode":"1023",
"country":"AR"
}

3. Con coordenadas:

"to":{
"coords":{
"lat":-34.603722,
"lng":-58.381592
},
"addressDescription":"Av. Callao 1234, CABA, Buenos Aires, Argentina"
}

4. Con Google Place ID:

"to": { "placeId": "ChIJJ3SpfQsLlVQRkYXR9ua5Nhw" }

Validación estricta de código postal (postalCodeStrict)

Evita "falsos positivos" de geolocalización (direcciones que existen en otra ciudad/provincia con nombre similar). Se agrega dentro de to:

Campo

Tipo

Default

Descripción

postalCodeStrict

Boolean

false

Si es true, compara el CP enviado contra el CP detectado por coordenadas.

  • Si coinciden: el envío se crea y geolocaliza normalmente.

  • Si NO coinciden: el envío se crea igual, pero se marca con error crítico de dirección (en rojo en el dashboard) para que Operaciones lo revise antes de despachar.

"to":{
"street":"Av. Callao",
"number":"1234",
"city":"CABA",
"state":"Buenos Aires",
"postalCode":"1023",
"country":"AR",
"postalCodeStrict":true
}

📦 Items (bultos)

Cada elemento del array items describe un bulto:

Campo

Tipo

Unidad

Descripción

Obligatorio

type

String

Tipo de bulto (ej. box).

description

String

Descripción del contenido.

Recomendado

referenceCode

String

Código de referencia del bulto.

Opcional

quantity

Integer

Cantidad de unidades.

weight

Number

gramos

Peso del bulto (ej. 1500 = 1,5 kg).

length

Number

centímetros

Largo.

width

Number

centímetros

Ancho.

height

Number

centímetros

Alto.

📏 Peso siempre en gramos y dimensiones siempre en centímetros. El size del envío se calcula automáticamente a partir de estos valores.


⚙️ Settings (configuraciones especiales)

En el array settings pasás los IDs de las configuraciones que querés activar (ej. "settings": [3, 4]). Catálogo actual (obtenible en GET /b2b/shipping-setting-options):

ID

Nombre

Qué hace

1

PickupSignature

Exige firma del remitente para poder retirar el envío.

2

PickupPhoto

Exige foto del paquete al retirarlo.

3

SignaturePhoto

En vez de firma, se toma una foto en la entrega.

4

DeliveryUserIdentification

Pide identificación del receptor en la entrega.

5

BackAndForth

Envío de ida y vuelta.

6

UpdateDeliveredItems

Permite actualizar los items entregados al finalizar.

7

DeliverySurvey

Muestra una encuesta al destinatario en la entrega.

8

OnlyDeliverToAuthorized

Entregar solo a personas autorizadas.

9

ScanReceiverId

Escanear la identificación del receptor en la entrega.

10

ViaWarehouse

El envío debe pasar por un warehouse antes de la entrega.

11

ShippingMustHaveItems

El envío debe tener al menos un item antes de ser retirado.

Algunas configuraciones pueden venir activadas por defecto según tu cuenta (aparecen en activeSettings en la respuesta aunque no las hayas enviado).


🧩 Servicios opcionales (services)

Servicio

Descripción

cash_on_delivery

Se cobra el producto en el lugar de la entrega.

seguros

Agrega un seguro por el valor declarado.

Verificá con tu asesor de ventas si están disponibles en tu país.

Se pasan como array; podés combinar ambos. Cuando usás cash_on_delivery es obligatorio enviar chargeAmount en la raíz del payload (no dentro de services):

"services": ["cash_on_delivery", "seguros"], "chargeAmount": "25.00"

💵 chargeAmount es solo el número del monto a cobrar. La moneda se determina según el país de la cuenta, así que no hace falta especificarla.

Código de seguridad en la entrega (delivery)

Permite pedirle al destinatario un código de verificación al recibir. El repartidor ve el message en su app y confirma que el código coincida.

"delivery":{
"validations":[
{
"option":"DNI",
"code":[
"222"
],
"message":"Por favor pida los últimos 3 números del DNI"
}
]
}

Campo

Tipo

Requerido

Descripción

option

String

✔️

Tipo de validación: DNI, PIN, CODE.

code

String[]

✔️

Valores válidos aceptados.

message

String

✔️

Mensaje que ve el repartidor.


📤 Ejemplo de request

{
"type":"regular",
"flow":"manual",
"internalOrderId":"pedido-1234",
"from":{
"address":"Av. Santa Fe 1234, 1425 CABA, Buenos Aires, Argentina",
"postalCode":"1425",
"contact":{
"firstName":"Juan",
"lastName":"Perez",
"phone":"+541112345678",
"email":"[email protected]"
}
},
"to":{
"street":"Av. Corrientes",
"number":300,
"city":"CABA",
"state":"Buenos Aires",
"postalCode":"1199",
"country":"AR",
"contact":{
"firstName":"Maria",
"lastName":"Gonzalez",
"phone":"+541199876543",
"email":"[email protected]"
},
"instructions":"Entregar en conserjería"
},
"items":[
{
"type":"box",
"description":"RELOJ PARA HOMBRE",
"referenceCode":"88667859432832",
"quantity":1,
"weight":1500,
"length":30,
"width":20,
"height":15
}
],
"description":"Kit promocional",
"packagesCount":1,
"scheduledDate":"2025-06-01 15:00:00",
"currency":"ars",
"internalCode":"LABEL-XYZ-987"
}

📥 Respuesta

Ejemplo abreviado (se omiten campos internos):

{
"id":"6c7f76d0-7f67-11f0-b5d0-e1aa5ea0996c",
"shortId":"6c7f76d0",
"type":"regular",
"size":"M",
"price":220000.02,
"priceFormatted":"$ 220.000,02",
"currency":"ARS",
"status":"DRAFT",
"secretCode":"5033",
"internalCode":"LABEL-XYZ-987",
"internalOrderId":"pedido-1234",
"from":{
"placeId":97425,
"googlePlaceId":"ChIJfzoxtbnKvJUR2O-zSUSNVlY",
"address":"Av. Sta. Fe 1234, C1059ABT CABA, Argentina",
"contact":"Juan",
"coords":{
"lat":-34.5959117,
"lng":-58.3846907
}
},
"to":{
"placeId":98971,
"address":"Av. Corrientes 300, C1043AAR CABA, Argentina",
"contact":"Maria Gonzalez",
"coords":{
"lat":-34.6031762,
"lng":-58.3712136
}
},
"statusHistory":[
{
"status":"DRAFT",
"details":null,
"createdAt":"2025-08-22 14:51:02"
}
],
"activeSettings":[

],
"items":[

],
"addressErrors":null
}

Campos clave de la respuesta

Campo

Qué significa

id

Identificador único del envío en Moova. Guardalo: lo vas a usar para consultar, actualizar o cancelar.

shortId

Versión corta del id.

status

Estado inicial (depende del flow; ver tabla de flujos).

size

Tamaño del envío, calculado automáticamente a partir del peso y las dimensiones de los items.

price / priceFormatted

Precio cotizado del envío. Viene siempre en la respuesta (price numérico, priceFormatted ya formateado).

secretCode

Código secreto asociado al envío, disponible por si querés usarlo del lado de tu integración.

from.placeId / to.placeId

Número = la dirección se geolocalizó OK. null = el envío se creó pero con error de dirección; hay que corregirlo en el dashboard.

addressErrors

null si todo bien. Ver sección de errores de dirección.


🧭 Manejo de errores de dirección

Si hay problemas con las direcciones, la respuesta incluye addressErrors:

"addressErrors": { "from": { "suggestions": null } }
  • Si aparece from o to, indica cuál dirección tiene el problema.

  • Si suggestions es null, no se pudo obtener una sugerencia válida.

  • Si addressErrors es null, la dirección se interpretó correctamente.

💡 Usar googlePlaceId o validar antes con la API de cotización ayuda a evitar estos errores.


❌ Errores comunes

40902 — Envío duplicado

Si intentás crear un envío con datos que ya existen, la API lo rechaza y te devuelve el id del envío existente:

{
"status":"error",
"code":40902,
"message":"El envío ya existe con el identificador 6fbeea50-3d8d-11f1-89f6-cf42a04ddfc5"
}

Moova usa el internalCode para detectar duplicados: si mandás un internalCode que ya existe en el sistema, la creación se rechaza con este error. Para evitarlo, usá un internalCode único en cada envío.

404 — Not found / Budget not found (no se encontró presupuesto)

Significa que el sistema no pudo cotizar la ruta. Causas típicas:

  • No hay tarifas configuradas para ese origen → destino.

  • Direcciones inválidas o ambiguas que no se pueden geolocalizar.

  • El área de origen/destino está fuera de la tarifa configurada.

  • El tamaño o peso de los items supera lo permitido.

Cómo resolverlo:

  • Verificá con el equipo Comercial que las tarifas de esa ruta estén activas.

  • Validá y normalizá las direcciones antes de enviarlas (por ejemplo con Google Maps o la API de cotización).

  • En testing: escribí a [email protected] con origen, destino y tipo de envío.

  • En producción: contactá a tu comercial.


Próximo paso:


Para ver configuraciones especiales como logística inversa, validaciones, flex o food, consultá la sección:
"13. Envíos especiales: settings, ida y vuelta, cobros y más"

¿Ha quedado contestada tu pregunta?