원클릭으로
european-parliament-api
EU Parliament open data API integration, MEP data, voting records, committee data for cross-parliament analysis
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
EU Parliament open data API integration, MEP data, voting records, committee data for cross-parliament analysis
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Identity and access management: RBAC, least privilege, MFA, quarterly reviews per ISO 27001 A.5.15, A.8.2, A.8.3
Business continuity and disaster recovery: 30-day retention, quarterly restore tests, RTO/RPO targets per ISO 27001 A.17
Political psychology, cognitive biases, group dynamics, leadership analysis, decision-making patterns for Swedish political intelligence
Risk-based data and asset classification framework: PUBLIC, INTERNAL, CONFIDENTIAL, RESTRICTED aligned with ISO 27001 A.5.12 and CIA triad
Unified compliance verification across ISO 27001, NIST CSF, CIS Controls, NIS2, EU CRA, GDPR, SOC 2, PCI DSS, and HIPAA for cybersecurity consulting
Cryptographic controls implementation: TLS 1.3, AES-256-GCM, bcrypt, RSA-4096, key management per NIST FIPS 140-2 and ISO 27001 A.8.24
| name | european-parliament-api |
| description | EU Parliament open data API integration, MEP data, voting records, committee data for cross-parliament analysis |
| license | Apache-2.0 |
This skill provides integration guidance for the European Parliament's open data APIs, enabling the CIA platform to perform cross-parliament analysis between the Swedish Riksdag and the EU Parliament. It covers MEP data retrieval, plenary voting records, committee information, and legislative document tracking.
Apply this skill when:
Do NOT use for:
EU Parliament Open Data Ecosystem
│
├─ European Parliament Open Data Portal
│ ├─ URL: https://data.europarl.europa.eu/
│ ├─ Format: RDF/SPARQL, JSON-LD, CSV
│ └─ License: CC BY 4.0
│
├─ Plenary Data (Votes, Debates)
│ ├─ Roll-call votes by session
│ ├─ Debate transcripts
│ └─ Attendance records
│
├─ MEP Data
│ ├─ Current and former MEPs
│ ├─ Political group membership
│ ├─ Committee assignments
│ └─ Contact information
│
├─ Legislative Data
│ ├─ Legislative procedures (COD, CNS, APP)
│ ├─ Committee reports and opinions
│ ├─ Amendments and resolutions
│ └─ Interinstitutional negotiations
│
└─ Parliamentary Questions
├─ Written questions
├─ Oral questions
└─ Priority questions
@Service
public class EuropeanParliamentApiClient {
private static final String BASE_URL = "https://data.europarl.europa.eu/api/v2";
private static final Duration TIMEOUT = Duration.ofSeconds(30);
private static final int MAX_RETRIES = 3;
private final RestTemplate restTemplate;
public EuropeanParliamentApiClient(RestTemplateBuilder builder) {
this.restTemplate = builder
.setConnectTimeout(TIMEOUT)
.setReadTimeout(TIMEOUT)
.defaultHeader("Accept", "application/json")
.build();
}
/**
* Retrieve current MEPs with retry logic.
*/
public List<MepData> getCurrentMeps() {
String url = BASE_URL + "/meps?filter=current&format=json";
return executeWithRetry(() -> {
ResponseEntity<MepListResponse> response =
restTemplate.getForEntity(url, MepListResponse.class);
return response.getBody().getMeps();
});
}
/**
* Retrieve voting records for a specific plenary session.
*/
public List<VoteRecord> getPlenaryVotes(String sessionId) {
String url = BASE_URL + "/plenary-sessions/" + sessionId + "/votes";
return executeWithRetry(() -> {
ResponseEntity<VoteListResponse> response =
restTemplate.getForEntity(url, VoteListResponse.class);
return response.getBody().getVotes();
});
}
private <T> T executeWithRetry(Supplier<T> operation) {
int attempts = 0;
while (attempts < MAX_RETRIES) {
try {
return operation.get();
} catch (RestClientException e) {
attempts++;
if (attempts >= MAX_RETRIES) throw e;
try {
// Use TimeUnit for clarity; consider ScheduledExecutorService for non-blocking retries
TimeUnit.SECONDS.sleep((long) Math.pow(2, attempts));
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
throw new RuntimeException(ie);
}
}
}
throw new RuntimeException("Max retries exceeded");
}
}
@Entity
@Table(name = "eu_mep_data")
public class MepData {
@Id
@Column(name = "mep_id")
private String mepId;
@Column(name = "full_name")
private String fullName;
@Column(name = "country")
private String country; // "SE" for Swedish MEPs
@Column(name = "political_group")
private String politicalGroup;
@Column(name = "national_party")
private String nationalParty;
@Column(name = "active")
private boolean active;
@Column(name = "start_date")
private LocalDate startDate;
@Column(name = "end_date")
private LocalDate endDate;
}
@Entity
@Table(name = "eu_vote_record")
public class EuVoteRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "session_id")
private String sessionId;
@Column(name = "vote_date")
private LocalDate voteDate;
@Column(name = "subject")
private String subject;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "mep_id")
private MepData mep;
@Enumerated(EnumType.STRING)
@Column(name = "vote_position")
private VotePosition position; // FOR, AGAINST, ABSTAIN, ABSENT
}
Swedish MEP Analysis Dimensions
│
├─ Voting Alignment
│ ├─ Swedish MEP votes vs national party line
│ ├─ Swedish MEP votes vs EU political group
│ └─ Deviation analysis (party loyalty metric)
│
├─ Committee Participation
│ ├─ Swedish MEP committee assignments
│ ├─ Report authorship frequency
│ ├─ Amendment submission rate
│ └─ Attendance in committee meetings
│
├─ Legislative Influence
│ ├─ Rapporteur appointments
│ ├─ Shadow rapporteur roles
│ ├─ Negotiation mandates
│ └─ Successful amendments ratio
│
└─ Cross-Parliament Correlation
├─ EU legislation impact on Swedish law
├─ Swedish Riksdag debates on EU matters
├─ Transposition compliance tracking
└─ Swedish positions in Council vs MEP votes
@Repository
public interface MepRepository extends JpaRepository<MepData, String> {
// Find all Swedish MEPs (current)
@Query("SELECT m FROM MepData m WHERE m.country = 'SE' AND m.active = true")
List<MepData> findActiveSwedishMeps();
// Find Swedish MEPs by national party
@Query("SELECT m FROM MepData m WHERE m.country = 'SE' " +
"AND m.nationalParty = :party AND m.active = true")
List<MepData> findSwedishMepsByParty(@Param("party") String party);
// Voting record for a specific MEP
@Query("SELECT v FROM EuVoteRecord v WHERE v.mep.mepId = :mepId " +
"AND v.voteDate BETWEEN :startDate AND :endDate " +
"ORDER BY v.voteDate DESC")
List<EuVoteRecord> findVotesByMepAndPeriod(
@Param("mepId") String mepId,
@Param("startDate") LocalDate startDate,
@Param("endDate") LocalDate endDate);
}
@Service
public class EuParliamentImportService {
private static final Logger LOG =
LoggerFactory.getLogger(EuParliamentImportService.class);
@Autowired
private EuropeanParliamentApiClient apiClient;
@Autowired
private MepRepository mepRepository;
/**
* Import MEP data daily at 02:00 UTC.
* EU Parliament data updates are typically published overnight.
*/
@Scheduled(cron = "0 0 2 * * *")
@Transactional
public void importMepData() {
LOG.info("Starting EU Parliament MEP data import");
try {
List<MepData> meps = apiClient.getCurrentMeps();
int imported = 0;
for (MepData mep : meps) {
mepRepository.save(mep);
imported++;
}
LOG.info("Imported {} MEP records", imported);
} catch (Exception e) {
LOG.error("MEP import failed", e);
// Alert via CloudWatch alarm
}
}
}
// Circuit breaker for EU Parliament API
@Service
public class ResilientEuParliamentClient {
private final AtomicInteger failureCount = new AtomicInteger(0);
private static final int FAILURE_THRESHOLD = 5;
private volatile Instant circuitOpenedAt;
public <T> Optional<T> callWithCircuitBreaker(Supplier<T> apiCall) {
if (isCircuitOpen()) {
LOG.warn("Circuit breaker OPEN for EU Parliament API");
return Optional.empty();
}
try {
T result = apiCall.get();
failureCount.set(0); // Reset on success
return Optional.of(result);
} catch (Exception e) {
if (failureCount.incrementAndGet() >= FAILURE_THRESHOLD) {
circuitOpenedAt = Instant.now();
LOG.error("Circuit breaker OPENED after {} failures", FAILURE_THRESHOLD);
}
return Optional.empty();
}
}
private boolean isCircuitOpen() {
if (circuitOpenedAt == null) return false;
// Auto-reset after 5 minutes
return Duration.between(circuitOpenedAt, Instant.now()).toMinutes() < 5;
}
}
| Data Type | Cache Duration | Reason |
|---|---|---|
| MEP profiles | 24 hours | Changes rarely, daily import |
| Plenary votes | 1 week | Immutable after session ends |
| Committee data | 12 hours | Updates with meeting schedules |
| Legislative docs | 6 hours | Active procedures change frequently |
| Session calendar | 1 month | Published well in advance |
EU Parliament Data and GDPR:
├─ MEP public data: Legitimate interest (public figure, Art. 6(1)(f))
├─ Voting records: Public document (Art. 6(1)(e))
├─ Contact details: Only official/public information
├─ Personal data: Never collect private MEP data
└─ Data retention: Archive per parliamentary term
Module Integration Points
│
├─ model.external.riksdagen → Cross-reference Swedish party data
├─ service.external.riksdagen → Compare Riksdag votes with EU votes
├─ service.data.api → Shared data access patterns
├─ web-widgets → EU Parliament views and dashboards
└─ citizen-intelligence-agency → Configuration and routing