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 Email
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:

  1. Primeira página: não envie cursor.
  2. Próximas páginas: use o valor de meta.next_cursor como parâmetro cursor.
  3. Fim: quando meta.has_more for false, 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_since para sincronização incremental.
  • Implemente retry com exponential backoff em erros 5xx.
  • Use cache quando apropriado, respeitando updatedAt.
  • Processe resultados em lotes por página.