POST /api/v1/user/login
Headers
| Header | Required | Notes |
|---|---|---|
x-api-key | yes | Your API key |
x-timestamp | yes | Unix seconds, current ±5 min |
x-signature | yes | HMAC-SHA256(${timestamp}.${encrypted_body}, HMAC secret) |
content-type | yes | application/json |
Request body
{ "data": "<aes-256-gcm encrypted blob of the payload below>" }
| Field | Type | Required | Notes |
|---|---|---|---|
email | string | yes | The owner email on the consumer account |
password | string | yes | The owner’s password |
Example request
The snippets below assume you’ve already encrypted the body and computed the signature — see the Quickstart for the full helper in Node and Python.
const login = await call('/api/v1/user/login', {
email: 'you@example.com',
password: 'YOUR_PASSWORD',
})
status, body = call('/api/v1/user/login', {
'email': 'you@example.com',
'password': 'YOUR_PASSWORD',
})
curl -X POST "https://api.pontisglobe.com/api/v1/user/login" \
-H "content-type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-H "x-timestamp: 1748023400" \
-H "x-signature: 2f8a9b…" \
-d '{"data":"<encrypted blob>"}'
req, _ := http.NewRequest("POST",
"https://api.pontisglobe.com/api/v1/user/login",
strings.NewReader(`{"data":"`+encryptedBody+`"}`))
req.Header.Set("content-type", "application/json")
req.Header.Set("x-api-key", apiKey)
req.Header.Set("x-timestamp", timestamp)
req.Header.Set("x-signature", signature)
res, _ := http.DefaultClient.Do(req)
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://api.pontisglobe.com/api/v1/user/login"))
.header("content-type", "application/json")
.header("x-api-key", apiKey)
.header("x-timestamp", timestamp)
.header("x-signature", signature)
.POST(HttpRequest.BodyPublishers.ofString("{\"data\":\"" + encryptedBody + "\"}"))
.build();
HttpResponse<String> res = HttpClient.newHttpClient().send(req, BodyHandlers.ofString());
val req = Request.Builder()
.url("https://api.pontisglobe.com/api/v1/user/login")
.post("""{"data":"$encryptedBody"}""".toRequestBody("application/json".toMediaType()))
.addHeader("x-api-key", apiKey)
.addHeader("x-timestamp", timestamp)
.addHeader("x-signature", signature)
.build()
val res = OkHttpClient().newCall(req).execute()
$ch = curl_init('https://api.pontisglobe.com/api/v1/user/login');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'content-type: application/json',
"x-api-key: $apiKey",
"x-timestamp: $timestamp",
"x-signature: $signature",
],
CURLOPT_POSTFIELDS => json_encode(['data' => $encryptedBody]),
CURLOPT_RETURNTRANSFER => true,
]);
$res = curl_exec($ch);
uri = URI('https://api.pontisglobe.com/api/v1/user/login')
req = Net::HTTP::Post.new(uri, {
'content-type' => 'application/json',
'x-api-key' => api_key,
'x-timestamp' => timestamp,
'x-signature' => signature,
})
req.body = { data: encrypted_body }.to_json
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
var req = new HttpRequestMessage(HttpMethod.Post,
"https://api.pontisglobe.com/api/v1/user/login");
req.Headers.Add("x-api-key", apiKey);
req.Headers.Add("x-timestamp", timestamp);
req.Headers.Add("x-signature", signature);
req.Content = new StringContent($"{{\"data\":\"{encryptedBody}\"}}",
Encoding.UTF8, "application/json");
var res = await new HttpClient().SendAsync(req);
var req = URLRequest(url: URL(string: "https://api.pontisglobe.com/api/v1/user/login")!)
req.httpMethod = "POST"
req.setValue("application/json", forHTTPHeaderField: "content-type")
req.setValue(apiKey, forHTTPHeaderField: "x-api-key")
req.setValue(timestamp, forHTTPHeaderField: "x-timestamp")
req.setValue(signature, forHTTPHeaderField: "x-signature")
req.httpBody = #"{"data":"\#(encryptedBody)"}"#.data(using: .utf8)
let (data, _) = try await URLSession.shared.data(for: req)
Responses
200 — Success
{
"ok": true,
"data": {
"access_token": "eyJhbGciOi...",
"token_type": "Bearer",
"expires_in": 900
}
}
access_token as Authorization: Bearer <token> on subsequent requests.
401 — unauthorized
Wrong email/password, or account suspended.{
"ok": false,
"request_id": "01J9F5Z4X7Y3K2B1Q0M8N7V6T5",
"error": {
"code": "unauthorized",
"message": "Invalid credentials. Make sure the email, password, and API key all belong to the same user account."
}
}
429 — rate_limited
Too many login attempts (scoped per consumer + mode).{
"ok": false,
"request_id": "01J9F5Z4X7Y3K2B1Q0M8N7V6T5",
"error": { "code": "rate_limited", "message": "Too many login attempts. Try again later." }
}
500 — internal_error
Account misconfiguration — contact support withrequest_id.
See Errors for the full envelope shape and full code list.