Menu

Reference

API reference

Connect events from your platform, add game sessions and publish them. Every call acts as one Neegma host, with the access token they gave your app. The same contract is available as an OpenAPI spec for Postman or a client generator.

Base URL

https://tryneegma.com/api/v1

Authentication

Send the host's OAuth access token on every request. See how the host connects.

Authorization: Bearer <access token>
Content-Type: application/json

Errors

Errors share one shape. code is stable for your code to check; message is fine to show the host.

StatusCodeMeaning
400invalid_requestA field is missing or wrong. message names it.
400invalid_eventThe event cannot be created, such as a title under 2 characters.
400invalid_sourcesource is not 2 to 32 lowercase letters, digits or hyphens.
400invalid_external_idexternal_id is empty, too long, or has a space or slash.
400cannot_publishThe event has nothing in it to publish yet. Add a session.
401invalid_tokenRefresh the access token, or ask the host to connect again.
403limit_reachedThe host's plan limit is reached. Show message and upgrade_url.
403upgrade_requiredThe host's plan does not include this, such as private sessions.
403template_not_allowedThe host cannot use that template.
403event_pass_not_allowedevent_pass needs a partner agreement. Contact us to sell Neegma events.
404not_foundThe event does not exist, or belongs to another host.
409event_finishedThe event has finished, so nothing more can be added.
429rate_limitedToo many requests. Wait a minute, then try again.
500server_errorSomething went wrong on Neegma's side. Try again shortly.
503temporarily_unavailableNeegma could not check the account just now. Try again.

Limits

  • 20 changes and 60 reads a minute, per host, per app. Adding sessions: 3 a minute.
  • 5,000 attendees per call.
  • The host's Neegma plan applies: sessions per month, players per session, private sessions.

Connect an event

PUT/api/v1/connected-events/{source}/{external_id}

Creates the Neegma event for one of your events the first time (201), and updates it on every later call (200). Safe to retry: it never creates a second event. Send your own event object with a mapping, or send Neegma's field names.

Path parameters

  • sourcestringrequired

    A short name for your platform: 2 to 32 lowercase letters, digits or hyphens.

  • external_idstringrequired

    The event's ID on your platform. Up to 128 characters, no spaces or slashes.

Body, option 1: Your fields, with a mapping

  • datamaprequired

    Your event, exactly as your platform stores it.

  • mappingobjectrequired

    Which of your fields holds each piece Neegma needs. Paths are dot paths into data.

  • titlestringrequired

    mapping.title

    Field holding the event's name.

  • starts_atstring

    mapping.starts_at

    Field holding the start, as ISO 8601.

  • timezonestring

    mapping.timezone

    Field holding the IANA timezone.

  • urlstring

    mapping.url

    Field holding your event page's URL.

  • privacystring or object

    mapping.privacy

    Field holding public or private, or a translation of your own values.

  • fieldstringrequired

    mapping.privacy.field

    The field in your object that holds the value.

  • valuesmap

    mapping.privacy.values

    Your value on the left, Neegma's on the right.

  • defaultstring

    mapping.privacy.default

    Used for any value not listed in values.

    One of: public, private

  • attendeesobject

    mapping.attendees

    Where the guest list is, and what each guest's fields are.

  • liststringrequired

    mapping.attendees.list

    Field holding the array of guests.

  • namestring or array of stringrequired

    mapping.attendees.name

    Field in each guest holding the name, or up to 3 joined with a space.

  • emailstring

    mapping.attendees.email

    Field in each guest holding the email. Accepted, not stored yet.

  • external_idstring

    mapping.attendees.external_id

    Field in each guest holding your ID for them.

  • statusstring or object

    mapping.attendees.status

    Field holding going, invited or not_going, or a translation.

  • event_passobject

    For partners who sell Neegma events: the paid event pass this event uses. A pass moves or comes off only until guests join. Apps without a partner agreement get event_pass_not_allowed.

  • paidbooleanrequired

    event_pass.paid

    This event is paid for.

    One of: true

  • plan_codestringrequired

    event_pass.plan_code

    The pass bought: party_pass_50, _100, _150 or _200, by the guests it allows.

    One of: party_pass_50, party_pass_100, party_pass_150, party_pass_200

  • referencestringrequired

    event_pass.reference

    Your ID for the pass, such as your order line. Send it for another event to move it.

  • paidbooleanrequired

    event_pass.paid

    Takes your pass off this event.

    One of: false

