Complete guide to SSU Methods Transfer Analysis API
# Get all circles
curl -X GET "http://service.ssumethods.com/api/circles" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Accept: application/json"
# Get circles with filters
curl -X GET "http://service.ssumethods.com/api/circles?limit=10&min_amount=100&max_steps=4" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Accept: application/json"
# Get paginated results
curl -X GET "http://service.ssumethods.com/api/circles?page=2&limit=5" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Accept: application/json"
// Get all circles function
const getAllCircles = async (filters = {}) => {
try {
const token = localStorage.getItem('api_token');
if (!token) {
throw new Error('No authentication token found');
}
// Build query string from filters
const queryParams = new URLSearchParams();
Object.keys(filters).forEach(key => {
if (filters[key] !== null && filters[key] !== undefined) {
queryParams.append(key, filters[key]);
}
});
const url = `http://service.ssumethods.com/api/circles${queryParams.toString() ? '?' + queryParams.toString() : ''}`;
const response = await fetch(url, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
console.log('Circles retrieved:', data);
return data;
} catch (error) {
console.error('Error fetching circles:', error);
throw error;
}
};
// Usage examples
getAllCircles()
.then(result => {
console.log(`Found ${result.data.circles.length} circles`);
console.log(`Total amount: ${result.data.summary.total_amount}`);
});
// With filters
getAllCircles({
limit: 10,
min_amount: 100,
max_steps: 4,
page: 1
}).then(result => {
console.log('Filtered circles:', result.data.circles);
});
// Pagination example
const loadCirclesPage = async (page) => {
try {
const result = await getAllCircles({ page, limit: 10 });
return {
circles: result.data.circles,
hasNext: result.data.pagination.has_next,
totalPages: result.data.pagination.total_pages
};
} catch (error) {
console.error('Failed to load page:', error);
throw error;
}
};
import requests
from typing import Dict, Any, Optional
class CirclesAPI:
def __init__(self, base_url: str, token: str):
self.base_url = base_url
self.session = requests.Session()
self.session.headers.update({
'Authorization': f'Bearer {token}',
'Accept': 'application/json'
})
def get_all_circles(self, **filters) -> Dict[str, Any]:
"""Get all circles with optional filters"""
try:
# Remove None values from filters
params = {k: v for k, v in filters.items() if v is not None}
response = self.session.get(
f'{self.base_url}/api/circles',
params=params,
timeout=30
)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
print(f"API error: {e}")
raise
def get_circles_page(self, page: int = 1, limit: int = 20, **filters) -> Dict[str, Any]:
"""Get paginated circles"""
filters.update({'page': page, 'limit': limit})
return self.get_all_circles(**filters)
def get_filtered_circles(self,
min_amount: Optional[float] = None,
max_amount: Optional[float] = None,
min_steps: Optional[int] = None,
max_steps: Optional[int] = None,
limit: int = 20) -> Dict[str, Any]:
"""Get circles with specific filters"""
filters = {
'min_amount': min_amount,
'max_amount': max_amount,
'min_steps': min_steps,
'max_steps': max_steps,
'limit': limit
}
return self.get_all_circles(**filters)
# Usage example
try:
api = CirclesAPI('http://service.ssumethods.com', 'your_access_token_here')
# Get all circles
all_circles = api.get_all_circles()
print(f"Found {len(all_circles['data']['circles'])} circles")
print(f"Total amount: {all_circles['data']['summary']['total_amount']}")
# Get filtered circles
filtered = api.get_filtered_circles(
min_amount=100.0,
max_steps=4,
limit=10
)
for circle in filtered['data']['circles']:
print(f"Circle ID: {circle['id']}")
print(f"Steps: {circle['steps']}")
print(f"Amount: {circle['total_amount']}")
print("---")
# Pagination example
page = 1
while True:
result = api.get_circles_page(page=page, limit=5)
circles = result['data']['circles']
if not circles:
break
print(f"Page {page}: {len(circles)} circles")
if not result['data']['pagination']['has_next']:
break
page += 1
except Exception as e:
print(f"Error: {e}")
<?php
class CirclesAPI {
private $baseUrl;
private $token;
public function __construct($baseUrl, $token) {
$this->baseUrl = rtrim($baseUrl, '/');
$this->token = $token;
}
public function getAllCircles($filters = []) {
$url = $this->baseUrl . '/api/circles';
if (!empty($filters)) {
$url .= '?' . http_build_query($filters);
}
return $this->makeRequest($url);
}
public function getCirclesPage($page = 1, $limit = 20, $filters = []) {
$filters['page'] = $page;
$filters['limit'] = $limit;
return $this->getAllCircles($filters);
}
public function getFilteredCircles($minAmount = null, $maxAmount = null,
$minSteps = null, $maxSteps = null, $limit = 20) {
$filters = array_filter([
'min_amount' => $minAmount,
'max_amount' => $maxAmount,
'min_steps' => $minSteps,
'max_steps' => $maxSteps,
'limit' => $limit
], function($value) { return $value !== null; });
return $this->getAllCircles($filters);
}
private function makeRequest($url) {
$headers = [
'Authorization: Bearer ' . $this->token,
'Accept: application/json'
];
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_TIMEOUT => 30,
CURLOPT_SSL_VERIFYPEER => false
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($error) {
throw new Exception("cURL Error: " . $error);
}
$decodedResponse = json_decode($response, true);
if ($httpCode >= 400) {
$message = isset($decodedResponse['message']) ? $decodedResponse['message'] : 'Unknown error';
throw new Exception("HTTP Error $httpCode: " . $message);
}
return $decodedResponse;
}
}
// Usage example
try {
$api = new CirclesAPI('http://service.ssumethods.com', 'your_access_token_here');
// Get all circles
$allCircles = $api->getAllCircles();
echo "Found " . count($allCircles['data']['circles']) . " circles\n";
echo "Total amount: " . $allCircles['data']['summary']['total_amount'] . "\n";
// Get filtered circles
$filtered = $api->getFilteredCircles(
$minAmount = 100.0,
$maxAmount = null,
$minSteps = null,
$maxSteps = 4,
$limit = 10
);
foreach ($filtered['data']['circles'] as $circle) {
echo "Circle ID: " . $circle['id'] . "\n";
echo "Steps: " . $circle['steps'] . "\n";
echo "Amount: " . $circle['total_amount'] . "\n";
echo "---\n";
}
// Pagination example
$page = 1;
while (true) {
$result = $api->getCirclesPage($page, 5);
$circles = $result['data']['circles'];
if (empty($circles)) {
break;
}
echo "Page $page: " . count($circles) . " circles\n";
if (!$result['data']['pagination']['has_next']) {
break;
}
$page++;
}
} catch (Exception $e) {
echo "Error: " . $e->getMessage() . "\n";
}
?>
import java.io.IOException;
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;
public class CirclesAPI {
private final String baseUrl;
private final String token;
private final HttpClient httpClient;
private final ObjectMapper objectMapper;
public CirclesAPI(String baseUrl, String token) {
this.baseUrl = baseUrl.replaceAll("/$", "");
this.token = token;
this.httpClient = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(30))
.build();
this.objectMapper = new ObjectMapper();
}
public JsonNode getAllCircles() throws IOException, InterruptedException {
return getAllCircles(new HashMap<>());
}
public JsonNode getAllCircles(Map<String, Object> filters) throws IOException, InterruptedException {
String url = this.baseUrl + "/api/circles";
if (!filters.isEmpty()) {
String queryString = filters.entrySet().stream()
.filter(entry -> entry.getValue() != null)
.map(entry -> URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8) + "=" +
URLEncoder.encode(entry.getValue().toString(), StandardCharsets.UTF_8))
.collect(Collectors.joining("&"));
url += "?" + queryString;
}
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer " + this.token)
.header("Accept", "application/json")
.GET()
.timeout(Duration.ofSeconds(30))
.build();
HttpResponse<String> response = httpClient.send(
request,
HttpResponse.BodyHandlers.ofString()
);
if (response.statusCode() != 200) {
throw new RuntimeException("Request failed with HTTP " + response.statusCode() +
": " + response.body());
}
return objectMapper.readTree(response.body());
}
public JsonNode getCirclesPage(int page, int limit) throws IOException, InterruptedException {
Map<String, Object> filters = new HashMap<>();
filters.put("page", page);
filters.put("limit", limit);
return getAllCircles(filters);
}
public JsonNode getFilteredCircles(Double minAmount, Double maxAmount,
Integer minSteps, Integer maxSteps,
int limit) throws IOException, InterruptedException {
Map<String, Object> filters = new HashMap<>();
if (minAmount != null) filters.put("min_amount", minAmount);
if (maxAmount != null) filters.put("max_amount", maxAmount);
if (minSteps != null) filters.put("min_steps", minSteps);
if (maxSteps != null) filters.put("max_steps", maxSteps);
filters.put("limit", limit);
return getAllCircles(filters);
}
public static void main(String[] args) {
try {
CirclesAPI api = new CirclesAPI(
"http://service.ssumethods.com",
"your_access_token_here"
);
// Get all circles
JsonNode allCircles = api.getAllCircles();
JsonNode circles = allCircles.get("data").get("circles");
JsonNode summary = allCircles.get("data").get("summary");
System.out.println("Found " + circles.size() + " circles");
System.out.println("Total amount: " + summary.get("total_amount").asDouble());
// Get filtered circles
JsonNode filtered = api.getFilteredCircles(100.0, null, null, 4, 10);
JsonNode filteredCircles = filtered.get("data").get("circles");
for (JsonNode circle : filteredCircles) {
System.out.println("Circle ID: " + circle.get("id").asText());
System.out.println("Steps: " + circle.get("steps").asInt());
System.out.println("Amount: " + circle.get("total_amount").asDouble());
System.out.println("---");
}
// Pagination example
int page = 1;
while (true) {
JsonNode result = api.getCirclesPage(page, 5);
JsonNode pageCircles = result.get("data").get("circles");
if (pageCircles.size() == 0) {
break;
}
System.out.println("Page " + page + ": " + pageCircles.size() + " circles");
if (!result.get("data").get("pagination").get("has_next").asBoolean()) {
break;
}
page++;
}
} catch (Exception e) {
System.err.println("Error: " + e.getMessage());
e.printStackTrace();
}
}
}
package main
import (
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"strconv"
"strings"
"time"
)
type CirclesAPI struct {
BaseURL string
Token string
Client *http.Client
}
type CircleResponse struct {
Success bool `json:"success"`
Message string `json:"message"`
Data struct {
Circles []struct {
ID string `json:"id"`
Steps int `json:"steps"`
TotalAmount float64 `json:"total_amount"`
Participants []string `json:"participants"`
Path []struct {
From string `json:"from"`
To string `json:"to"`
Amount float64 `json:"amount"`
Date string `json:"date"`
} `json:"path"`
DetectedAt string `json:"detected_at"`
} `json:"circles"`
Pagination struct {
CurrentPage int `json:"current_page"`
PerPage int `json:"per_page"`
Total int `json:"total"`
TotalPages int `json:"total_pages"`
HasNext bool `json:"has_next"`
HasPrevious bool `json:"has_previous"`
} `json:"pagination"`
Summary struct {
TotalCircles int `json:"total_circles"`
TotalAmount float64 `json:"total_amount"`
AvgSteps float64 `json:"avg_steps"`
MaxSteps int `json:"max_steps"`
MinSteps int `json:"min_steps"`
} `json:"summary"`
} `json:"data"`
}
func NewCirclesAPI(baseURL, token string) *CirclesAPI {
return &CirclesAPI{
BaseURL: strings.TrimSuffix(baseURL, "/"),
Token: token,
Client: &http.Client{
Timeout: 30 * time.Second,
},
}
}
func (api *CirclesAPI) GetAllCircles(filters map[string]interface{}) (*CircleResponse, error) {
baseURL := api.BaseURL + "/api/circles"
// Build query parameters
if len(filters) > 0 {
params := url.Values{}
for key, value := range filters {
if value != nil {
params.Add(key, fmt.Sprintf("%v", value))
}
}
baseURL += "?" + params.Encode()
}
req, err := http.NewRequest("GET", baseURL, nil)
if err != nil {
return nil, fmt.Errorf("creating request: %w", err)
}
req.Header.Set("Authorization", "Bearer "+api.Token)
req.Header.Set("Accept", "application/json")
resp, err := api.Client.Do(req)
if err != nil {
return nil, fmt.Errorf("making request: %w", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("reading response: %w", err)
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("request failed with status %d: %s", resp.StatusCode, string(body))
}
var circleResp CircleResponse
if err := json.Unmarshal(body, &circleResp); err != nil {
return nil, fmt.Errorf("parsing response: %w", err)
}
return &circleResp, nil
}
func (api *CirclesAPI) GetCirclesPage(page, limit int, filters map[string]interface{}) (*CircleResponse, error) {
if filters == nil {
filters = make(map[string]interface{})
}
filters["page"] = page
filters["limit"] = limit
return api.GetAllCircles(filters)
}
func (api *CirclesAPI) GetFilteredCircles(minAmount, maxAmount *float64, minSteps, maxSteps *int, limit int) (*CircleResponse, error) {
filters := make(map[string]interface{})
if minAmount != nil {
filters["min_amount"] = *minAmount
}
if maxAmount != nil {
filters["max_amount"] = *maxAmount
}
if minSteps != nil {
filters["min_steps"] = *minSteps
}
if maxSteps != nil {
filters["max_steps"] = *maxSteps
}
filters["limit"] = limit
return api.GetAllCircles(filters)
}
func main() {
api := NewCirclesAPI("http://service.ssumethods.com", "your_access_token_here")
// Get all circles
allCircles, err := api.GetAllCircles(nil)
if err != nil {
fmt.Printf("Error getting circles: %v\n", err)
return
}
fmt.Printf("Found %d circles\n", len(allCircles.Data.Circles))
fmt.Printf("Total amount: %.2f\n", allCircles.Data.Summary.TotalAmount)
// Get filtered circles
minAmount := 100.0
maxSteps := 4
filtered, err := api.GetFilteredCircles(&minAmount, nil, nil, &maxSteps, 10)
if err != nil {
fmt.Printf("Error getting filtered circles: %v\n", err)
return
}
for _, circle := range filtered.Data.Circles {
fmt.Printf("Circle ID: %s\n", circle.ID)
fmt.Printf("Steps: %d\n", circle.Steps)
fmt.Printf("Amount: %.2f\n", circle.TotalAmount)
fmt.Println("---")
}
// Pagination example
page := 1
for {
result, err := api.GetCirclesPage(page, 5, nil)
if err != nil {
fmt.Printf("Error getting page %d: %v\n", page, err)
break
}
if len(result.Data.Circles) == 0 {
break
}
fmt.Printf("Page %d: %d circles\n", page, len(result.Data.Circles))
if !result.Data.Pagination.HasNext {
break
}
page++
}
}