SP SPACEPLACE
EXAMPLE #06 PHP Bash

Handle 401 / 403 / 422 / network

Production-grade error handling for every failure mode.

06-error-handling.php
#!/usr/bin/env php
<?php

/**
 * Example: Error handling for API responses
 *
 * Demonstrates how to handle the various error codes returned by the API:
 *   401 - Missing or invalid DataStream ID / Token value
 *   403 - Token is not provisioned for this endpoint
 *   422 - A field failed validation (updating an event, or the inventory
 *         endpoints; creating an event accepts any fields, so this call
 *         won't see one)
 *
 * Usage:
 *   php 06-error-handling.php
 */

$baseUrl       = 'https://www.spaceplace.app';
$dataStreamId  = 'YOUR-DATASTREAM-UUID-HERE';
$tokenValue    = 'YOUR-TOKEN-VALUE-HERE';

/**
 * Send an event and return the parsed result.
 *
 * @return array{success: bool, http_code: int, body: array}
 */
function sendEvent(string $baseUrl, string $dataStreamId, string $tokenValue, array $event): array
{
    $ch = curl_init("{$baseUrl}/api/events");
    curl_setopt_array($ch, [
        CURLOPT_POST           => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT        => 10,
        CURLOPT_HTTPHEADER     => [
            'Content-Type: application/json',
            'Accept: application/json',
            "X-DataStream-ID: {$dataStreamId}",
            "X-Token: {$tokenValue}",
        ],
        CURLOPT_POSTFIELDS => json_encode($event),
    ]);

    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $error    = curl_error($ch);
    curl_close($ch);

    if ($error) {
        return ['success' => false, 'http_code' => 0, 'body' => ['error' => "cURL: {$error}"]];
    }

    return [
        'success'   => $httpCode === 201,
        'http_code' => $httpCode,
        'body'      => json_decode($response, true) ?? ['raw' => $response],
    ];
}

// ── Send an event and handle all possible outcomes ───────────────────────────

$result = sendEvent($baseUrl, $dataStreamId, $tokenValue, [
    'number' => 1,
    'source' => 'error-handling-example',
    'key'    => 'test',
    'value'  => 'hello',
]);

switch ($result['http_code']) {
    case 201:
        echo "Success! Event ID: {$result['body']['event_id']}\n";
        break;

    case 401:
        // Missing credentials, invalid DataStream UUID, or unrecognised Token value
        echo "Authentication failed.\n";
        echo "Check that your DataStream UUID and Token value are correct.\n";
        echo "Server message: " . ($result['body']['error'] ?? $result['body']['message'] ?? 'none') . "\n";
        break;

    case 403:
        // Token exists but has no active Provision for this endpoint
        echo "Token is not provisioned for this endpoint.\n";
        echo "Ensure a Token Provision exists with:\n";
        echo "  - API Endpoints set to \"*\" or includes \"api/events\"\n";
        echo "  - StartDateTime in the past and EndDateTime in the future\n";
        echo "Server message: " . ($result['body']['error'] ?? $result['body']['message'] ?? 'none') . "\n";
        break;

    case 422:
        // Validation errors on the event fields
        echo "Validation error:\n";
        if (isset($result['body']['errors'])) {
            foreach ($result['body']['errors'] as $field => $messages) {
                echo "  {$field}: " . implode(', ', $messages) . "\n";
            }
        }
        break;

    case 0:
        echo "Connection error: {$result['body']['error']}\n";
        echo "Is the server running at {$baseUrl}?\n";
        break;

    default:
        echo "Unexpected response (HTTP {$result['http_code']}):\n";
        print_r($result['body']);
        break;
}
06-error-handling.sh
#!/usr/bin/env bash
#
# Example: Error handling for API responses
#
# Demonstrates how to handle the various error codes returned by the API:
#   401 - Missing or invalid DataStream ID / Token value
#   403 - Token is not provisioned for this endpoint
#   422 - A field failed validation (updating an event, or the inventory
#         endpoints; creating an event accepts any fields, so this call
#         won't see one)
#
# Usage:
#   bash 06-error-handling.sh

BASE_URL="https://www.spaceplace.app"
DATASTREAM_ID="YOUR-DATASTREAM-UUID-HERE"
TOKEN_VALUE="YOUR-TOKEN-VALUE-HERE"

send_event() {
  local payload="$1"

  response=$(curl -s -w "\n%{http_code}" --max-time 10 \
    -X POST "${BASE_URL}/api/events" \
    -H "Content-Type: application/json" \
    -H "Accept: application/json" \
    -H "X-DataStream-ID: ${DATASTREAM_ID}" \
    -H "X-Token: ${TOKEN_VALUE}" \
    -d "$payload" 2>&1)

  # Check for curl-level failure
  if [ $? -ne 0 ]; then
    echo "Connection error. Is the server running at ${BASE_URL}?"
    return 1
  fi

  http_code=$(echo "$response" | tail -n1)
  body=$(echo "$response" | sed '$d')

  case "$http_code" in
    201)
      echo "Success! Event ID: $(echo "$body" | jq -r '.event_id')"
      ;;
    401)
      echo "Authentication failed."
      echo "Check that your DataStream UUID and Token value are correct."
      echo "Server message: $(echo "$body" | jq -r '.error // .message // "none"')"
      return 1
      ;;
    403)
      echo "Token is not provisioned for this endpoint."
      echo "Ensure a Token Provision exists with:"
      echo "  - API Endpoints set to \"*\" or includes \"api/events\""
      echo "  - StartDateTime in the past and EndDateTime in the future"
      echo "Server message: $(echo "$body" | jq -r '.error // .message // "none"')"
      return 1
      ;;
    422)
      echo "Validation error:"
      echo "$body" | jq -r '.errors | to_entries[] | "  \(.key): \(.value | join(", "))"'
      return 1
      ;;
    *)
      echo "Unexpected response (HTTP ${http_code}):"
      echo "$body" | jq .
      return 1
      ;;
  esac
}

send_event '{
  "number": 1,
  "source": "error-handling-example",
  "key": "test",
  "value": "hello"
}'
← All examples