Body, option 2: Neegma's field names

  • titlestringrequired

    The event's name. 2 to 50 characters; longer names are cut.

  • starts_atstring (date-time) or null

    ISO 8601 start. Leave it out to keep the current time.

  • timezonestring or null

    IANA timezone, such as Europe/London.

  • urlstring or null

    Your event page.

  • privacystring

    private puts a join PIN on every session added to the event.

    One of: public, private

  • attendeesarray of object

    The full guest list. Replaces the one Neegma holds; leave it out to keep it.

  • namestringrequired

    attendees[].name

    The guest's name. Cut to 80 characters.

  • emailstring or null

    attendees[].email

    Optional. Accepted, but not stored yet: nothing in Neegma uses it.

  • external_idstring or number or null

    attendees[].external_id

    Your ID for the guest. Stops the same guest being added twice.

  • statusstring

    attendees[].status

    Defaults to going.

    One of: going, invited, not_going

  • event_passobject

    For partners who sell Neegma events: the paid event pass this event uses. A pass moves or comes off only until guests join. Apps without a partner agreement get event_pass_not_allowed.

  • paidbooleanrequired

    event_pass.paid

    This event is paid for.

    One of: true

  • plan_codestringrequired

    event_pass.plan_code

    The pass bought: party_pass_50, _100, _150 or _200, by the guests it allows.

    One of: party_pass_50, party_pass_100, party_pass_150, party_pass_200

  • referencestringrequired

    event_pass.reference

    Your ID for the pass, such as your order line. Send it for another event to move it.

  • paidbooleanrequired

    event_pass.paid

    Takes your pass off this event.

    One of: false

Returns 201

The connected event. 200 on an update.

  • createdbooleanrequired

    True the first time, when the event was created.

  • eventobjectrequired

    A Neegma event.

  • idintegerrequired

    event.id

    Neegma's ID for the event. Use it in /events/{id}.

  • titlestringrequired

    event.title

  • statusstringrequired

    event.status

    One of: draft, scheduled, ready, active, completed

  • starts_atstring or nullrequired

    event.starts_at

    ISO 8601, or null to play now.

  • timezonestring or nullrequired

    event.timezone

  • privacystringrequired

    event.privacy

    One of: public, private

  • connectionobject or nullrequired

    event.connection

    The platform event this one is connected to, if any.

  • attendeesobjectrequired

    event.attendees

    How many guests the event holds, by status.

  • unpublished_changesarray of stringrequired

    event.unpublished_changes

    What guests cannot see yet. Publish when it is not empty.

  • session_countintegerrequired

    event.session_count

  • manage_urlstringrequired

    event.manage_url

    The event in the host's Neegma dashboard.

  • attendee_urlstringrequired

    event.attendee_url

    The one link to share with guests.

  • host_urlstringrequired

    event.host_url

    Where the host opens the event on the day.

  • sessionsarray of objectrequired

    event.sessions

  • event_passobject

    Only when you sent event_pass. If a pass could not move, a warning says why.

  • passobject or nullrequired

    event_pass.pass

    The pass now on the event, or null when it has none.

  • releasedstring or nullrequired

    event_pass.released

    A pass that came off this event, free to use on another one.

  • warningsarray of stringrequired

    What Neegma changed or could not keep, without failing the call. Show them to the host.

Errors

invalid_request, invalid_event, invalid_source, invalid_external_id, invalid_token, event_pass_not_allowed, rate_limited

