curl --request PUT \
--url https://app.stockshift.io/api/v1/apps/push-token \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"token": "7d1c2a4f0b6e9c3d8a5f2e1b4c7d0a9e6f3b8c5d2a1e4f7b0c3d6e9a2f5b8c1d"
}
'import requests
url = "https://app.stockshift.io/api/v1/apps/push-token"
payload = { "token": "7d1c2a4f0b6e9c3d8a5f2e1b4c7d0a9e6f3b8c5d2a1e4f7b0c3d6e9a2f5b8c1d" }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.stockshift.io/api/v1/apps/push-token",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'token' => '7d1c2a4f0b6e9c3d8a5f2e1b4c7d0a9e6f3b8c5d2a1e4f7b0c3d6e9a2f5b8c1d'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.stockshift.io/api/v1/apps/push-token"
payload := strings.NewReader("{\n \"token\": \"7d1c2a4f0b6e9c3d8a5f2e1b4c7d0a9e6f3b8c5d2a1e4f7b0c3d6e9a2f5b8c1d\"\n}")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"code": "<string>",
"detail": "<string>",
"errors": {},
"feature": "<string>",
"reason": "<string>",
"attempts_left": 123,
"rule_ids": [
"<string>"
],
"witness": "<string>",
"blind_recount": true,
"flags": [
{
"flag": "<string>",
"facts": {},
"choices": [
"<string>"
]
}
]
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"code": "<string>",
"detail": "<string>",
"errors": {},
"feature": "<string>",
"reason": "<string>",
"attempts_left": 123,
"rule_ids": [
"<string>"
],
"witness": "<string>",
"blind_recount": true,
"flags": [
{
"flag": "<string>",
"facts": {},
"choices": [
"<string>"
]
}
]
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"code": "<string>",
"detail": "<string>",
"errors": {},
"feature": "<string>",
"reason": "<string>",
"attempts_left": 123,
"rule_ids": [
"<string>"
],
"witness": "<string>",
"blind_recount": true,
"flags": [
{
"flag": "<string>",
"facts": {},
"choices": [
"<string>"
]
}
]
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"code": "<string>",
"detail": "<string>",
"errors": {},
"feature": "<string>",
"reason": "<string>",
"attempts_left": 123,
"rule_ids": [
"<string>"
],
"witness": "<string>",
"blind_recount": true,
"flags": [
{
"flag": "<string>",
"facts": {},
"choices": [
"<string>"
]
}
]
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"code": "<string>",
"detail": "<string>",
"errors": {},
"feature": "<string>",
"reason": "<string>",
"attempts_left": 123,
"rule_ids": [
"<string>"
],
"witness": "<string>",
"blind_recount": true,
"flags": [
{
"flag": "<string>",
"facts": {},
"choices": [
"<string>"
]
}
]
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"code": "<string>",
"detail": "<string>",
"errors": {},
"feature": "<string>",
"reason": "<string>",
"attempts_left": 123,
"rule_ids": [
"<string>"
],
"witness": "<string>",
"blind_recount": true,
"flags": [
{
"flag": "<string>",
"facts": {},
"choices": [
"<string>"
]
}
]
}Registra el token push de la app que llama
Guarda el token que APNs o FCM dio a la app, para que el servidor pueda avisar al dispositivo de que cambió un feed o de que hay un bloqueo, un borrado o un cierre de sesión pendiente. Una notificación push lleva solo IDs, y la app obtiene el resto. El dispositivo tiene un solo token: envía uno nuevo cada vez que la plataforma lo rote. El token de acceso debe ser uno emitido a una app; cualquier otro responde 404. El cambio queda registrado en el historial de auditoría, sin el token push.
curl --request PUT \
--url https://app.stockshift.io/api/v1/apps/push-token \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"token": "7d1c2a4f0b6e9c3d8a5f2e1b4c7d0a9e6f3b8c5d2a1e4f7b0c3d6e9a2f5b8c1d"
}
'import requests
url = "https://app.stockshift.io/api/v1/apps/push-token"
payload = { "token": "7d1c2a4f0b6e9c3d8a5f2e1b4c7d0a9e6f3b8c5d2a1e4f7b0c3d6e9a2f5b8c1d" }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.stockshift.io/api/v1/apps/push-token",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'token' => '7d1c2a4f0b6e9c3d8a5f2e1b4c7d0a9e6f3b8c5d2a1e4f7b0c3d6e9a2f5b8c1d'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.stockshift.io/api/v1/apps/push-token"
payload := strings.NewReader("{\n \"token\": \"7d1c2a4f0b6e9c3d8a5f2e1b4c7d0a9e6f3b8c5d2a1e4f7b0c3d6e9a2f5b8c1d\"\n}")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"code": "<string>",
"detail": "<string>",
"errors": {},
"feature": "<string>",
"reason": "<string>",
"attempts_left": 123,
"rule_ids": [
"<string>"
],
"witness": "<string>",
"blind_recount": true,
"flags": [
{
"flag": "<string>",
"facts": {},
"choices": [
"<string>"
]
}
]
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"code": "<string>",
"detail": "<string>",
"errors": {},
"feature": "<string>",
"reason": "<string>",
"attempts_left": 123,
"rule_ids": [
"<string>"
],
"witness": "<string>",
"blind_recount": true,
"flags": [
{
"flag": "<string>",
"facts": {},
"choices": [
"<string>"
]
}
]
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"code": "<string>",
"detail": "<string>",
"errors": {},
"feature": "<string>",
"reason": "<string>",
"attempts_left": 123,
"rule_ids": [
"<string>"
],
"witness": "<string>",
"blind_recount": true,
"flags": [
{
"flag": "<string>",
"facts": {},
"choices": [
"<string>"
]
}
]
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"code": "<string>",
"detail": "<string>",
"errors": {},
"feature": "<string>",
"reason": "<string>",
"attempts_left": 123,
"rule_ids": [
"<string>"
],
"witness": "<string>",
"blind_recount": true,
"flags": [
{
"flag": "<string>",
"facts": {},
"choices": [
"<string>"
]
}
]
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"code": "<string>",
"detail": "<string>",
"errors": {},
"feature": "<string>",
"reason": "<string>",
"attempts_left": 123,
"rule_ids": [
"<string>"
],
"witness": "<string>",
"blind_recount": true,
"flags": [
{
"flag": "<string>",
"facts": {},
"choices": [
"<string>"
]
}
]
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"code": "<string>",
"detail": "<string>",
"errors": {},
"feature": "<string>",
"reason": "<string>",
"attempts_left": 123,
"rule_ids": [
"<string>"
],
"witness": "<string>",
"blind_recount": true,
"flags": [
{
"flag": "<string>",
"facts": {},
"choices": [
"<string>"
]
}
]
}Autorizaciones
Cómo inician sesión las apps de StockShift. La app abre /apps/authorize en el navegador del sistema con un desafío PKCE S256 y la huella de su llave de dispositivo. El miembro inicia sesión allí, con todas las comprobaciones que aplica la web. El navegador devuelve un código a la app, que lo canjea en POST /apps/token con el verificador PKCE y una prueba DPoP (RFC 9449) firmada por la llave del dispositivo. La respuesta incluye un token de acceso de una hora, que se envía como token bearer en cada llamada, y un token de actualización rotativo de 30 días. Una actualización necesita una prueba DPoP con el último nonce del servidor, así que un token de actualización robado no sirve sin la llave del dispositivo. Una sesión termina como máximo 180 días después de iniciar sesión. Cada solicitud de la app lleva StockShift-Client: / (), como ios/1.4.2 (311). Por debajo del mínimo de GET /apps/version-policy, una llamada recibe la respuesta 426 client_upgrade_required con el mínimo y el enlace a la tienda. Por debajo de la versión deprecated-below funciona y la respuesta añade StockShift-Client-Deprecated: sunset=; minimum=. Iniciar y cerrar sesión, el estado del dispositivo, el acuse de borrado y las llamadas de bloqueo por PIN, y la política de versiones responden a cualquier versión.
Cuerpo
El token push que una app obtuvo de APNs o FCM.
El token de dispositivo de APNs (hex) o el token de registro de FCM, tal como lo dio la plataforma.
4096^[A-Za-z0-9_:\-]+$"7d1c2a4f0b6e9c3d8a5f2e1b4c7d0a9e6f3b8c5d2a1e4f7b0c3d6e9a2f5b8c1d"
Qué servidores de APNs reconocen el token: sandbox para una app de iOS o macOS compilada desde Xcode y, en otro caso, production, el valor predeterminado.
production Los servidores de producción de APNs, para apps de la App Store o TestFlight, y todos los tokens de FCM. |
sandbox Los servidores sandbox de APNs, para apps compiladas desde Xcode. |
production, sandbox Respuesta
Sin contenido
¿Esta página le ayudó?