curl --request GET \
--url https://core.api.dev.predictstreet.sde.adifoundation.ai/api/platform/maintenance \
--header 'X-Api-Key: <api-key>'import requests
url = "https://core.api.dev.predictstreet.sde.adifoundation.ai/api/platform/maintenance"
headers = {"X-Api-Key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-Api-Key': '<api-key>'}};
fetch('https://core.api.dev.predictstreet.sde.adifoundation.ai/api/platform/maintenance', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://core.api.dev.predictstreet.sde.adifoundation.ai/api/platform/maintenance",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-Api-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://core.api.dev.predictstreet.sde.adifoundation.ai/api/platform/maintenance"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-Api-Key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://core.api.dev.predictstreet.sde.adifoundation.ai/api/platform/maintenance")
.header("X-Api-Key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://core.api.dev.predictstreet.sde.adifoundation.ai/api/platform/maintenance")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-Api-Key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"windows": [
{
"id": "<string>",
"scope": "trading",
"status": "scheduled",
"title": "<string>",
"message": "<string>",
"startsAt": "2023-11-07T05:31:56Z",
"expectedEndAt": "2023-11-07T05:31:56Z",
"startedAt": "2023-11-07T05:31:56Z",
"endedAt": "2023-11-07T05:31:56Z"
}
],
"from": "2023-11-07T05:31:56Z",
"generatedAt": "2023-11-07T05:31:56Z"
}{
"status": 404,
"error": {
"code": "<string>",
"message": "<string>",
"trace_id": "<string>",
"retryAfterSec": 123,
"retryable": true,
"details": {}
}
}{
"status": 404,
"error": {
"code": "<string>",
"message": "<string>",
"trace_id": "<string>",
"retryAfterSec": 123,
"retryable": true,
"details": {}
}
}{
"status": 404,
"error": {
"code": "<string>",
"message": "<string>",
"trace_id": "<string>",
"retryAfterSec": 123,
"retryable": true,
"details": {}
}
}{
"status": 404,
"error": {
"code": "<string>",
"message": "<string>",
"trace_id": "<string>",
"retryAfterSec": 123,
"retryable": true,
"details": {}
}
}{
"status": 404,
"error": {
"code": "<string>",
"message": "<string>",
"trace_id": "<string>",
"retryAfterSec": 123,
"retryable": true,
"details": {}
}
}List maintenance windows
Upcoming and active maintenance windows, plus any that finished after from. This is the SCHEDULE — use it to stop trading before an outage rather than during it; GET /api/platform/status answers “is it down right now”.
Requires a partner API key in X-Api-Key, one issued when you were onboarded. No scope is needed, and no X-User-Wallet header. A self-service key minted from a retail account is refused with 403 partner_key_required, and a signed-in user session (Authorization: Bearer) with 403 api_key_required_not_jwt. Where the feature is not switched on, the endpoint answers 404 not_found.
Poll incrementally by passing generatedAt back as from — not the from you sent, and not your own clock. generatedAt sits about a minute behind the moment the data was read, so a completion or cancellation that was mid-commit when we read still reaches you on the next poll; you will therefore see windows you already have for up to a minute after they change, so upsert by id.
Three behaviours worth coding against: a running window stays listed after expectedEndAt passes (overrunning is when you most need it — drive logic off status, never off the clock); a window announced but never started stays listed as scheduled until its expectedEndAt passes and then disappears, so treat a scheduled window missing from a response as gone; and a window that has started is never cancelled — after in_progress the only status that follows is completed.
Rate limit: 600 requests per minute per partner (all of your keys share it; it scales with your rate tier) plus 600 per minute per IP. These are its own buckets, separate from the one the other /api/platform/* routes share. Cache-Control: private, max-age=5.
curl --request GET \
--url https://core.api.dev.predictstreet.sde.adifoundation.ai/api/platform/maintenance \
--header 'X-Api-Key: <api-key>'import requests
url = "https://core.api.dev.predictstreet.sde.adifoundation.ai/api/platform/maintenance"
headers = {"X-Api-Key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-Api-Key': '<api-key>'}};
fetch('https://core.api.dev.predictstreet.sde.adifoundation.ai/api/platform/maintenance', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://core.api.dev.predictstreet.sde.adifoundation.ai/api/platform/maintenance",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-Api-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://core.api.dev.predictstreet.sde.adifoundation.ai/api/platform/maintenance"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-Api-Key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://core.api.dev.predictstreet.sde.adifoundation.ai/api/platform/maintenance")
.header("X-Api-Key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://core.api.dev.predictstreet.sde.adifoundation.ai/api/platform/maintenance")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-Api-Key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"windows": [
{
"id": "<string>",
"scope": "trading",
"status": "scheduled",
"title": "<string>",
"message": "<string>",
"startsAt": "2023-11-07T05:31:56Z",
"expectedEndAt": "2023-11-07T05:31:56Z",
"startedAt": "2023-11-07T05:31:56Z",
"endedAt": "2023-11-07T05:31:56Z"
}
],
"from": "2023-11-07T05:31:56Z",
"generatedAt": "2023-11-07T05:31:56Z"
}{
"status": 404,
"error": {
"code": "<string>",
"message": "<string>",
"trace_id": "<string>",
"retryAfterSec": 123,
"retryable": true,
"details": {}
}
}{
"status": 404,
"error": {
"code": "<string>",
"message": "<string>",
"trace_id": "<string>",
"retryAfterSec": 123,
"retryable": true,
"details": {}
}
}{
"status": 404,
"error": {
"code": "<string>",
"message": "<string>",
"trace_id": "<string>",
"retryAfterSec": 123,
"retryable": true,
"details": {}
}
}{
"status": 404,
"error": {
"code": "<string>",
"message": "<string>",
"trace_id": "<string>",
"retryAfterSec": 123,
"retryable": true,
"details": {}
}
}{
"status": 404,
"error": {
"code": "<string>",
"message": "<string>",
"trace_id": "<string>",
"retryAfterSec": 123,
"retryable": true,
"details": {}
}
}Authorizations
Partner / integrator key — format ps_live_<keyId>_<secret>. Partner keys are issued by PredictStreet; a user can also create keys bound to their own wallet from their account settings in the web app. Never ship to a browser. multi_wallet partners must additionally send X-User-Wallet: 0x<40-hex> on every authenticated request to declare the acting wallet. See the API keys guide for scope taxonomy, partner kinds, rate limits, and rotation procedure.
Query Parameters
Return windows still relevant at this instant: everything live, plus anything that finished after it. Defaults to now, which gives upcoming + active. Must be a form with separators — 2026-10-11T02:00:00Z, not 20261011. Prefer Z; if you send an offset, URL-encode the + (%2B).
Asking for trading or withdrawals ALSO returns all windows, because an all window takes that surface down too. Asking for all returns full-platform windows only. Omit for every surface.
trading, withdrawals, all Response
OK
Oldest start first.
Show child attributes
Show child attributes
The filter applied to THIS request, echoed for debugging. Do not use it as your cursor — use generatedAt.
Your cursor for the next request: pass it back as from. About a minute behind the moment the data was read, so a completion or cancellation that was mid-commit at the read still reaches you next time. The overlap means you will be shown windows you already have for up to a minute after they change — upsert by id.