Request
curl -X PUT https://tryneegma.com/api/v1/connected-events/eventful/evt-123 \
  -H "Authorization: Bearer $NEEGMA_TOKEN" \
  -H "Content-Type: application/json" \
  -d @body.json
Body
{
  "data": {
    "id": "evt-123",
    "name": "Friday team social",
    "start_at": "2026-11-06T16:00:00Z",
    "tz": "Europe/London",
    "page": "https://eventful.example/e/friday-social",
    "visibility": "members-only",
    "guests": [
      {
        "id": "g1",
        "first_name": "Ada",
        "last_name": "Lovelace",
        "email": "ada@example.com",
        "rsvp": "yes"
      },
      {
        "id": "g2",
        "first_name": "Alan",
        "last_name": "Turing",
        "email": "alan@example.com",
        "rsvp": "maybe"
      }
    ]
  },
  "mapping": {
    "title": "name",
    "starts_at": "start_at",
    "timezone": "tz",
    "url": "page",
    "privacy": {
      "field": "visibility",
      "values": {
        "public": "public",
        "members-only": "private"
      },
      "default": "public"
    },
    "attendees": {
      "list": "guests",
      "name": [
        "first_name",
        "last_name"
      ],
      "email": "email",
      "external_id": "id",
      "status": {
        "field": "rsvp",
        "values": {
          "yes": "going",
          "maybe": "invited",
          "no": "not_going"
        },
        "default": "invited"
      }
    }
  }
}
Response
{
  "created": true,
  "event": {
    "id": 4182,
    "title": "Friday team social",
    "status": "draft",
    "starts_at": "2026-11-06T16:00:00.000Z",
    "timezone": "Europe/London",
    "privacy": "private",
    "connection": {
      "source": "eventful",
      "external_id": "evt-123",
      "url": "https://eventful.example/e/friday-social"
    },
    "attendees": {
      "going": 1,
      "invited": 1,
      "not_going": 0,
      "total": 2
    },
    "unpublished_changes": [],
    "session_count": 0,
    "manage_url": "https://tryneegma.com/dashboard/events/4182",
    "attendee_url": "https://tryneegma.com/event/k3x9a7mq2b4z",
    "host_url": "https://tryneegma.com/event/k3x9a7mq2b4z/host",
    "sessions": []
  },
  "warnings": []
}

Get a connected event

GET/api/v1/connected-events/{source}/{external_id}

The Neegma event connected to one of your events.

Path parameters

  • sourcestringrequired

    A short name for your platform: 2 to 32 lowercase letters, digits or hyphens.

  • external_idstringrequired

    The event's ID on your platform. Up to 128 characters, no spaces or slashes.

Returns 200

The event.

  • eventobjectrequired

    A Neegma event.

  • idintegerrequired

    event.id

    Neegma's ID for the event. Use it in /events/{id}.

  • titlestringrequired

    event.title

  • statusstringrequired

    event.status

    One of: draft, scheduled, ready, active, completed

  • starts_atstring or nullrequired

    event.starts_at

    ISO 8601, or null to play now.

  • timezonestring or nullrequired

    event.timezone

  • privacystringrequired

    event.privacy

    One of: public, private

  • connectionobject or nullrequired

    event.connection

    The platform event this one is connected to, if any.

  • attendeesobjectrequired

    event.attendees

    How many guests the event holds, by status.

  • unpublished_changesarray of stringrequired

    event.unpublished_changes

    What guests cannot see yet. Publish when it is not empty.

  • session_countintegerrequired

    event.session_count

  • manage_urlstringrequired

    event.manage_url

    The event in the host's Neegma dashboard.

  • attendee_urlstringrequired

    event.attendee_url

    The one link to share with guests.

  • host_urlstringrequired

    event.host_url

    Where the host opens the event on the day.

  • sessionsarray of objectrequired

    event.sessions

Errors

not_found, invalid_token

Request
curl -X GET https://tryneegma.com/api/v1/connected-events/eventful/evt-123 \
  -H "Authorization: Bearer $NEEGMA_TOKEN"
