πŸ“¦Delivery rFBS API

Regional FBS delivery management and status tracking

βœ… Implementation Complete
πŸ“…

Delivery Scheduling

Set cutoff dates and manage delivery timeslots

πŸ“¦

Status Management

Track delivery lifecycle with precise updates

πŸ”

Tracking Integration

Add and manage tracking numbers

πŸ•’

Timeslot Control

Reschedule deliveries with availability checking

πŸ“š ΠšΠ°Ρ‚Π΅Π³ΠΎΡ€ΠΈΠΈ πŸ“‘ ИндСкс API πŸš€ Быстрый старт ❓ FAQ

πŸ“‹ Methods Overview - 8 Endpoints

πŸ“…
Scheduling & Timing
3 methods
setCutoff - Set posting shipment cutoff date
getTimeslotChangeRestrictions - Get rescheduling availability
setTimeslot - Reschedule delivery date
πŸ“¦
Status Management
4 methods
setSentBySeller - Change to "Sent by seller"
setDelivering - Change to "Delivering"
setLastMile - Change to "Last mile"
setDelivered - Change to "Delivered"
πŸ”
Tracking
1 method
setTrackingNumbers - Add tracking numbers to postings

πŸ”„ Complete rFBS Delivery Lifecycle

⏰

Set Cutoff

Schedule shipment deadline

β†’
πŸ“€

Sent by Seller

Package leaves facility

β†’
πŸš›

Delivering

Out for delivery

β†’
πŸ“

Last Mile

Final delivery stage

β†’
βœ…

Delivered

Package received

// Complete rFBS Delivery Lifecycle
async function completeRfbsDeliveryLifecycle(postingNumber: string) {
  try {
    // Step 1: Set cutoff date for shipment
    const cutoff = await deliveryRfbsApi.setCutoff({
      posting_number: postingNumber,
      cutoff_at: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString() // +1 day
    });
    
    if (cutoff.result !== 'success') {
      throw new Error(`Cutoff setting failed: ${cutoff.error}`);
    }
    
    // Step 2: Add tracking number
    const tracking = await deliveryRfbsApi.setTrackingNumbers({
      tracking_numbers: [{
        posting_number: postingNumber,
        tracking_number: `TRACK${Date.now()}`,
        delivery_service: 'CDEK'
      }]
    });
    
    const trackingResult = tracking.results?.[0];
    if (trackingResult?.result !== 'success') {
      throw new Error(`Tracking number failed: ${trackingResult?.error}`);
    }
    
    // Step 3: Status progression with delays
    const statusUpdates = [
      { method: 'setSentBySeller', timestamp: Date.now() },
      { method: 'setDelivering', timestamp: Date.now() + 2 * 24 * 60 * 60 * 1000 }, // +2 days
      { method: 'setLastMile', timestamp: Date.now() + 4 * 24 * 60 * 60 * 1000 }, // +4 days
      { method: 'setDelivered', timestamp: Date.now() + 5 * 24 * 60 * 60 * 1000 } // +5 days
    ];
    
    for (const update of statusUpdates) {
      const result = await deliveryRfbsApi[update.method]({
        posting_number: postingNumber,
        [`${update.method.replace('set', '').toLowerCase()}_at`]: new Date(update.timestamp).toISOString()
      });
      
      if (result.result !== 'success') {
        console.warn(`Status update ${update.method} failed: ${result.error}`);
      } else {
        console.log(`βœ… ${update.method} completed`);
      }
    }
    
    return {
      status: 'completed',
      postingNumber,
      trackingNumber: trackingResult.tracking_number
    };
    
  } catch (error) {
    console.error('rFBS delivery lifecycle failed:', error);
    throw error;
  }
}

πŸ•’ Smart Delivery Rescheduling

Interactive Rescheduling Example

Check available dates and reschedule deliveries intelligently

Jan 25
Jan 26
Jan 27
Jan 28
Jan 29
Remaining Reschedules: 2/3
// Smart Delivery Rescheduling
async function smartDeliveryRescheduling(postingNumber: string, preferredDate?: string) {
  try {
    // Check rescheduling availability
    const restrictions = await deliveryRfbsApi.getTimeslotChangeRestrictions({
      posting_number: postingNumber
    });
    
    const availableDates = restrictions.restrictions?.available_dates ?? [];
    const remainingReschedules = restrictions.restrictions?.available_reschedules ?? 0;
    
    if (remainingReschedules <= 0) {
      throw new Error('No reschedules remaining for this posting');
    }
    
    if (availableDates.length === 0) {
      throw new Error('No available dates for rescheduling');
    }
    
    // Select optimal date
    let selectedDate = preferredDate;
    
    // If preferred date is not available, select the earliest available
    if (!selectedDate || !availableDates.includes(selectedDate)) {
      selectedDate = availableDates.sort()[0];
      console.log(`Preferred date not available. Selected: ${selectedDate}`);
    }
    
    // Perform rescheduling
    const result = await deliveryRfbsApi.setTimeslot({
      posting_number: postingNumber,
      timeslot_date: selectedDate
    });
    
    if (result.result !== 'success') {
      throw new Error(`Rescheduling failed: ${result.error}`);
    }
    
    return {
      success: true,
      originalPreference: preferredDate,
      actualDate: result.new_timeslot_date,
      remainingReschedules: remainingReschedules - 1
    };
    
  } catch (error) {
    console.error('Smart rescheduling failed:', error);
    return {
      success: false,
      error: error.message
    };
  }
}

πŸ”‘ Key Method Examples

πŸ“… Scheduling Methods

// Set cutoff date
const cutoffResult = await deliveryRfbsApi.setCutoff({
  posting_number: 'FBS-123456789',
  cutoff_at: '2024-01-15T10:00:00Z'
});

