Events

Upsert an event by external id (replace)

Changed on

Upserts the event carrying the (extKey, extId) pair: its content is REPLACED if it already exists (200), or the event is CREATED if not (201 + a Location header pointing at its canonical by-uid URL). The path pair is authoritative - it is added to the event's extIds, keeping the mappings from other systems, so the event always carries its own external identity; any extIds in the body are ignored. This is the recommended write path for syncing from your own system: it is idempotent by external identity, so a lost response can be retried without creating a duplicate.

The acting member must be allowed to create or edit the event, otherwise 403.

put/agendas/{agendaUid}/events/ext/{extKey}/{extId}

Request

  • Base URL: https://api.openagenda.com/v3
  • URL: https://api.openagenda.com/v3/agendas/{agendaUid}/events/ext/{extKey}/{extId}
  • Auth: one of:
    • HTTP bearer
    • OAuth 2 (authorization code, authorization URL https://openagenda.com/api/auth/oauth2/authorize, token URL https://openagenda.com/api/auth/oauth2/token, scopes: events:write)

Path parameters

agendaUidinteger required

Numeric uid of the agenda.

extKeystring required

Name of the external system/source the identifier belongs to (the key of an ExtId mapping carried on the resource — an event or a location).

extIdstring required

The resource's identifier within that external system (the value of an ExtId mapping carried in the resource's extIds). Percent-encode reserved characters.

Request body

titleLocalizedString

A string localized per language, keyed by ISO 639-1 code (e.g. fr, en).

descriptionLocalizedString

A string localized per language, keyed by ISO 639-1 code (e.g. fr, en).

longDescriptionLocalizedString

A string localized per language, keyed by ISO 639-1 code (e.g. fr, en).

conditionsLocalizedString

A string localized per language, keyed by ISO 639-1 code (e.g. fr, en).

keywordsLocalizedStringArray

A list of strings localized per language code (used for keywords).

attendanceMode1 | 2 | 3

How attendees take part.

onlineAccessLinkstring uri nullable

Access link for an online or hybrid event (attendanceMode 2 or 3).

state-2 | -1 | 0 | 1 | 2

Moderation state of the event.

status1 | 2 | 3 | 4 | 5 | 6

Lifecycle status of the event.

imageCreditsstring nullable

Credits for the event image. Ignored when the event has no image; null clears them.

canonicalUrlstring uri nullable

The event's own page on its publisher's website, declared by the licensor. Reads fall back on the event's page on its origin agenda; writing that page back declares nothing and is stored as null, as is null itself.

additionalFieldsAdditionalFields

Agenda-specific additional fields. The available keys and the shape of each value are defined by the agenda's event form schema (GET /agendas/{agendaUid}/events/schema): each value follows its field's fieldType. On a write, a key the schema does not declare answers 422.

A file/image field is set by reference, like the native image: stage the bytes via POST /agendas/{uid}/uploads, then send { ref, name? } here (name is the original filename, used for the download; optional), or null to clear it. On read the same field returns the stored descriptor { originalName, extension, filename }, where filename is the stored object's key; the API does not return its absolute URL.

Example request

{
  "title": {
    "fr": "Concert de jazz",
    "en": "Jazz concert"
  },
  "description": {
    "fr": "Concert de jazz",
    "en": "Jazz concert"
  },
  "longDescription": {
    "fr": "Concert de jazz",
    "en": "Jazz concert"
  },
  "conditions": {
    "fr": "Concert de jazz",
    "en": "Jazz concert"
  }
}

Response

The existing event was updated.

uidinteger required
slugstring required

Unique across all events. Set by the server from the title when the event is created, and never changed afterwards, even if the title changes.

titleLocalizedString required

A string localized per language, keyed by ISO 639-1 code (e.g. fr, en).

descriptionLocalizedString required

A string localized per language, keyed by ISO 639-1 code (e.g. fr, en).

status1 | 2 | 3 | 4 | 5 | 6 required

Lifecycle status of the event.

dateRangeLocalizedString required

A string localized per language, keyed by ISO 639-1 code (e.g. fr, en).

featuredboolean required
imageCreditsstring nullable required
keywordsLocalizedStringArray required

