Automatización
Sigue trabajando como hasta ahora.
Tu PIM, ERP, DAM o una carpeta compartida ya tiene los datos y las fotos. Elige la primera receta que encaje: todas funcionan con cualquier portal de Open Brand Exchange.
$ obx push ./export
Publishing to brands.kestrel.example (Kestrel, Kestrel Trail)
images: 27 checked, 3 uploaded (4.2 MB) in 3s
Done: rows: 40, images: 27 → new: 2 · updated: 3 · unchanged: 35# .github/workflows/publish.yml
on:
push:
paths: ["export/**"]
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: openbrandexchange/obx-go/push-action@v0
with:
url: ${{ secrets.OBX_URL }}
token: ${{ secrets.OBX_TOKEN }}
folder: export¿Qué receta te encaja?
| Tienes… | Usa | Código necesario |
|---|---|---|
| un CSV o zip en una dirección web, un servidor SFTP o un bucket S3 | Importación programada | ninguno |
| una carpeta donde llegan las exportaciones | obx watch | ninguno |
| un servidor o PC que ejecuta tareas por la noche | cron o Programador de tareas | una línea |
| tus exportaciones en un repositorio Git | GitHub Action | un archivo YAML |
| n8n, Make o Zapier | Pasos HTTP | ninguno (visual) |
| un desarrollador que conecta tu PIM o ERP | La API directamente | un poco |
Un formato para todo
Todas las formas de publicar leen lo mismo: un products.csv con una fila por talla y fotos llamadas {style}_{color}_{position}.jpg (referencia, color, posición). Con eso, todas las recetas de abajo funcionan.
brand,style_number,name:en,name:nl,item_type,season,materials,color_code,color_name:en,size,gtin
Kestrel,KO-1001,Merino Crew Sweater,Merino trui met ronde hals,sweater,AW26,main: 100% merino_wool,NVY,Navy,S,2000100101018
Kestrel,KO-1001,Merino Crew Sweater,Merino trui met ronde hals,sweater,AW26,main: 100% merino_wool,NVY,Navy,M,2000100101025images/
KO-1001_NVY_1.jpg ← style KO-1001, colour NVY, position 1 (front)
KO-1001_NVY_2.jpg
KO-1001_NVY_3.jpgLo que necesitas
En tu administración, ve a Subida automática → Claves de acceso y crea una clave nueva. Tendrás dos valores: la dirección de tu portal (OBX_URL) y la propia clave (OBX_TOKEN). La clave solo se muestra una vez.
export OBX_URL=https://brands.kestrel.example
export OBX_TOKEN=obxi_… # admin → Automatic upload → Access keys (shown once)Da a cada sistema su propia clave. Así puedes revocar una sin romper las demás.
1. Importación programada (sin código)
En tu administración: Subida automática → Importaciones programadas → Añadir importación programada. Elige el origen y la frecuencia.
- Dirección web (HTTPS): la dirección de un products.csv, o de un zip con products.csv y fotos. Los datos de acceso se guardan cifrados.
- SFTP: servidor, usuario, contraseña o clave, y la carpeta con la exportación.
- Bucket S3: AWS S3, Cloudflare R2, MinIO o Backblaze: endpoint, bucket, carpeta y una clave de solo lectura.
Elige «Solo añadir y actualizar» o «Retirar también los artículos que falten». La segunda opción retira también lo que desapareció del archivo, pero se detiene si fuera a desaparecer más de la mitad de una marca, para que una exportación defectuosa nunca vacíe tu catálogo. «Probar conexión» muestra qué archivos leería.
La herramienta obx
obx es un único programa para Windows, macOS y Linux. Lee OBX_URL y OBX_TOKEN del entorno, sube solo las fotos nuevas o modificadas, crea las versiones web cuando hace falta y espera a que tu portal lo haya procesado todo. Ejecútalo tantas veces como quieras: los artículos sin cambios no cuestan nada.
obx info # check the token, see limits and brands
obx push --csv products.csv --images ./images # publish a CSV and a folder (or zip) of images
obx push --package export.zip # the same, as one zip
obx push --csv products.csv --images ./images --mirror # also take offline what is no longer in the file
obx push --csv products.csv --images ./images --dry-run # only check, change nothing
obx watch ./outbox # keep publishing whatever lands in a folder
obx status # recent jobs and their errorsCódigo de salida 0 = todo bien, 2 = terminado pero algunas filas tenían errores (se muestran), 1 = fallo.
2. Una carpeta que se publica sola: obx watch
Deja que tu PIM, tu ERP o un compañero guarde exportaciones en una carpeta. obx watch publica en cuanto algo cambia y omite las fotos que siguen igual. Ejecútalo como servicio o con Docker:
obx watch /data/outboxdocker run -d --restart unless-stopped \
-e OBX_URL -e OBX_TOKEN \
-v /data/outbox:/outbox \
ghcr.io/openbrandexchange/obx watch /outbox3. cron o Programador de tareas de Windows
# crontab -e: every night at 02:30
30 2 * * * OBX_URL=https://brands.kestrel.example OBX_TOKEN=obxi_… /usr/local/bin/obx push --csv /exports/products.csv --images /exports/images >> /var/log/obx.log 2>&1$action = New-ScheduledTaskAction -Execute "C:\Tools\obx.exe" -Argument "push --csv D:\Export\products.csv --images D:\Export\images"
$trigger = New-ScheduledTaskTrigger -Daily -At 2:30am
[Environment]::SetEnvironmentVariable("OBX_URL", "https://brands.kestrel.example", "Machine")
[Environment]::SetEnvironmentVariable("OBX_TOKEN", "obxi_…", "Machine")
Register-ScheduledTask -TaskName "Publish to OBX" -Action $action -Trigger $trigger -User "SYSTEM"4. GitHub Action
Guarda OBX_URL y OBX_TOKEN como secretos del repositorio. Lo mismo funciona en GitLab CI, Bitbucket o Azure DevOps: instala obx y ejecuta obx push.
# .github/workflows/publish.yml (secrets: OBX_URL, OBX_TOKEN)
name: Publish product content
on:
push:
branches: [main]
paths: ["export/**"]
schedule:
- cron: "30 2 * * *"
workflow_dispatch:
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install obx
run: |
curl -fsSL https://github.com/openbrandexchange/obx-go/releases/latest/download/obx_linux_amd64.tar.gz | tar -xz obx
sudo mv obx /usr/local/bin/
- name: Publish
env:
OBX_URL: ${{ secrets.OBX_URL }}
OBX_TOKEN: ${{ secrets.OBX_TOKEN }}
run: obx push --csv export/products.csv --assets-csv export/assets.csv --images export/images5. n8n, Make o Zapier
Usa un paso HTTP Request normal con la cabecera Authorization: Bearer seguida de tu clave. Cada paso se puede repetir sin riesgo: enviar los mismos datos dos veces no cambia nada.
PUT {OBX_URL}/obx/v1/ingest/products/KO-1001
Authorization: Bearer obxi_…
Content-Type: application/json
{"style_number": "KO-1001",
"name": {"en": "Merino Crew Sweater", "nl": "Merino trui met ronde hals"},
"item_type": "sweater", "season": "AW26",
"materials": [{"part": "main", "fibers": [{"fiber": "merino_wool", "percentage": 100}]}]}PUT {OBX_URL}/obx/v1/ingest/variants/2000100101025
Authorization: Bearer obxi_…
Content-Type: application/json
{"product_external_id": "KO-1001", "gtin": "2000100101025",
"color": {"code": "NVY", "name": {"en": "Navy"}}, "size": "M"}PUT {OBX_URL}/obx/v1/ingest/assets/KO-1001_NVY_1
Authorization: Bearer obxi_…
Content-Type: application/json
{"product_external_id": "KO-1001", "color_code": "NVY",
"role": "packshot", "view": "front", "position": 1}
PUT {OBX_URL}/obx/v1/ingest/assets/KO-1001_NVY_1/files/original
Authorization: Bearer obxi_…
Content-Type: image/jpeg
<the image file as binary body>El Portal para Cloudflare no crea por sí mismo versiones web de las fotos. Publica allí con obx o desde «Importaciones» en tu administración: ellos las crean por ti. Las fotos que llegan de otra forma, por ejemplo con una importación programada, se muestran hasta entonces a su tamaño original.
PATCH {OBX_URL}/obx/v1/ingest/products/KO-1001
Authorization: Bearer obxi_…
Content-Type: application/merge-patch+json
{"status": "unpublished"}¿Quieres un aviso cuando pase algo? En tu administración, añade una notificación (webhook) para una importación terminada o una nueva solicitud de acceso, y haz que active un disparador en n8n, Make o Zapier.
6. La API directamente (para desarrolladores)
Una integración recuerda lo que envió la última vez y solo envía los cambios, por lotes. O envía el CSV tal cual y deja que el portal lo lea.
URL="$OBX_URL/obx/v1/ingest"; AUTH="Authorization: Bearer $OBX_TOKEN"
# 1. Upload only the images the node does not have yet (addressed by sha256).
for f in images/*.jpg; do
sha=$(shasum -a 256 "$f" | cut -d' ' -f1)
curl -sf -I -H "$AUTH" "$URL/blobs/$sha" >/dev/null || \
curl -sf -X PUT -H "$AUTH" -H 'Content-Type: image/jpeg' --data-binary @"$f" "$URL/blobs/$sha"
done
# 2. One batch of up to 1000 operations (NDJSON), processed in order.
cat > batch.ndjson <<'EOF'
{"op":"upsert","kind":"product","external_id":"KO-1001","data":{"style_number":"KO-1001","name":{"en":"Merino Crew Sweater"}}}
{"op":"upsert","kind":"variant","external_id":"2000100101025","data":{"product_external_id":"KO-1001","gtin":"2000100101025","color":{"code":"NVY"},"size":"M"}}
{"op":"unpublish","kind":"product","external_id":"KO-0999"}
EOF
curl -s -X POST -H "$AUTH" -H 'Content-Type: application/x-ndjson' \
-H "Idempotency-Key: nightly-$(date +%F)" --data-binary @batch.ndjson "$URL/batch"curl -s -X POST -H "Authorization: Bearer $OBX_TOKEN" \
-F [email protected] -F [email protected] \
-F 'options={"mode":"upsert"};type=application/json' \
"$OBX_URL/obx/v1/ingest/imports" # returns a job; poll $OBX_URL/obx/v1/ingest/jobs/<id>Todos los detalles están en la especificación:Ingest API ·recetas de automatización ·SDK de Go ·Desarrolladores