Response
{
  "event": {
    "id": 4182,
    "title": "Friday team social",
    "status": "draft",
    "starts_at": "2026-11-06T16:00:00.000Z",
    "timezone": "Europe/London",
    "privacy": "private",
    "connection": {
      "source": "eventful",
      "external_id": "evt-123",
      "url": "https://eventful.example/e/friday-social"
    },
    "attendees": {
      "going": 1,
      "invited": 1,
      "not_going": 0,
      "total": 2
    },
    "unpublished_changes": [],
    "session_count": 0,
    "manage_url": "https://tryneegma.com/dashboard/events/4182",
    "attendee_url": "https://tryneegma.com/event/k3x9a7mq2b4z",
    "host_url": "https://tryneegma.com/event/k3x9a7mq2b4z/host",
    "sessions": []
  }
}

Get an event

GET/api/v1/events/{id}

Any of the host's events, by Neegma's ID.

Path parameters

  • idstringrequired

    Neegma's ID for the event, from event.id.

Returns 200

The event.

  • eventobjectrequired

    A Neegma event.

  • idintegerrequired

    event.id

    Neegma's ID for the event. Use it in /events/{id}.

  • titlestringrequired

    event.title

  • statusstringrequired

    event.status

    One of: draft, scheduled, ready, active, completed

  • starts_atstring or nullrequired

    event.starts_at

    ISO 8601, or null to play now.

  • timezonestring or nullrequired

    event.timezone

  • privacystringrequired

    event.privacy

    One of: public, private

  • connectionobject or nullrequired

    event.connection

    The platform event this one is connected to, if any.

  • attendeesobjectrequired

    event.attendees

    How many guests the event holds, by status.

  • unpublished_changesarray of stringrequired

    event.unpublished_changes

    What guests cannot see yet. Publish when it is not empty.

  • session_countintegerrequired

    event.session_count

  • manage_urlstringrequired

    event.manage_url

    The event in the host's Neegma dashboard.

  • attendee_urlstringrequired

    event.attendee_url

    The one link to share with guests.

  • host_urlstringrequired

    event.host_url

    Where the host opens the event on the day.

  • sessionsarray of objectrequired

    event.sessions

Errors

not_found, invalid_token

Request
curl -X GET https://tryneegma.com/api/v1/events/4182 \
  -H "Authorization: Bearer $NEEGMA_TOKEN"
Response
{
  "event": {
    "id": 4182,
    "title": "Friday team social",
    "status": "draft",
    "starts_at": "2026-11-06T16:00:00.000Z",
    "timezone": "Europe/London",
    "privacy": "private",
    "connection": {
      "source": "eventful",
      "external_id": "evt-123",
      "url": "https://eventful.example/e/friday-social"
    },
    "attendees": {
      "going": 1,
      "invited": 1,
      "not_going": 0,
      "total": 2
    },
    "unpublished_changes": [],
    "session_count": 0,
    "manage_url": "https://tryneegma.com/dashboard/events/4182",
    "attendee_url": "https://tryneegma.com/event/k3x9a7mq2b4z",
    "host_url": "https://tryneegma.com/event/k3x9a7mq2b4z/host",
    "sessions": []
  }
}

Add a game session

POST/api/v1/events/{id}/sessions

Adds a Live or One-Screen Session. On a private event the session gets a 4-digit join PIN. Counts towards the host's monthly session limit.

Path parameters

  • idstringrequired

    Neegma's ID for the event, from event.id.

Body

  • modestringrequired

    live: guests join on their phones. one_screen: only the host's screen.

    One of: live, one_screen

  • titlestring

    Defaults to the event's name.

  • scheduled_forstring (date-time)

    ISO 8601. Only for a second or later session; the first follows the event.

  • template_idinteger

    A fixed running order of games, from GET /templates.

  • privateboolean

    Overrides the event's privacy for this session.

Returns 201