A list of strings localized per language code (used for keywords).

canonicalUrlstring uri nullable required

The address to link to when crediting the event: the page its licensor declared for it, else its page on its origin agenda. The same whichever agenda the event is read through. null on an event indexed before this field was introduced, until it is reindexed, and on an event whose origin agenda no longer exists.

timezonestring nullable required

IANA time zone the timings are expressed in (null when unset).

attendanceMode1 | 2 | 3 required

How attendees take part.

onlineAccessLinkstring uri nullable required
additionalFieldsAdditionalFields required

Agenda-specific additional fields. The available keys and the shape of each value are defined by the agenda's event form schema (GET /agendas/{agendaUid}/events/schema): each value follows its field's fieldType. On a write, a key the schema does not declare answers 422.

A file/image field is set by reference, like the native image: stage the bytes via POST /agendas/{uid}/uploads, then send { ref, name? } here (name is the original filename, used for the download; optional), or null to clear it. On read the same field returns the stored descriptor { originalName, extension, filename }, where filename is the stored object's key; the API does not return its absolute URL.

longDescriptionLocalizedString required

A string localized per language, keyed by ISO 639-1 code (e.g. fr, en).

conditionsLocalizedString required

A string localized per language, keyed by ISO 639-1 code (e.g. fr, en).

countryLocalizedString required

A string localized per language, keyed by ISO 639-1 code (e.g. fr, en).

createdAtstring date-time required
updatedAtstring date-time required
availabilityUpdatedAtstring date-time

A SECOND CURSOR, for inventory rather than catalogue. An availability write does not move updatedAt: an inventory tick is not a content change, and a catalogue consumer paging on updatedAt.asc must not see an event resurface every time a seat is sold. This stamp moves instead, so availability stays followable on its own — ?sort=availabilityUpdatedAt.asc&availabilityUpdatedAt[gte]=<watermark>. Its value is the instant OpenAgenda last WROTE an availability row of this event — the write clock. It is not the rows' own syncedAt, which says when each provider was read and may sit behind another provider's row, so a max-of-syncedAt would not move forward at all for such a provider. THE STAMP IS TAKEN AT THE WRITE, THE DOCUMENT IS INDEXED AFTER, and the two orders can differ: an event stamped at t1 may be indexed after one stamped at t2 > t1, and a consumer that has already moved its watermark to t2 would never see it. Re-indexing is also best-effort — a failed resync is retried later, not at the instant of the write. So overlap rather than trust exhaustiveness: page with a watermark set a little behind the newest value you saw (a few minutes covers the ordinary case), and make your ingestion idempotent. Rows carry syncedAt, so re-reading one costs nothing. ABSENT from an event that has never received availability, which is the overwhelming majority. A [gte] filter therefore excludes them naturally, which is the intent: following inventory should not mean paging through the whole corpus. IT DOES NOT MOVE WHEN AN EVENT LEAVES. Deleting an event, or unpublishing it, is a catalogue change: it stamps updatedAt and leaves this one where it was. A consumer that follows inventory ALONE therefore keeps selling dates for an event that is gone — follow updatedAt as well, or re-read the events you hold, to see departures.

state-2 | -1 | 0 | 1 | 2 required

Moderation state of the event.

Example response

