Product Import via Supplier API

Our company is engaged in the development, support and maintenance of sites of any complexity. From simple one-page sites to large-scale cluster systems built on micro services. Experience of developers is confirmed by certificates from vendors.
Development and maintenance of all types of websites:
Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Showing 1 of 1 servicesAll 2065 services
Product Import via Supplier API
Medium
~5 business days
FAQ
Our competencies:
Development stages
Latest works
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1041
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    822
  • image_crm_chasseurs_493_0.webp
    CRM development for Chasseurs
    847
  • image_website-sbh_0.png
    Website development for SBH Partners
    999
  • image_website-_0.png
    Website development for Red Pear
    451

Implementing Product Import via Supplier API

API import from supplier is most flexible and current way to get data. Instead of file exports, data taken directly from supplier system on schedule or event. Complexity: each supplier has own API with different auth formats, response structures, pagination models.

Supplier API Types

Type Example Features
REST JSON Most modern Pagination cursor/offset, JWT/API-key
REST XML Old systems (1C) Need XML parser response
SOAP Corporate ERP WSDL, SOAPClient
GraphQL Rare Flexible field selection
oData SAP, Microsoft $filter, $top, $skip

Basic Client with Retry and Rate Limiting

class SupplierApiClient
{
    private \GuzzleHttp\Client $http;
    private RateLimiter        $rateLimiter;

    public function __construct(
        private SupplierApiConfig $config,
    ) {
        $this->http = new \GuzzleHttp\Client([
            'base_uri' => $config->baseUrl,
            'timeout'  => 30,
            'handler'  => $this->buildHandlerStack(),
        ]);
    }

    private function buildHandlerStack(): \GuzzleHttp\HandlerStack
    {
        $stack = \GuzzleHttp\HandlerStack::create();
        $stack->push(\GuzzleHttp\Middleware::retry(
            function (int $retries, $request, $response, $exception) {
                if ($retries >= 3) return false;
                if ($exception instanceof \GuzzleHttp\Exception\ConnectException) return true;
                if ($response && $response->getStatusCode() >= 500) return true;
                return false;
            },
            fn(int $retries) => 1000 * (2 ** $retries) // exponential backoff
        ));
        return $stack;
    }

    public function get(string $path, array $params = []): array
    {
        // Rate limiting: not more than N requests per second
        $this->rateLimiter->throttle($this->config->id, $this->config->rateLimit);

        $response = $this->http->get($path, [
            'query'   => $params,
            'headers' => $this->buildHeaders(),
        ]);

        return json_decode($response->getBody(), true);
    }

    private function buildHeaders(): array
    {
        return match ($this->config->authType) {
            'bearer' => ['Authorization' => 'Bearer ' . $this->config->token],
            'api_key' => ['X-API-Key' => $this->config->apiKey],
            'basic'   => ['Authorization' => 'Basic ' . base64_encode(
                $this->config->login . ':' . $this->config->password
            )],
            default => [],
        };
    }
}

Pagination Models

Offset Pagination

public function fetchAllProducts(): iterable
{
    $page    = 1;
    $perPage = 100;

    do {
        $response = $this->client->get('/products', [
            'page'     => $page,
            'per_page' => $perPage,
        ]);

        foreach ($response['data'] as $item) {
            yield $item;
        }

        $hasMore = count($response['data']) === $perPage;
        $page++;
    } while ($hasMore);
}

Cursor Pagination (efficient for large tables)

public function fetchAllProducts(): iterable
{
    $cursor = null;

    do {
        $params   = ['limit' => 200];
        if ($cursor) $params['cursor'] = $cursor;

        $response = $this->client->get('/v2/products', $params);

        foreach ($response['items'] as $item) {
            yield $item;
        }

        $cursor = $response['next_cursor'] ?? null;
    } while ($cursor);
}

OAuth 2.0 Authorization

Some suppliers require OAuth 2.0 client credentials:

class OAuth2TokenProvider
{
    private ?string $accessToken  = null;
    private ?int    $expiresAt    = null;

    public function getToken(): string
    {
        if ($this->accessToken && time() < ($this->expiresAt - 60)) {
            return $this->accessToken;
        }

        $response = Http::asForm()->post($this->tokenUrl, [
            'grant_type'    => 'client_credentials',
            'client_id'     => $this->clientId,
            'client_secret' => $this->clientSecret,
            'scope'         => 'products:read stocks:read',
        ]);

        $data               = $response->json();
        $this->accessToken  = $data['access_token'];
        $this->expiresAt    = time() + $data['expires_in'];

        return $this->accessToken;
    }
}

Incremental Synchronization

Most valuable mode — get only changes since last sync:

public function fetchUpdatedSince(\DateTimeInterface $since): iterable
{
    return $this->fetchAllProducts([
        'updated_after' => $since->format(DATE_ATOM),
        'fields'        => 'sku,price,qty,name,description',
    ]);
}

Implementation Timeline

  • One REST supplier, offset pagination, normalization, import — 2 days
  • OAuth 2.0, cursor pagination, incremental sync — +1 day
  • Multi-supplier via config, SOAP, rate limiting, retry — +2 days