Subscrições
Consulta de subscrições da MetCare com dados do utilizador e plano de saúde associados.
Resumo
| Item | Valor |
|---|---|
| Endpoint | GET /v1/subscriptions |
| Autenticação | Bearer token |
| Paginação | Cursor-based (limit, cursor) |
| Filtro | updated_since (RFC3339) |
URLs: Sandbox — https://integration.met-care.com/sandbox/v1/subscriptions · Produção — https://integration.met-care.com/v1/subscriptions
Token: solicitar em developers@met-care.com.
Referência do endpoint
Parâmetros de query
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
limit |
integer | Não | Registos por página (1–500; padrão: 100) |
cursor |
string | Não | Cursor para a próxima página (da resposta anterior) |
updated_since |
string (RFC3339) | Não | Apenas subscrições atualizadas desde esta data |
Exemplo de requisição (cURL)
# Produção
curl -X GET "https://integration.met-care.com/v1/subscriptions?limit=50&updated_since=2026-01-01T00:00:00Z" \
-H "Authorization: Bearer YOUR_TOKEN"
# Sandbox
curl -X GET "https://integration.met-care.com/sandbox/v1/subscriptions?limit=50" \
-H "Authorization: Bearer YOUR_TOKEN"
Resposta de sucesso (200)
{
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"userId": 12345,
"tutorId": 67890,
"aggregateId": "AGG-2026-001",
"status": "active",
"statusDate": "2026-01-10T08:00:00Z",
"statusReason": "payment_confirmed",
"statusNotes": "Subscription activated",
"contractDuration": 12,
"healthPlanId": "plan-premium-001",
"startDate": "2026-01-01T00:00:00Z",
"endDate": "2026-12-31T23:59:59Z",
"pricePaid": 29990,
"createdAt": "2024-12-15T10:00:00Z",
"updatedAt": "2026-01-10T08:00:00Z",
"type": "monthly",
"user": {
"id": 12345,
"name": "Manuel Costa",
"phone": "+244912345678",
"email": "manuel.costa@exemplo.ao",
"birthday": "1990-05-15T00:00:00Z",
"identity": "00012345678",
"identity_type": "BI",
"nif": "123456789",
"gender": "male",
"active": true,
"identity_expire_date": "2030-05-15T00:00:00Z",
"registration_source": "web"
},
"plan": {
"id": "550e8400-e29b-41d4-a716-446655440001",
"name": "Plano Premium",
"description": "Plano de saúde premium com cobertura completa",
"photo": "https://cdn.metcare.com/plans/premium.jpg",
"price": 29990,
"type": "premium",
"level": "gold"
}
}
],
"meta": {
"limit": 50,
"has_more": true,
"next_cursor": "eyJ1cGRhdGVkQXQiOiIyMDI1LTAxLTEwVDA4OjAwOjAwWiIsImlkIjoiNTUwZTg0MDAtZTI5Yi00MWQ0LWE3MTYtNDQ2NjU1NDQwMDAwIn0"
},
"links": {
"self": "/v1/subscriptions?limit=50&updated_since=2026-01-01T00:00:00Z",
"next": "/v1/subscriptions?limit=50&updated_since=...&cursor=..."
}
}
Exemplos com dados angolanos: telefone +244, valores em Kz (Kwanza), documento BI.
Campos da resposta
Objeto Subscription
| Campo | Tipo | Descrição |
|---|---|---|
id |
UUID | Identificador único da subscrição |
userId |
integer | ID do utilizador |
tutorId |
integer | ID do tutor (se aplicável) |
aggregateId |
string | Identificador agregado |
status |
string | Estado (active, suspended, cancelled, etc.) |
statusDate |
datetime (RFC3339) | Data da última alteração de estado |
statusReason |
string | Razão da alteração de estado |
statusNotes |
string | Notas sobre o estado |
contractDuration |
integer | Duração do contrato (meses) |
healthPlanId |
string | ID do plano de saúde |
startDate, endDate |
datetime (RFC3339) | Início e fim da subscrição |
pricePaid |
float | Preço pago (ex.: Kz) |
createdAt, updatedAt |
datetime (RFC3339) | Criação e última atualização |
type |
string | Tipo de subscrição |
Objeto User (dentro de cada subscrição)
| Campo | Tipo | Descrição |
|---|---|---|
id |
integer | ID do cliente |
name |
string | Nome completo |
phone |
string | Telefone (ex.: +244 912 345 678) |
email |
string | |
birthday |
datetime (RFC3339) | Data de nascimento |
identity |
string | Número de identificação |
identity_type |
string | Documento (ex.: BI) |
nif |
string | NIF angolano |
gender |
string | male, female, unknown |
active |
boolean | Utilizador ativo |
identity_expire_date |
datetime (RFC3339) | Validade do documento |
registration_source |
string | Origem do registo |
Objeto Plan
| Campo | Tipo | Descrição |
|---|---|---|
id |
UUID | ID do plano |
name |
string | Nome do plano |
description |
string | Descrição |
photo |
string (URL) | URL da foto |
price |
float | Preço (ex.: Kz) |
type |
string | Tipo do plano |
level |
string | Nível do plano |
Paginação
A API usa paginação por cursor:
- Primeira página: não envie
cursor. - Próximas páginas: use o valor de
meta.next_cursorcomo parâmetrocursor. - Fim: quando
meta.has_moreforfalse, não há mais páginas.
Exemplo de navegação:
GET .../v1/subscriptions?limit=50
GET .../v1/subscriptions?limit=50&cursor=<next_cursor da resposta anterior>
Filtro por data
Use updated_since em formato RFC3339 para obter apenas subscrições atualizadas desde uma data (sincronização incremental).
Exemplo: GET .../v1/subscriptions?updated_since=2026-01-01T00:00:00Z
Exemplos de integração
BASE_URL: Produção — https://integration.met-care.com/v1 · Sandbox — https://integration.met-care.com/sandbox/v1
JavaScript
const BASE_URL = 'https://integration.met-care.com/v1';
const API_TOKEN = 'YOUR_TOKEN';
async function listSubscriptions(cursor = null, updatedSince = null) {
const url = new URL(`${BASE_URL}/subscriptions`);
url.searchParams.set('limit', '50');
if (cursor) url.searchParams.set('cursor', cursor);
if (updatedSince) url.searchParams.set('updated_since', updatedSince);
const response = await fetch(url, {
headers: {
'Authorization': `Bearer ${API_TOKEN}`,
'Content-Type': 'application/json'
}
});
return response.json();
}
let cursor = null;
do {
const result = await listSubscriptions(cursor);
console.log('Subscriptions:', result.data);
cursor = result.meta?.next_cursor;
} while (result.meta?.has_more);
PHP
<?php
$baseUrl = 'https://integration.met-care.com/v1';
$apiToken = 'YOUR_TOKEN';
function listSubscriptions($baseUrl, $apiToken, $cursor = null, $updatedSince = null) {
$params = ['limit' => 50];
if ($cursor) $params['cursor'] = $cursor;
if ($updatedSince) $params['updated_since'] = $updatedSince;
$url = $baseUrl . '/subscriptions?' . http_build_query($params);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiToken,
'Content-Type: application/json'
]
]);
$response = curl_exec($ch);
curl_close($ch);
return json_decode($response, true);
}
$cursor = null;
do {
$result = listSubscriptions($baseUrl, $apiToken, $cursor);
foreach ($result['data'] ?? [] as $sub) echo $sub['id'] . ' - ' . $sub['status'] . "\n";
$cursor = $result['meta']['next_cursor'] ?? null;
} while (!empty($result['meta']['has_more']));
Python
import requests
BASE_URL = 'https://integration.met-care.com/v1'
API_TOKEN = 'YOUR_TOKEN'
def list_subscriptions(cursor=None, updated_since=None):
params = {'limit': 50}
if cursor: params['cursor'] = cursor
if updated_since: params['updated_since'] = updated_since
r = requests.get(
f'{BASE_URL}/subscriptions',
params=params,
headers={'Authorization': f'Bearer {API_TOKEN}', 'Content-Type': 'application/json'}
)
r.raise_for_status()
return r.json()
cursor = None
while True:
result = list_subscriptions(cursor=cursor)
for sub in result['data']:
print(f"{sub['id']} - {sub['status']}")
if not result.get('meta', {}).get('has_more'):
break
cursor = result['meta']['next_cursor']
Códigos de erro
| HTTP | Código de erro | Descrição |
|---|---|---|
| 200 | — | Sucesso |
| 400 | VALIDATION_ERROR |
Parâmetro inválido (ex.: limit fora de 1–500) |
| 400 | BAD_REQUEST |
Requisição inválida (cursor ou data inválidos) |
| 401 | — | Não autenticado |
| 403 | — | Não autorizado |
| 500 | — | Erro interno do servidor |
Exemplo de erro:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "limit must be an integer between 1 and 500"
}
}
Limites e boas práticas
- Máximo
limit: 500 · Recomendado: 50–100 -
Rate limit: 1000 requisições/minuto por cliente
-
Use sempre paginação; evite obter todos os registos de uma vez.
- Use
updated_sincepara sincronização incremental. - Implemente retry com exponential backoff em erros 5xx.
- Use cache quando apropriado, respeitando
updatedAt. - Processe resultados em lotes por página.