{
  "uid": 9876543,
  "slug": "concert-de-jazz-au-parc",
  "title": {
    "fr": "Concert de jazz au parc",
    "en": "Jazz concert in the park"
  },
  "description": {
    "fr": "Une soirée jazz en plein air.",
    "en": "An open-air jazz evening."
  },
  "status": 1,
  "dateRange": {
    "fr": "Le 20 juin 2025 de 18h00 à 22h00",
    "en": "June 20, 2025, 6:00 PM – 10:00 PM"
  },
  "featured": false,
  "image": {
    "width": 1200,
    "height": 800,
    "src": "https://img.openagenda.com/u/1080x0/main/9876543.full.image.jpg",
    "srcTemplate": "https://img.openagenda.com/u/{geo}/main/9876543.full.image.jpg",
    "srcset": [
      {
        "width": 640,
        "url": "https://img.openagenda.com/u/640x0/main/9876543.full.image.jpg"
      },
      {
        "width": 1080,
        "url": "https://img.openagenda.com/u/1080x0/main/9876543.full.image.jpg"
      }
    ]
  },
  "imageCredits": "Ville de Lyon",
  "keywords": {
    "fr": [
      "jazz",
      "concert",
      "plein air"
    ],
    "en": [
      "jazz",
      "concert",
      "open air"
    ]
  },
  "originAgenda": {
    "uid": 12345,
    "title": "Festival des Lumières",
    "slug": "festival-des-lumieres",
    "image": {
      "src": "https://img.openagenda.com/u/400x0/main/a1b2c3d4e5f60718293a4b5c6d7e8f90.full.image.jpg",
      "srcTemplate": "https://img.openagenda.com/u/{geo}/main/a1b2c3d4e5f60718293a4b5c6d7e8f90.full.image.jpg"
    },
    "url": "https://openagenda.com/festival-des-lumieres",
    "official": true
  },
  "rights": {
    "license": {
      "id": "etalab-2.0",
      "name": "Licence Ouverte 2.0",
      "url": "https://www.data.gouv.fr/pages/legal/licences/etalab-2.0/"
    },
    "licensor": {
      "name": "Ville de Lyon",
      "url": "https://www.lyon.fr",
      "agendaUid": 12345
    },
    "publisher": {
      "name": "Ville de Lyon",
      "url": "https://www.lyon.fr",
      "agendaUid": 12345
    }
  },
  "canonicalUrl": "https://www.lyon.fr/evenement/concert-de-jazz-au-parc",
  "timings": [
    {
      "begin": "2025-06-20T18:00:00+02:00",
      "end": "2025-06-20T22:00:00+02:00"
    }
  ],
  "location": {
    "uid": 55512,
    "name": "Parc de la Tête d'Or",
    "address": "Place Général Leclerc",
    "city": "Lyon",
    "region": "Auvergne-Rhône-Alpes",
    "postalCode": "69006",
    "countryCode": "FR",
    "latitude": 45.7772,
    "longitude": 4.8558,
    "district": null,
    "department": "Rhône",
    "adminLevel3": null,
    "adminLevel5": null,
    "country": {
      "fr": "France",
      "en": "France"
    },
    "timezone": "Europe/Paris"
  },
  "timezone": "Europe/Paris",
  "attendanceMode": 1,
  "onlineAccessLink": null,
  "firstTiming": {
    "begin": "2025-06-20T18:00:00+02:00",
    "end": "2025-06-20T22:00:00+02:00"
  },
  "lastTiming": {
    "begin": "2025-06-20T18:00:00+02:00",
    "end": "2025-06-20T22:00:00+02:00"
  },
  "nextTiming": {
    "begin": "2025-06-20T18:00:00+02:00",
    "end": "2025-06-20T22:00:00+02:00"
  },
  "additionalFields": {},
  "longDescription": {
    "fr": "Un concert en plein air avec plusieurs formations de jazz…",
    "en": "An open-air concert featuring several jazz ensembles…"
  },
  "conditions": {
    "fr": "Entrée libre",
    "en": "Free entry"
  },
  "country": {
    "fr": "France",
    "en": "France"
  },
  "registration": [
    {
      "type": "link",
      "value": "https://openagenda.com/festival-des-lumieres/events/concert-de-jazz-au-parc"
    }
  ],
  "createdAt": "2025-03-12T11:30:00+01:00",
  "updatedAt": "2025-05-28T16:45:00+02:00",
  "accessibility": {
    "hi": false,
    "ii": false,
    "vi": true,
    "pi": false,
    "mi": true
  },
  "age": {
    "min": 0,
    "max": null
  },
  "state": 2,
  "links": [
    {
      "link": "https://example.org/jazz-au-parc",
      "data": {}
    }
  ],
  "extIds": [
    {
      "key": "legacy",
      "value": "4421007"
    }
  ],
  "sourceAgendas": []
}

Changes

    • info

      added the optional property /// to the response with the status

    • info

      added the optional property /////// to the response with the status

    • info

      added the optional property to the response with the status

    • info

      added the optional property to the response with the status