This guide covers machine-to-machine writes from partner systems (for example, cesam-la.pt) into Legaciti.
Base URL
Section titled “Base URL”https://api.legaciti.org
Authentication Model
Section titled “Authentication Model”Partner writes use scoped API keys in the X-API-Key header.
- Keys are provisioned by Legaciti operators in dashboard site-tools.
- Keys are stored hashed server-side.
- Each key has explicit scopes.
- Rate limiting is applied per key.
Supported Scopes
Section titled “Supported Scopes”ingest: allowsPOST /api/ingestmembership.update: allowsPOST /api/partners/people/:orcid/membership
If a key is valid but does not include the required scope, the API returns 403.
Endpoint: Queue Ingestion
Section titled “Endpoint: Queue Ingestion”POST /api/ingest
Required scope: ingest
curl -X POST https://api.legaciti.org/api/ingest \ -H "X-API-Key: $PARTNER_INGEST_KEY" \ -H "Content-Type: application/json" \ -d '{"orcid_ids": ["0000-0002-8685-5194"]}'Successful response:
{ "queued": 1, "requested": 1}Endpoint: Update CESAM Affiliation
Section titled “Endpoint: Update CESAM Affiliation”POST /api/partners/people/:orcid/membership
Required scope: membership.update
curl -X POST "https://api.legaciti.org/api/partners/people/0000-0002-8685-5194/membership" \ -H "X-API-Key: $PARTNER_MEMBERSHIP_KEY" \ -H "Content-Type: application/json" \ -d '{ "entity_id": "cesam", "status": "cesam" }'Request body:
entity_id: must becesamstatus:cesamorexternalstarts_at: optional unix timestamp in milliseconds
Successful response:
{ "success": true, "affiliation": { "person_orcid": "0000-0002-8685-5194", "entity_id": "cesam", "status": "cesam", "starts_at": 1742900000000, "ends_at": null }}Error Handling
Section titled “Error Handling”401: missing, invalid, or inactive API key403: key does not have required scope400: invalid request body404: researcher or entity not found429: key exceeded configured per-minute request limit