The new session, its join PIN and the updated event.

  • sessionobjectrequired

    A game session.

  • idintegerrequired

    session.id

  • titlestring or nullrequired

    session.title

  • modestringrequired

    session.mode

    One of: live, one_screen

  • scheduled_forstring or nullrequired

    session.scheduled_for

    ISO 8601, or null to follow the event.

  • statestringrequired

    session.state

    One of: not_started, started, finished

  • template_idinteger or nullrequired

    session.template_id

  • is_privatebooleanrequired

    session.is_private

  • host_urlstring

    session.host_url

    Where the host runs the session.

  • player_urlstring

    session.player_url

    Where guests join. Absent on one_screen sessions.

  • join_pinstring or nullrequired

    On a private session, the PIN to show confirmed guests. Otherwise null.

  • eventobject or nullrequired

    A Neegma event.

  • idintegerrequired

    event.id

    Neegma's ID for the event. Use it in /events/{id}.

  • titlestringrequired

    event.title

  • statusstringrequired

    event.status

    One of: draft, scheduled, ready, active, completed

  • starts_atstring or nullrequired

    event.starts_at

    ISO 8601, or null to play now.

  • timezonestring or nullrequired

    event.timezone

  • privacystringrequired

    event.privacy

    One of: public, private

  • connectionobject or nullrequired

    event.connection

    The platform event this one is connected to, if any.

  • attendeesobjectrequired

    event.attendees

    How many guests the event holds, by status.

  • unpublished_changesarray of stringrequired

    event.unpublished_changes

    What guests cannot see yet. Publish when it is not empty.

  • session_countintegerrequired

    event.session_count

  • manage_urlstringrequired

    event.manage_url

    The event in the host's Neegma dashboard.

  • attendee_urlstringrequired

    event.attendee_url

    The one link to share with guests.

  • host_urlstringrequired

    event.host_url

    Where the host opens the event on the day.

  • sessionsarray of objectrequired

    event.sessions

  • warningsarray of stringrequired

    What Neegma changed or could not keep, without failing the call. Show them to the host.

Errors

invalid_request, not_found, limit_reached, upgrade_required, template_not_allowed, event_finished, rate_limited

Request
curl -X POST https://tryneegma.com/api/v1/events/4182/sessions \
  -H "Authorization: Bearer $NEEGMA_TOKEN" \
  -H "Content-Type: application/json" \
  -d @body.json
Body
{
  "mode": "live",
  "template_id": 31
}
Response
{
  "session": {
    "id": 9120,
    "title": "Friday team social",
    "mode": "live",
    "scheduled_for": null,
    "state": "not_started",
    "template_id": 31,
    "is_private": true,
    "host_url": "https://tryneegma.com/neeg-host/qz12ab34cd56",
    "player_url": "https://tryneegma.com/neeg-host/qz12ab34cd56/channel"
  },
  "join_pin": "4821",
  "event": {
    "id": 4182,
    "title": "Friday team social",
    "status": "draft",
    "starts_at": "2026-11-06T16:00:00.000Z",
    "timezone": "Europe/London",
    "privacy": "private",
    "connection": {
      "source": "eventful",
      "external_id": "evt-123",
      "url": "https://eventful.example/e/friday-social"
    },
    "attendees": {
      "going": 1,
      "invited": 1,
      "not_going": 0,
      "total": 2
    },
    "unpublished_changes": [
      "Friday team social is new"
    ],
    "session_count": 1,
    "manage_url": "https://tryneegma.com/dashboard/events/4182",
    "attendee_url": "https://tryneegma.com/event/k3x9a7mq2b4z",
    "host_url": "https://tryneegma.com/event/k3x9a7mq2b4z/host",
    "sessions": [
      {
        "id": 9120,
        "title": "Friday team social",
        "mode": "live",
        "scheduled_for": null,
        "state": "not_started",
        "template_id": 31,
        "is_private": true,
        "host_url": "https://tryneegma.com/neeg-host/qz12ab34cd56",
        "player_url": "https://tryneegma.com/neeg-host/qz12ab34cd56/channel"
      }
    ]
  },
  "warnings": []
}

