{"openapi":"3.0.3","info":{"title":"Data Connect GH \u2014 Console API v2","version":"2.0.0","description":"Public HTTP API for console integrations. Send header `x-api-key` on every request. Each response carries an `X-Request-Id` header \u2014 quote it in support tickets so we can trace your call across our logs.\n\n## API key format\nNewly issued keys are prefixed `dcgh_live_` for leak-detection by tools like GitHub secret scanning. Pre-prefix keys (40 hex chars only) continue to work \u2014 the hash is independent of the format.\n\n## Idempotency\nThe two write endpoints (`POST \/api\/v2\/packages\/buy` and `POST \/api\/v2\/packages\/buy-bulk`) accept an optional `Idempotency-Key` header (16\u2013128 chars). Retries within 24 hours with the same key return the cached response \u2014 no double-charge. Strongly recommended on every state-changing call from automated clients.\n\n## Rate limiting\nDefault: 60 requests \/ minute per API key (server-side bucket keyed by `api_key_id`, not your IP). Per-key limits can be raised in your admin console. On exhaustion the API returns `429 Too Many Requests`.\n\n## Deprecated endpoints (v1)\nThe `\/api\/v1\/*` surface is **deprecated** and will be removed on **2027-05-14**. All v1 responses carry standard `Deprecation: true` and `Sunset` headers, plus a `Link: <successor-url>; rel=\"successor-version\"` pointing at v2. Migrate at your own pace before the sunset date. (The following v1 routes were removed in May 2026 because they had no implementation and returned 500: `buy-ishare-package`, `buy-multiple-ishare-package`, `fetch-ishare-transactions`, `fetch-other-network-transactions`, `fetch-ishare-transaction`, `geo\/{orderId}`.)\n\n## Outbound webhooks\nWhen an order item's `status` or `api_status` changes for a console order, the system POSTs JSON to the **webhook URL** configured on your API key (admin Console). If no URL is set, nothing is sent.\n\n**Headers** (verify in this order on the receiver):\n- `X-DataConnectGH-Event`: e.g. `order.status_updated`\n- `X-DataConnectGH-Timestamp`: Unix seconds \u2014 reject requests > 300s skew from wall-clock\n- `X-DataConnectGH-Signature`: `hex( hmac-sha256( webhook_secret, timestamp + \".\" + body ) )` \u2014 compare with `hash_equals`\n\n**Payload (JSON):** `event`, `order_item_id`, `order_code`, `msisdn`, `network`, `volume_mb`, `status`, `api_status`, `price`, `timestamp` (ISO 8601).\n\n**Retry policy:** non-2xx responses trigger up to 5 retries with exponential backoff (30s, 2min, 10min, 1h, 6h). After exhaustion the delivery appears in the admin Webhook Failures dashboard for manual retry."},"tags":[{"name":"ConsoleV2","description":"Console API v2 (`\/api\/v2`)"}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"x-api-key","description":"Format: `dcgh_live_<40 hex chars>` for keys minted after 2026-05-14; legacy keys are 40 hex chars without prefix and still work."}},"parameters":{"IdempotencyKey":{"name":"Idempotency-Key","in":"header","schema":{"type":"string","minLength":16,"maxLength":128},"description":"Optional. A unique client-generated string (16\u2013128 chars, e.g. a UUID v4). Retries with the same key within 24h return the original response. Strongly recommended."},"RequestId":{"name":"X-Request-Id","in":"header","schema":{"type":"string","maxLength":64},"description":"Optional. Inbound correlation ID \u2014 echoed back in the response. If omitted the server mints a UUID. Quote in support tickets."}},"headers":{"XRequestId":{"description":"Per-request correlation ID echoed by the server. Quote in support tickets to trace the call across our logs.","schema":{"type":"string"}}},"schemas":{"BuySingleBody":{"type":"object","required":["recipient_msisdn","network_id"],"properties":{"recipient_msisdn":{"type":"string","pattern":"^0[0-9]{9}$","example":"0541234567"},"network_id":{"type":"integer"},"shared_bundle":{"type":"number","description":"Package `volume` value from fetchPackages"},"volume_mb":{"type":"number","description":"Alias for `shared_bundle`"}}},"BuyBulkBody":{"type":"object","required":["network_id","recipients"],"properties":{"network_id":{"type":"integer"},"recipients":{"type":"array","items":{"type":"object","required":["msisdn","volume_mb"],"properties":{"msisdn":{"type":"string","pattern":"^0[0-9]{9}$"},"volume_mb":{"type":"integer","minimum":1}}}}}}}},"security":[{"ApiKeyAuth":[]}],"paths":{"\/api\/v2\/networks":{"get":{"operationId":"fetchNetworks","tags":["ConsoleV2"],"summary":"List networks","parameters":[{"$ref":"#\/components\/parameters\/RequestId"}],"responses":{"200":{"description":"JSON array of networks","headers":{"X-Request-Id":{"$ref":"#\/components\/headers\/XRequestId"}}},"401":{"description":"Missing or invalid API key"},"429":{"description":"Rate limit exceeded"}}}},"\/api\/v2\/packages":{"get":{"operationId":"fetchPackages","tags":["ConsoleV2"],"summary":"List packages","parameters":[{"name":"network_id","in":"query","schema":{"type":"integer"},"description":"If set, only packages for this network"},{"$ref":"#\/components\/parameters\/RequestId"}],"responses":{"200":{"description":"Package list","headers":{"X-Request-Id":{"$ref":"#\/components\/headers\/XRequestId"}}},"404":{"description":"No packages"},"429":{"description":"Rate limit exceeded"}}}},"\/api\/v2\/packages\/buy":{"post":{"operationId":"BuySinglePackage","tags":["ConsoleV2"],"summary":"Purchase one package","parameters":[{"$ref":"#\/components\/parameters\/IdempotencyKey"},{"$ref":"#\/components\/parameters\/RequestId"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/BuySingleBody"}}}},"responses":{"200":{"description":"Success","headers":{"X-Request-Id":{"$ref":"#\/components\/headers\/XRequestId"}}},"400":{"description":"Validation or business error"},"403":{"description":"Network not in API key scopes"},"409":{"description":"Duplicate same-day order for this msisdn + package"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Idempotency lock contention \u2014 retry shortly"}}}},"\/api\/v2\/packages\/buy-bulk":{"post":{"operationId":"BuyBulkPackages","tags":["ConsoleV2"],"summary":"Purchase many recipients in one request","parameters":[{"$ref":"#\/components\/parameters\/IdempotencyKey"},{"$ref":"#\/components\/parameters\/RequestId"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/BuyBulkBody"}}}},"responses":{"202":{"description":"Accepted \u2014 partial rejects may appear in `rejected`","headers":{"X-Request-Id":{"$ref":"#\/components\/headers\/XRequestId"}}},"400":{"description":"Validation or business error"},"403":{"description":"Network not in API key scopes"},"429":{"description":"Rate limit exceeded"},"503":{"description":"Idempotency lock contention \u2014 retry shortly"}}}}},"servers":[{"url":"https:\/\/smconnect.researchershubgh.com","description":"Application base"}]}