// Check rescheduling availability
const restrictions = await deliveryRfbsApi.getTimeslotChangeRestrictions({
  posting_number: 'FBS-123456789'
});

console.log('Available dates:', restrictions.restrictions?.available_dates);
console.log('Remaining reschedules:', restrictions.restrictions?.available_reschedules);

// Reschedule delivery
const rescheduleResult = await deliveryRfbsApi.setTimeslot({
  posting_number: 'FBS-123456789',
  timeslot_date: '2024-01-25'
});

if (rescheduleResult.result === 'success') {
  console.log('New delivery date:', rescheduleResult.new_timeslot_date);
}

πŸ“¦ Status Management

// Update status to "Sent by seller"
const sentResult = await deliveryRfbsApi.setSentBySeller({
  posting_number: 'FBS-123456789',
  sent_by_seller_at: '2024-01-15T12:00:00Z'
});

// Update status to "Delivering"
const deliveringResult = await deliveryRfbsApi.setDelivering({
  posting_number: 'FBS-123456789',
  delivering_at: '2024-01-18T09:00:00Z'
});

// Update status to "Delivered"
const deliveredResult = await deliveryRfbsApi.setDelivered({
  posting_number: 'FBS-123456789',
  delivered_at: '2024-01-20T15:30:00Z'
});

if (deliveredResult.result === 'success') {
  console.log('Delivery completed:', deliveredResult.status);
}

πŸ” Tracking Numbers

// Add tracking numbers to multiple postings
const trackingResult = await deliveryRfbsApi.setTrackingNumbers({
  tracking_numbers: [
    {
      posting_number: 'FBS-123456789',
      tracking_number: 'TRACK123456',
      delivery_service: 'CDEK'
    },
    {
      posting_number: 'FBS-987654321',
      tracking_number: 'TRACK789012',
      delivery_service: 'Russian Post'
    },
    {
      posting_number: 'FBS-555666777',
      tracking_number: 'TRACK345678',
      delivery_service: 'DPD'
    }
  ]
});

// Process results
trackingResult.results?.forEach(res => {
  if (res.result === 'success') {
    console.log(`βœ… ${res.posting_number}: Tracking ${res.tracking_number} added`);
  } else {
    console.error(`❌ ${res.posting_number}: ${res.error}`);
  }
});

const successful = trackingResult.results?.filter(r => r.result === 'success').length ?? 0;
const failed = trackingResult.results?.filter(r => r.result === 'error').length ?? 0;
console.log(`Summary: ${successful} successful, ${failed} failed`);

🎯 Best Practices

Status Progression Validation

Ensure proper status transitions and validate current state before updates.

const VALID_STATUS_TRANSITIONS = {
  'awaiting_packaging': ['sent_by_seller'],
  'sent_by_seller': ['delivering'],
  'delivering': ['last_mile'],
  'last_mile': ['delivered']
};

function validateStatusTransition(currentStatus: string, newStatus: string): boolean {
  const validNext = VALID_STATUS_TRANSITIONS[currentStatus] || [];
  return validNext.includes(newStatus);
}

async function safeStatusUpdate(
  postingNumber: string, 
  newStatus: string, 
  timestamp: string,
  currentStatus?: string
) {
  if (currentStatus && !validateStatusTransition(currentStatus, newStatus)) {
    throw new Error(`Invalid status transition from ${currentStatus} to ${newStatus}`);
  }
  
  const methodMap = {
    sent_by_seller: 'setSentBySeller',
    delivering: 'setDelivering',
    last_mile: 'setLastMile',
    delivered: 'setDelivered'
  };
  
  const method = methodMap[newStatus];
  if (!method) {
    throw new Error(`Unsupported status: ${newStatus}`);
  }
  
  return await deliveryRfbsApi[method]({
    posting_number: postingNumber,
    [`${newStatus}_at`]: timestamp
  });
}
Error Recovery with Exponential Backoff

Implement resilient tracking updates with retry logic and exponential backoff.

async function resilientTrackingUpdate(postingNumber: string, trackingNumber: string, deliveryService: string) {
  const maxRetries = 3;
  let lastError;
  
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const result = await deliveryRfbsApi.setTrackingNumbers({
        tracking_numbers: [{
          posting_number: postingNumber,
          tracking_number: trackingNumber,
          delivery_service: deliveryService
        }]
      });
      
      const trackingResult = result.results?.[0];
      if (trackingResult?.result === 'success') {
        return trackingResult;
      }
      
      lastError = trackingResult?.error || 'Unknown error';
      
    } catch (error) {
      lastError = error.message;
    }
    
    if (attempt < maxRetries) {
      const delay = Math.pow(2, attempt) * 1000; // Exponential backoff
      console.log(`Attempt ${attempt} failed, retrying in ${delay}ms...`);
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
  
  throw new Error(`Failed after ${maxRetries} attempts. Last error: ${lastError}`);
}

πŸ“Š API Endpoints Reference

Method Endpoint Description
πŸ“… Scheduling & Timing
POST setCutoff /v1/posting/cutoff/set Set shipment cutoff date
POST getTimeslotChangeRestrictions /v1/posting/fbs/timeslot/change-restrictions Get rescheduling availability
POST setTimeslot /v1/posting/fbs/timeslot/set Reschedule delivery date
πŸ“¦ Status Management
POST setSentBySeller /v2/fbs/posting/sent-by-seller Set "Sent by seller" status
POST setDelivering /v2/fbs/posting/delivering Set "Delivering" status
POST setLastMile /v2/fbs/posting/last-mile Set "Last mile" status
POST setDelivered /v2/fbs/posting/delivered Set "Delivered" status
πŸ” Tracking
POST setTrackingNumbers /v2/fbs/posting/tracking-number/set Add tracking numbers