Inicio rápido

Tu primera llamada, solo lectura

Crea un token, identifica tu tienda y consulta sus productos desde un servidor.

La API usa producción, aunque los pagos estén en sandbox. Los IDs y las respuestas de esta guía son ficticios; reemplázalos por los de tu tienda.

  1. Crea un token de solo lectura

    En API e integraciones, elige la tienda, el acceso solo lectura y un vencimiento. El secreto se muestra una sola vez; guárdalo en una variable de entorno del servidor llamada MOKU_PAT.

    No pegues el token en estas páginas, URLs, repositorios ni JavaScript del navegador. Incluso un token de lectura permite ver datos personales de pedidos: protege su almacenamiento y sus logs.

    Requisitos de los ejemplos

    Los ejemplos cURL usan una terminal de servidor. Los ejemplos PHP son programas para PHP CLI y requieren la extensión cURL; no son un plugin ni código para pegar directamente en WordPress. Ambos leen MOKU_PAT desde el entorno y muestran la respuesta sin incluir el token.

    Permisos, vencimiento y revocación
  2. Obtén el ID de tu tienda

    Envía el token como Authorization: Bearer. En v1, un PAT válido autoriza una sola tienda: guarda data[0].id y úsalo como vendor_id en las siguientes rutas.

    Tienda vinculada al PAT

    Solicitud · ejemplo ilustrativo

    cURL
    : "${MOKU_PAT:?}" &&
    curl --silent --show-error --fail-with-body \
      'https://moku.cl/api/v1/vendors' \
      --header "Authorization: Bearer ${MOKU_PAT}" \
      --header 'Accept: application/json'
    PHP

    Ejemplo para PHP CLI con la extensión cURL. No es un plugin de WordPress ni debe ejecutarse en el navegador.

    <?php
    $token = getenv('MOKU_PAT');
    if ($token === false || $token === '') {
        throw new RuntimeException('MOKU_PAT');
    }
    
    $url = 'https://moku.cl/api/v1/vendors';
    $curl = curl_init($url);
    if ($curl === false) {
        throw new RuntimeException('curl_init');
    }
    curl_setopt_array($curl, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_CUSTOMREQUEST => 'GET',
        CURLOPT_CONNECTTIMEOUT => 10,
        CURLOPT_TIMEOUT => 30,
        CURLOPT_HTTPHEADER => [
            'Accept: application/json',
            'Authorization: Bearer ' . $token,
        ],
    ]);
    $response = curl_exec($curl);
    if ($response === false) {
        $message = curl_error($curl);
        curl_close($curl);
        throw new RuntimeException($message);
    }
    $status = curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
    curl_close($curl);
    $result = json_decode($response, false, 512, JSON_THROW_ON_ERROR);
    $failed = $status < 200 || $status >= 300;
    if ($failed) {
        fwrite(STDERR, "HTTP {$status}\n");
    }
    fwrite(
        $failed ? STDERR : STDOUT,
        json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR) . PHP_EOL
    );
    exit($failed ? 1 : 0);

    Respuesta 200 application/json

    {
      "data": [
        {
          "id": "vendor_demo_ceramica",
          "name": "Cerámica de ejemplo",
          "slug": "ceramica-de-ejemplo"
        }
      ]
    }
    ¿La respuesta es 401?

    Un token ausente, vencido, revocado o que ya no corresponde al dueño de la tienda falla con UNAUTHENTICATED, no con una lista vacía. Revisa la credencial; no registres su valor.

    Token ausente o no válido

    Solicitud · ejemplo ilustrativo

    cURL
    curl --silent --show-error --fail-with-body \
      'https://moku.cl/api/v1/vendors' \
      --header 'Accept: application/json'
    PHP

    Ejemplo para PHP CLI con la extensión cURL. No es un plugin de WordPress ni debe ejecutarse en el navegador.

    <?php
    
    $url = 'https://moku.cl/api/v1/vendors';
    $curl = curl_init($url);
    if ($curl === false) {
        throw new RuntimeException('curl_init');
    }
    curl_setopt_array($curl, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_CUSTOMREQUEST => 'GET',
        CURLOPT_CONNECTTIMEOUT => 10,
        CURLOPT_TIMEOUT => 30,
        CURLOPT_HTTPHEADER => [
            'Accept: application/json',
        ],
    ]);
    $response = curl_exec($curl);
    if ($response === false) {
        $message = curl_error($curl);
        curl_close($curl);
        throw new RuntimeException($message);
    }
    $status = curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
    curl_close($curl);
    $result = json_decode($response, false, 512, JSON_THROW_ON_ERROR);
    $failed = $status < 200 || $status >= 300;
    if ($failed) {
        fwrite(STDERR, "HTTP {$status}\n");
    }
    fwrite(
        $failed ? STDERR : STDOUT,
        json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR) . PHP_EOL
    );
    exit($failed ? 1 : 0);

    Respuesta 401 application/problem+json

    {
      "type": "https://developers.moku.cl/reference/errors/#unauthenticated",
      "title": "Authentication required",
      "status": 401,
      "code": "UNAUTHENTICATED",
      "detail": "Provide a valid Moku personal access token.",
      "request_id": "req_00000000000000000000000000000002"
    }
  3. Lista tus productos

    Reemplaza el ID ficticio de la URL por el recibido en el paso anterior. La respuesta incluye productos en todos sus estados de publicación; una lectura no publica ni modifica nada.

    Primera página de productos

    Solicitud · ejemplo ilustrativo

    cURL
    : "${MOKU_PAT:?}" &&
    curl --silent --show-error --fail-with-body \
      'https://moku.cl/api/v1/vendors/vendor_demo_ceramica/products' \
      --header "Authorization: Bearer ${MOKU_PAT}" \
      --header 'Accept: application/json' \
      --get \
      --data-urlencode 'limit=1'
    PHP

    Ejemplo para PHP CLI con la extensión cURL. No es un plugin de WordPress ni debe ejecutarse en el navegador.

    <?php
    $token = getenv('MOKU_PAT');
    if ($token === false || $token === '') {
        throw new RuntimeException('MOKU_PAT');
    }
    
    $url = 'https://moku.cl/api/v1/vendors/vendor_demo_ceramica/products';
    $query = [
        'limit' => '1',
    ];
    $url .= '?' . http_build_query($query, '', '&', PHP_QUERY_RFC3986);
    $curl = curl_init($url);
    if ($curl === false) {
        throw new RuntimeException('curl_init');
    }
    curl_setopt_array($curl, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_CUSTOMREQUEST => 'GET',
        CURLOPT_CONNECTTIMEOUT => 10,
        CURLOPT_TIMEOUT => 30,
        CURLOPT_HTTPHEADER => [
            'Accept: application/json',
            'Authorization: Bearer ' . $token,
        ],
    ]);
    $response = curl_exec($curl);
    if ($response === false) {
        $message = curl_error($curl);
        curl_close($curl);
        throw new RuntimeException($message);
    }
    $status = curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
    curl_close($curl);
    $result = json_decode($response, false, 512, JSON_THROW_ON_ERROR);
    $failed = $status < 200 || $status >= 300;
    if ($failed) {
        fwrite(STDERR, "HTTP {$status}\n");
    }
    fwrite(
        $failed ? STDERR : STDOUT,
        json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR) . PHP_EOL
    );
    exit($failed ? 1 : 0);

    Respuesta 200 application/json

    {
      "data": [
        {
          "id": "product_demo_tazon",
          "vendor_id": "vendor_demo_ceramica",
          "catalog_status": "active",
          "status": "published",
          "revision": 3,
          "kind": "variable",
          "name": "Tazón de cerámica",
          "slug": "tazon-de-ceramica",
          "description": "Tazón de cerámica hecho a mano.",
          "price": 15000,
          "original_price": null,
          "discount": 0,
          "category": "hogar",
          "subcategory": "ceramica",
          "image_urls": [
            "https://example.com/tazon-azul.jpg"
          ],
          "badge": null,
          "options": {
            "Color": [
              "Azul"
            ]
          },
          "default_options": {
            "Color": "Azul"
          },
          "variations": [
            {
              "id": "variation_demo_azul",
              "status": "active",
              "options": {
                "Color": "Azul"
              },
              "price": 15000,
              "original_price": null,
              "sku": "TAZ-AZUL"
            }
          ],
          "features": [
            "Hecho a mano"
          ],
          "related_product_ids": [],
          "tags": [
            "ceramica"
          ],
          "sku": null,
          "weight_kg": 0.4,
          "source_region": "metropolitana",
          "created_at": "2026-08-01T12:00:00.000Z",
          "updated_at": "2026-08-26T09:00:00.000Z",
          "published_at": "2026-08-01T12:00:00.000Z",
          "archived_at": null
        }
      ],
      "page": {
        "next_cursor": "eyJ2IjoxLCJraW5kIjoicHJvZHVjdCIsInZlbmRvcklkIjoidmVuZG9yX2RlbW9fY2VyYW1pY2EiLCJwcm9kdWN0SWQiOiJwcm9kdWN0X2RlbW9fdGF6b24ifQ.KalmHw2-bJJUEJF6PFqDKKyNmWuniEUIYAG3mWI_TM4"
      }
    }
    Una tienda sin productos también responde 200

    Una respuesta con data: [] y page.next_cursor: null es válida. Muestra un estado vacío y termina la lectura; no crees productos automáticamente para completar esta guía.

    Catálogo vacío

    Solicitud · ejemplo ilustrativo

    cURL
    : "${MOKU_PAT:?}" &&
    curl --silent --show-error --fail-with-body \
      'https://moku.cl/api/v1/vendors/vendor_demo_ceramica/products' \
      --header "Authorization: Bearer ${MOKU_PAT}" \
      --header 'Accept: application/json' \
      --get \
      --data-urlencode 'limit=1'
    PHP

    Ejemplo para PHP CLI con la extensión cURL. No es un plugin de WordPress ni debe ejecutarse en el navegador.

    <?php
    $token = getenv('MOKU_PAT');
    if ($token === false || $token === '') {
        throw new RuntimeException('MOKU_PAT');
    }
    
    $url = 'https://moku.cl/api/v1/vendors/vendor_demo_ceramica/products';
    $query = [
        'limit' => '1',
    ];
    $url .= '?' . http_build_query($query, '', '&', PHP_QUERY_RFC3986);
    $curl = curl_init($url);
    if ($curl === false) {
        throw new RuntimeException('curl_init');
    }
    curl_setopt_array($curl, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_CUSTOMREQUEST => 'GET',
        CURLOPT_CONNECTTIMEOUT => 10,
        CURLOPT_TIMEOUT => 30,
        CURLOPT_HTTPHEADER => [
            'Accept: application/json',
            'Authorization: Bearer ' . $token,
        ],
    ]);
    $response = curl_exec($curl);
    if ($response === false) {
        $message = curl_error($curl);
        curl_close($curl);
        throw new RuntimeException($message);
    }
    $status = curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
    curl_close($curl);
    $result = json_decode($response, false, 512, JSON_THROW_ON_ERROR);
    $failed = $status < 200 || $status >= 300;
    if ($failed) {
        fwrite(STDERR, "HTTP {$status}\n");
    }
    fwrite(
        $failed ? STDERR : STDOUT,
        json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR) . PHP_EOL
    );
    exit($failed ? 1 : 0);

    Respuesta 200 application/json

    {
      "data": [],
      "page": {
        "next_cursor": null
      }
    }
    Cómo leer la siguiente página

    Si page.next_cursor no es null, cópialo sin modificar al parámetro page_after de la misma colección y con el mismo token. La muestra usa un cursor ficticio: usa siempre el que te devuelva la API.

    Página siguiente de productos

    Solicitud · ejemplo ilustrativo

    cURL
    : "${MOKU_PAT:?}" &&
    curl --silent --show-error --fail-with-body \
      'https://moku.cl/api/v1/vendors/vendor_demo_ceramica/products' \
      --header "Authorization: Bearer ${MOKU_PAT}" \
      --header 'Accept: application/json' \
      --get \
      --data-urlencode 'limit=1' \
      --data-urlencode 'page_after=eyJ2IjoxLCJraW5kIjoicHJvZHVjdCIsInZlbmRvcklkIjoidmVuZG9yX2RlbW9fY2VyYW1pY2EiLCJwcm9kdWN0SWQiOiJwcm9kdWN0X2RlbW9fdGF6b24ifQ.KalmHw2-bJJUEJF6PFqDKKyNmWuniEUIYAG3mWI_TM4'
    PHP

    Ejemplo para PHP CLI con la extensión cURL. No es un plugin de WordPress ni debe ejecutarse en el navegador.

    <?php
    $token = getenv('MOKU_PAT');
    if ($token === false || $token === '') {
        throw new RuntimeException('MOKU_PAT');
    }
    
    $url = 'https://moku.cl/api/v1/vendors/vendor_demo_ceramica/products';
    $query = [
        'limit' => '1',
        'page_after' => 'eyJ2IjoxLCJraW5kIjoicHJvZHVjdCIsInZlbmRvcklkIjoidmVuZG9yX2RlbW9fY2VyYW1pY2EiLCJwcm9kdWN0SWQiOiJwcm9kdWN0X2RlbW9fdGF6b24ifQ.KalmHw2-bJJUEJF6PFqDKKyNmWuniEUIYAG3mWI_TM4',
    ];
    $url .= '?' . http_build_query($query, '', '&', PHP_QUERY_RFC3986);
    $curl = curl_init($url);
    if ($curl === false) {
        throw new RuntimeException('curl_init');
    }
    curl_setopt_array($curl, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_CUSTOMREQUEST => 'GET',
        CURLOPT_CONNECTTIMEOUT => 10,
        CURLOPT_TIMEOUT => 30,
        CURLOPT_HTTPHEADER => [
            'Accept: application/json',
            'Authorization: Bearer ' . $token,
        ],
    ]);
    $response = curl_exec($curl);
    if ($response === false) {
        $message = curl_error($curl);
        curl_close($curl);
        throw new RuntimeException($message);
    }
    $status = curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
    curl_close($curl);
    $result = json_decode($response, false, 512, JSON_THROW_ON_ERROR);
    $failed = $status < 200 || $status >= 300;
    if ($failed) {
        fwrite(STDERR, "HTTP {$status}\n");
    }
    fwrite(
        $failed ? STDERR : STDOUT,
        json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR) . PHP_EOL
    );
    exit($failed ? 1 : 0);

    Respuesta 200 application/json

    {
      "data": [
        {
          "id": "product_demo_vaso",
          "vendor_id": "vendor_demo_ceramica",
          "catalog_status": "active",
          "status": "published",
          "revision": 1,
          "kind": "simple",
          "name": "Vaso de greda",
          "slug": "vaso-de-greda",
          "description": "Vaso de greda hecho a mano.",
          "price": 12000,
          "original_price": null,
          "discount": 0,
          "category": "hogar",
          "subcategory": "ceramica",
          "image_urls": [
            "https://example.com/vaso-greda.jpg"
          ],
          "badge": null,
          "options": {},
          "default_options": null,
          "variations": [],
          "features": [
            "Hecho a mano"
          ],
          "related_product_ids": [],
          "tags": [
            "ceramica"
          ],
          "sku": "VAS-GREDA",
          "weight_kg": 0.3,
          "source_region": "metropolitana",
          "created_at": "2026-08-01T12:00:00.000Z",
          "updated_at": "2026-08-26T09:00:00.000Z",
          "published_at": "2026-08-01T12:00:00.000Z",
          "archived_at": null
        }
      ],
      "page": {
        "next_cursor": null
      }
    }

    Detente cuando el cursor sea null. Las páginas no son una foto inmutable: el catálogo puede cambiar entre lecturas; conserva los IDs y reconcilia diferencias.

    Ver campos y errores de listar productos

Del producto al stock

Sigue con una comparación de inventario sin escrituras. Después acuerda con el vendedor qué sistema será la fuente de verdad antes de habilitar cualquier cambio.

Seguir la guía de producto a stock →