API Mobile do Gastometria
A API Mobile do Gastometria permite integrar seu aplicativo Flutter (ou qualquer cliente HTTP) com a plataforma.
Requisito: Esta API está disponível exclusivamente para usuários do plano Infinity.
Base URL
Desenvolvimento: http://localhost:9002/api/mobile
Produção: https://seu-dominio.vercel.app/api/mobile
Autenticação
A API utiliza autenticação JWT (Bearer Token).
Fluxo de Autenticação
- Faça login com
/api/mobile/loginpara obter tokens - Use o
accessTokenno headerAuthorization: Bearer {token} - Quando expirar, use
/api/mobile/refreshcom orefreshToken
Endpoints
POST /api/mobile/login
Autentica o usuário e retorna tokens JWT.
Request:
{
"email": "usuario@email.com",
"password": "senha123"
}
Response (200):
{
"user": {
"id": "abc123",
"email": "usuario@email.com",
"displayName": "João Silva",
"plan": "Infinity",
"aiCredits": 500
},
"tokens": {
"accessToken": "eyJhbGc...",
"refreshToken": "eyJhbGc...",
"expiresIn": 3600
}
}
Erros:
400- Email ou senha não fornecidos401- Credenciais inválidas403- Plano não é Infinity (API Mobile requer Infinity)
POST /api/mobile/refresh
Renova o access token usando o refresh token.
Request:
{
"refreshToken": "eyJhbGc..."
}
Response (200):
{
"accessToken": "eyJhbGc...",
"expiresIn": 3600
}
Erros:
400- Refresh token não fornecido401- Refresh token inválido ou expirado403- Plano não é mais Infinity
GET /api/mobile/me
Retorna os dados do usuário autenticado.
Headers:
Authorization: Bearer {accessToken}
Response (200):
{
"user": {
"id": "abc123",
"email": "usuario@email.com",
"displayName": "João Silva",
"plan": "Infinity",
"aiCredits": 500
}
}
Erros:
401- Token não fornecido ou inválido403- Plano não é Infinity
Uso no Flutter
import 'dart:convert';
import 'package:http/http.dart' as http;
class GastometriaApi {
static const String baseUrl = 'https://gastometria.vercel.app/api/mobile';
String? _accessToken;
String? _refreshToken;
Future<bool> login(String email, String password) async {
final response = await http.post(
Uri.parse('$baseUrl/login'),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'email': email, 'password': password}),
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
_accessToken = data['tokens']['accessToken'];
_refreshToken = data['tokens']['refreshToken'];
return true;
}
return false;
}
Future<Map<String, dynamic>?> getMe() async {
final response = await http.get(
Uri.parse('$baseUrl/me'),
headers: {
'Authorization': 'Bearer $_accessToken',
'Content-Type': 'application/json',
},
);
if (response.statusCode == 200) {
return jsonDecode(response.body);
}
return null;
}
Future<bool> refreshToken() async {
final response = await http.post(
Uri.parse('$baseUrl/refresh'),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'refreshToken': _refreshToken}),
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
_accessToken = data['accessToken'];
return true;
}
return false;
}
}
Segurança
- Tokens JWT: Access token expira em 1 hora, refresh token em 7 dias
- Plano obrigatório: Apenas usuários Infinity têm acesso
- Re-verificação: O plano é verificado em cada request
- HTTPS: Sempre use HTTPS em produção
Limitações
- Rate limiting: 100 requests/minuto por IP
- Tamanho máximo de payload: 4MB
- Tokens não são transferíveis entre dispositivos
Próximos Endpoints (Em Desenvolvimento)
GET /api/mobile/transactions- Listar transaçõesPOST /api/mobile/transactions- Criar transaçãoGET /api/mobile/wallets- Listar carteirasGET /api/mobile/budgets- Listar orçamentos