Publish an event

POST/api/v1/events/{id}/publish

Makes the event's link show its current name, time and sessions. Publish again after any change; unpublished_changes says when.

Path parameters

  • idstringrequired

    Neegma's ID for the event, from event.id.

Returns 200

The published event.

  • eventobjectrequired

    A Neegma event.

  • idintegerrequired

    event.id

    Neegma's ID for the event. Use it in /events/{id}.

  • titlestringrequired

    event.title

  • statusstringrequired

    event.status

    One of: draft, scheduled, ready, active, completed

  • starts_atstring or nullrequired

    event.starts_at

    ISO 8601, or null to play now.

  • timezonestring or nullrequired

    event.timezone

  • privacystringrequired

    event.privacy

    One of: public, private

  • connectionobject or nullrequired

    event.connection

    The platform event this one is connected to, if any.

  • attendeesobjectrequired

    event.attendees

    How many guests the event holds, by status.

  • unpublished_changesarray of stringrequired

    event.unpublished_changes

    What guests cannot see yet. Publish when it is not empty.

  • session_countintegerrequired

    event.session_count

  • manage_urlstringrequired

    event.manage_url

    The event in the host's Neegma dashboard.

  • attendee_urlstringrequired

    event.attendee_url

    The one link to share with guests.

  • host_urlstringrequired

    event.host_url

    Where the host opens the event on the day.

  • sessionsarray of objectrequired

    event.sessions

Errors

cannot_publish, not_found

Request
curl -X POST https://tryneegma.com/api/v1/events/4182/publish \
  -H "Authorization: Bearer $NEEGMA_TOKEN"
Response
{
  "event": {
    "id": 4182,
    "title": "Friday team social",
    "status": "scheduled",
    "starts_at": "2026-11-06T16:00:00.000Z",
    "timezone": "Europe/London",
    "privacy": "private",
    "connection": {
      "source": "eventful",
      "external_id": "evt-123",
      "url": "https://eventful.example/e/friday-social"
    },
    "attendees": {
      "going": 1,
      "invited": 1,
      "not_going": 0,
      "total": 2
    },
    "unpublished_changes": [],
    "session_count": 1,
    "manage_url": "https://tryneegma.com/dashboard/events/4182",
    "attendee_url": "https://tryneegma.com/event/k3x9a7mq2b4z",
    "host_url": "https://tryneegma.com/event/k3x9a7mq2b4z/host",
    "sessions": [
      {
        "id": 9120,
        "title": "Friday team social",
        "mode": "live",
        "scheduled_for": null,
        "state": "not_started",
        "template_id": 31,
        "is_private": true,
        "host_url": "https://tryneegma.com/neeg-host/qz12ab34cd56",
        "player_url": "https://tryneegma.com/neeg-host/qz12ab34cd56/channel"
      }
    ]
  }
}

List templates

GET/api/v1/templates

Templates the host can use: their own, ones they bought, and Neegma's. A template fixes a session's running order of games.

Returns 200

The templates.

  • templatesarray of objectrequired
  • idintegerrequired

    templates[].id

  • titlestringrequired

    templates[].title

  • descriptionstring or nullrequired

    templates[].description

  • sourcestringrequired

    templates[].source

    One of: neegma, bought, mine

  • gamesarray of objectrequired

    templates[].games

Errors

invalid_token

Request
curl -X GET https://tryneegma.com/api/v1/templates \
  -H "Authorization: Bearer $NEEGMA_TOKEN"
Response
{
  "templates": [
    {
      "id": 31,
      "title": "Office icebreakers",
      "description": "Three quick games to get a team talking.",
      "source": "neegma",
      "games": [
        {
          "id": "two-truths-and-a-lie",
          "title": "Two Truths and a Lie"
        },
        {
          "id": "trivia",
          "title": "Trivia"
        }
      ]
    }
  ]
}