Duplicate the event

Embed
Preview of the card
<a href="https://forumulate.com/reference/forumulate-api-events-duplicate"><img src="https://forumulate.com/reference/_api/public/orgs/046a9bc0-d530-43ae-9bae-af7945008cda/spaces/8042f004-e3d9-445f-b7a4-b6c1f86836e6/pages/c88fc572-763b-4ac1-9349-224e333e5f53/social-card.svg?v=3e7ae33eec8b" alt="Duplicate the event" width="600" height="315"></a>
POSThttps://forumulate.com/api/orgs/{orgId}/spaces/{spaceId}/events/{handle}/duplicate

Copies an event as a new DRAFT — place, hosts, tags and look — without its RSVPs, recording or cancellation. The weekly session is a copy with a new date, not a new form.

Requires token scope: write (the coarse method gate) for Atlas key (ak_), Personal Access Token (cft_) or OAuth (cfo_) auth — in addition to any catalog scope (GET /pats/scopes) the route’s capability needs. Session/cookie auth is governed by RBAC capabilities instead.

Parameters
orgIdstringpathrequired
spaceIdstringpathrequired
handlestringpathrequired
forumulate-versionstringheader
API version negotiation. Send forumulate-version: 2026-12-01 on every request from a new integration; it is optional only so that integrations written before versioning keep working. Each version includes everything before it:
Idempotency-Keystringheader
Makes this write safe to retry. Optional — send any unique string (a UUID is ideal) and the first request runs while its response is remembered under that key for 24 hours; an identical retry replays that same status and body instead of acting twice, so a timeout or a 5xx from the edge can be retried without creating a second row. A retry sent while the first request is still in flight is refused with 409. The key is scoped to the method and path, so the same key on a different endpoint is a different request. Error responses of 5xx are never cached — those retries re-run. A key is bound to the BODY it was first used with: reusing it with a different body is a 409 idempotency.key_reused, not a replay, because replaying would tell you a write landed that never ran. Generate one key per request, never per process or per session.
Request body application/json
titlestring
startsAtstring
endsAtstring
{
  "title": "string",
  "startsAt": "string",
  "endsAt": "string"
}
Code samples
cURL
curl -X POST "https://forumulate.com/api/orgs/{orgId}/spaces/{spaceId}/events/{handle}/duplicate" \
  -H "forumulate-version: <value>" \
  -H "Idempotency-Key: <value>" \
  -H "Content-Type: application/json" \
  -d '{"title":"string","startsAt":"string","endsAt":"string"}'
TypeScript
const res = await fetch('https://forumulate.com/api/orgs/{orgId}/spaces/{spaceId}/events/{handle}/duplicate', {
  method: 'POST',
  headers: {
    'forumulate-version': '<value>',
    'Idempotency-Key': '<value>',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({"title":"string","startsAt":"string","endsAt":"string"}),
});
const data = await res.json();
Python
import requests

res = requests.request(
    "POST",
    "https://forumulate.com/api/orgs/{orgId}/spaces/{spaceId}/events/{handle}/duplicate",
    headers={
    "forumulate-version": "<value>",
    "Idempotency-Key": "<value>",
    "Content-Type": "application/json",
    },
    json={"title": "string", "startsAt": "string", "endsAt": "string"},
)
data = res.json()
Go
package main

import (
	"fmt"
	"io"
	"net/http"
	"strings"
)

func main() {
	req, _ := http.NewRequest("POST", "https://forumulate.com/api/orgs/{orgId}/spaces/{spaceId}/events/{handle}/duplicate", strings.NewReader(`{"title":"string","startsAt":"string","endsAt":"string"}`))
	req.Header.Set("forumulate-version", "<value>")
	req.Header.Set("Idempotency-Key", "<value>")
	req.Header.Set("Content-Type", "application/json")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)
	fmt.Println(string(body))
}
PHP
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://forumulate.com/api/orgs/{orgId}/spaces/{spaceId}/events/{handle}/duplicate');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['forumulate-version: <value>', 'Idempotency-Key: <value>', 'Content-Type: application/json']);
curl_setopt($ch, CURLOPT_POSTFIELDS, '{"title":"string","startsAt":"string","endsAt":"string"}');
$response = curl_exec($ch);
curl_close($ch);
echo $response;
Ruby
require 'net/http'
require 'uri'

uri = URI('https://forumulate.com/api/orgs/{orgId}/spaces/{spaceId}/events/{handle}/duplicate')
req = Net::HTTP::Post.new(uri)
req['forumulate-version'] = '<value>'
req['Idempotency-Key'] = '<value>'
req['Content-Type'] = 'application/json'
req.body = '{"title":"string","startsAt":"string","endsAt":"string"}'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
  http.request(req)
end
puts res.body
Java
import java.net.URI;
import java.net.http.*;
import java.net.http.HttpRequest.BodyPublishers;

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://forumulate.com/api/orgs/{orgId}/spaces/{spaceId}/events/{handle}/duplicate"))
    .header("forumulate-version", "<value>")
    .header("Idempotency-Key", "<value>")
    .header("Content-Type", "application/json")
    .method("POST", BodyPublishers.ofString("{\"title\":\"string\",\"startsAt\":\"string\",\"endsAt\":\"string\"}"))
    .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
Responses
201 Created.
Example
{
  "event": {
    "attendanceMode": "hybrid",
    "capacity": 0,
    "capacityState": {
      "capacity": 0,
      "full": true,
      "going": 0,
      "spotsLeft": 0,
      "waitlisted": 0,
      "waitlistOpen": true
    },
    "counts": {
      "declined": 0,
      "going": 0,
      "interested": 0,
      "waitlist": 0
    },
    "coverAlt": "string",
    "coverUrl": "string",
    "customization": {
      "customCss": "string",
      "jsonLd": "string",
      "ogDescription": "string",
      "ogTitle": "string",
      "shareImageUrl": "string",
      "theme": {
        "accentColor": null,
        "bodyFontFamily": null,
        "changelog": null,
        "colorScheme": null,
        "components": null,
        "contentWidth": null,
        "customFontFamily": null,
        "font": null,
        "headingFontFamily": null,
        "layout": null,
        "monoFontFamily": null,
        "motion": null,
        "palette": null,
        "paletteDark": null,
        "post": null,
        "primaryColor": null,
        "typography": null
      },
      "twitterCard": "summary"
    },
    "description": "string",
    "endsAt": "string",
    "feedbackFormId": "string",
    "gallery": [
      {
        "alt": "string",
        "caption": "string",
        "url": "string"
      }
    ],
    "guestsMax": 0,
    "hostInfo": [
      {
        "author": null,
        "avatarUrl": null,
        "bio": null,
        "handle": "string",
        "name": "string",
        "role": null,
        "url": null,
        "userId": null
      }
    ],
    "hosts": [
      {}
    ],
    "id": "string",
    "joinLinkHidden": true,
    "joinLinkVisibility": "attendees",
    "location": "string",
    "phase": "live",
    "previousStartsAt": "string",
    "questions": [
      {
        "help": "string",
        "label": "string",
        "max": 0,
        "min": 0,
        "name": "string",
        "options": [
          null
        ],
        "pattern": "string",
        "placeholder": "string",
        "required": true,
        "type": "checkbox",
        "value": "string"
      }
    ],
    "recapUrl": "string",
    "recordingUrl": "string",
    "recurrence": {
      "byWeekday": [
        null
      ],
      "count": 0,
      "freq": "daily",
      "interval": 0,
      "until": "string"
    },
    "rrule": "string",
    "rsvpApproval": true,
    "sequence": 0,
    "seriesId": "string",
    "slidesUrl": "string",
    "slug": "string",
    "startsAt": "string",
    "state": "CANCELLED",
    "stateReason": "string",
    "tagInfo": [
      {
        "color": null,
        "colorDark": null,
        "coverUrl": null,
        "description": null,
        "gradient": null,
        "icon": "string",
        "label": "string",
        "pagePalette": null,
        "pageScheme": "dark",
        "slug": "string",
        "textColor": null,
        "textColorDark": null
      }
    ],
    "tags": [
      "string"
    ],
    "timezone": "string",
    "title": "string",
    "topicId": "string",
    "updatedAt": "string",
    "url": "string",
    "venue": {
      "city": "string",
      "country": "string",
      "lat": 0,
      "lng": 0,
      "name": "string",
      "postalCode": "string",
      "region": "string",
      "street": "string"
    }
  },
  "data": {
    "attendanceMode": "hybrid",
    "capacity": 0,
    "capacityState": {
      "capacity": 0,
      "full": true,
      "going": 0,
      "spotsLeft": 0,
      "waitlisted": 0,
      "waitlistOpen": true
    },
    "counts": {
      "declined": 0,
      "going": 0,
      "interested": 0,
      "waitlist": 0
    },
    "coverAlt": "string",
    "coverUrl": "string",
    "customization": {
      "customCss": "string",
      "jsonLd": "string",
      "ogDescription": "string",
      "ogTitle": "string",
      "shareImageUrl": "string",
      "theme": {
        "accentColor": null,
        "bodyFontFamily": null,
        "changelog": null,
        "colorScheme": null,
        "components": null,
        "contentWidth": null,
        "customFontFamily": null,
        "font": null,
        "headingFontFamily": null,
        "layout": null,
        "monoFontFamily": null,
        "motion": null,
        "palette": null,
        "paletteDark": null,
        "post": null,
        "primaryColor": null,
        "typography": null
      },
      "twitterCard": "summary"
    },
    "description": "string",
    "endsAt": "string",
    "feedbackFormId": "string",
    "gallery": [
      {
        "alt": "string",
        "caption": "string",
        "url": "string"
      }
    ],
    "guestsMax": 0,
    "hostInfo": [
      {
        "author": null,
        "avatarUrl": null,
        "bio": null,
        "handle": "string",
        "name": "string",
        "role": null,
        "url": null,
        "userId": null
      }
    ],
    "hosts": [
      {}
    ],
    "id": "string",
    "joinLinkHidden": true,
    "joinLinkVisibility": "attendees",
    "location": "string",
    "phase": "live",
    "previousStartsAt": "string",
    "questions": [
      {
        "help": "string",
        "label": "string",
        "max": 0,
        "min": 0,
        "name": "string",
        "options": [
          null
        ],
        "pattern": "string",
        "placeholder": "string",
        "required": true,
        "type": "checkbox",
        "value": "string"
      }
    ],
    "recapUrl": "string",
    "recordingUrl": "string",
    "recurrence": {
      "byWeekday": [
        null
      ],
      "count": 0,
      "freq": "daily",
      "interval": 0,
      "until": "string"
    },
    "rrule": "string",
    "rsvpApproval": true,
    "sequence": 0,
    "seriesId": "string",
    "slidesUrl": "string",
    "slug": "string",
    "startsAt": "string",
    "state": "CANCELLED",
    "stateReason": "string",
    "tagInfo": [
      {
        "color": null,
        "colorDark": null,
        "coverUrl": null,
        "description": null,
        "gradient": null,
        "icon": "string",
        "label": "string",
        "pagePalette": null,
        "pageScheme": "dark",
        "slug": "string",
        "textColor": null,
        "textColorDark": null
      }
    ],
    "tags": [
      "string"
    ],
    "timezone": "string",
    "title": "string",
    "topicId": "string",
    "updatedAt": "string",
    "url": "string",
    "venue": {
      "city": "string",
      "country": "string",
      "lat": 0,
      "lng": 0,
      "name": "string",
      "postalCode": "string",
      "region": "string",
      "street": "string"
    }
  },
  "warnings": [
    "tags: \"Launch Day\" is stored as \"launch-day\""
  ]
}
Schema
eventobjectrequired
Show child parameters
attendanceModestringrequired
hybrid | in_person | online
capacitynumberrequired
capacityStateobjectrequired
Show child parameters
capacitynumberrequired
fullbooleanrequired
goingnumberrequired
spotsLeftnumberrequired
waitlistednumberrequired
waitlistOpenbooleanrequired
countsobjectrequired
Show child parameters
declinednumberrequired
goingnumberrequired
interestednumberrequired
waitlistnumberrequired
coverAltstringrequired
coverUrlstringrequired
customizationPieceCustomizationrequired
Show child parameters
customCssstring
jsonLdstring
ogDescriptionstring
ogTitlestring
shareImageUrlstring
themeobject
twitterCardstring
summary | summary_large_image
descriptionstringrequired
endsAtstringrequired
feedbackFormIdstringrequired
galleryobject[]required
Show child parameters
altstring
captionstring
urlstringrequired
guestsMaxnumberrequired
hostInfoBylineView[]required
Show child parameters
authorstringrequired
avatarUrlstringrequired
biostringrequired
handlestring
namestringrequired
rolestringrequired
urlstringrequired
userIdstringrequired
hostsobject[]required
idstringrequired
joinLinkHiddenbooleanrequired
joinLinkVisibilitystringrequired
attendees | public
locationstringrequired
phasestringrequired
live | past | upcoming
previousStartsAtstringrequired
questionsFormField[]required
Show child parameters
helpstring
labelstringrequired
maxnumber
minnumber
namestringrequired
optionsstring[]
patternstring
placeholderstring
requiredboolean
typestringrequired
checkbox | consent | date | email | file | hidden | multiselect | number | phone | radio | select | text | textarea | url
valuestring
recapUrlstringrequired
recordingUrlstringrequired
recurrenceobjectrequired
Show child parameters
byWeekdaystring[]
countnumber
freqstringrequired
daily | monthly | weekly
intervalnumber
untilstring
rrulestringrequired
rsvpApprovalbooleanrequired
sequencenumberrequired
seriesIdstringrequired
slidesUrlstringrequired
slugstringrequired
startsAtstringrequired
statestringrequired
CANCELLED | DRAFT | POSTPONED | PUBLISHED
stateReasonstringrequired
tagInfoTagDisplay[]required
Show child parameters
colorstringrequired
colorDarkstringrequired
coverUrlstringrequired
descriptionstringrequired
gradientarrayrequired
iconstring
labelstringrequired
pagePaletteobjectrequired
pageSchemestringrequired
dark | light
slugstringrequired
textColorstringrequired
textColorDarkstringrequired
tagsstring[]required
timezonestringrequired
titlestringrequired
topicIdstringrequired
updatedAtstringrequired
urlstringrequired
venueobjectrequired
Show child parameters
citystring
countrystring
latnumber
lngnumber
namestring
postalCodestring
regionstring
streetstring
dataobject
The created resource again, under a key that is the same on every create — so a generic client needs one parser rather than one per endpoint. It is the SAME object as the key named after the resource (page, article, topic, …), which remains the canonical name.
Show child parameters
attendanceModestringrequired
hybrid | in_person | online
capacitynumberrequired
capacityStateobjectrequired
Show child parameters
capacitynumberrequired
fullbooleanrequired
goingnumberrequired
spotsLeftnumberrequired
waitlistednumberrequired
waitlistOpenbooleanrequired
countsobjectrequired
Show child parameters
declinednumberrequired
goingnumberrequired
interestednumberrequired
waitlistnumberrequired
coverAltstringrequired
coverUrlstringrequired
customizationPieceCustomizationrequired
Show child parameters
customCssstring
jsonLdstring
ogDescriptionstring
ogTitlestring
shareImageUrlstring
themeobject
twitterCardstring
summary | summary_large_image
descriptionstringrequired
endsAtstringrequired
feedbackFormIdstringrequired
galleryobject[]required
Show child parameters
altstring
captionstring
urlstringrequired
guestsMaxnumberrequired
hostInfoBylineView[]required
Show child parameters
authorstringrequired
avatarUrlstringrequired
biostringrequired
handlestring
namestringrequired
rolestringrequired
urlstringrequired
userIdstringrequired
hostsobject[]required
idstringrequired
joinLinkHiddenbooleanrequired
joinLinkVisibilitystringrequired
attendees | public
locationstringrequired
phasestringrequired
live | past | upcoming
previousStartsAtstringrequired
questionsFormField[]required
Show child parameters
helpstring
labelstringrequired
maxnumber
minnumber
namestringrequired
optionsstring[]
patternstring
placeholderstring
requiredboolean
typestringrequired
checkbox | consent | date | email | file | hidden | multiselect | number | phone | radio | select | text | textarea | url
valuestring
recapUrlstringrequired
recordingUrlstringrequired
recurrenceobjectrequired
Show child parameters
byWeekdaystring[]
countnumber
freqstringrequired
daily | monthly | weekly
intervalnumber
untilstring
rrulestringrequired
rsvpApprovalbooleanrequired
sequencenumberrequired
seriesIdstringrequired
slidesUrlstringrequired
slugstringrequired
startsAtstringrequired
statestringrequired
CANCELLED | DRAFT | POSTPONED | PUBLISHED
stateReasonstringrequired
tagInfoTagDisplay[]required
Show child parameters
colorstringrequired
colorDarkstringrequired
coverUrlstringrequired
descriptionstringrequired
gradientarrayrequired
iconstring
labelstringrequired
pagePaletteobjectrequired
pageSchemestringrequired
dark | light
slugstringrequired
textColorstringrequired
textColorDarkstringrequired
400 The request could not be understood — a malformed header, path or query value (request.malformed). A value that was understood but is not acceptable is a 422 validation.failed.
{
  "error": {
    "code": "string",
    "message": "string",
    "details": {},
    "docs": "string",
    "reason": "string",
    "slugs": [
      "string"
    ],
    "conflict": {
      "etag": "string",
      "ops": [
        null
      ]
    }
  },
  "requestId": "string"
}
401 No credential, or one that is expired or revoked (auth.required). Send a Bearer token or the session cookie.
{
  "error": {
    "code": "string",
    "message": "string",
    "details": {},
    "docs": "string",
    "reason": "string",
    "slugs": [
      "string"
    ],
    "conflict": {
      "etag": "string",
      "ops": [
        null
      ]
    }
  },
  "requestId": "string"
}
403 Authenticated, and not allowed — always rbac.forbidden, whether what is missing is the capability, the token scope, or a resource the token is pinned away from. The message names the capability and, for a scope refusal, the scopes that would grant it. A refusal because of the PLAN is a 402 with quota.exceeded, not this.
{
  "error": {
    "code": "string",
    "message": "string",
    "details": {},
    "docs": "string",
    "reason": "string",
    "slugs": [
      "string"
    ],
    "conflict": {
      "etag": "string",
      "ops": [
        null
      ]
    }
  },
  "requestId": "string"
}
404 No such thing — one of the ids in the path does not resolve, or resolves to something this caller may not see (*.not_found).
{
  "error": {
    "code": "string",
    "message": "string",
    "details": {},
    "docs": "string",
    "reason": "string",
    "slugs": [
      "string"
    ],
    "conflict": {
      "etag": "string",
      "ops": [
        null
      ]
    }
  },
  "requestId": "string"
}
422 The body was understood and a value is unacceptable (validation.failed). error.details names the field paths.
{
  "error": {
    "code": "string",
    "message": "string",
    "details": {},
    "docs": "string",
    "reason": "string",
    "slugs": [
      "string"
    ],
    "conflict": {
      "etag": "string",
      "ops": [
        null
      ]
    }
  },
  "requestId": "string"
}
429 Rate limited — see the RateLimit-* headers.
{
  "error": {
    "code": "string",
    "message": "string",
    "details": {},
    "docs": "string",
    "reason": "string",
    "slugs": [
      "string"
    ],
    "conflict": {
      "etag": "string",
      "ops": [
        null
      ]
    }
  },
  "requestId": "string"
}
default Error — the stable { error: { code, message } } envelope.
{
  "error": {
    "code": "string",
    "message": "string",
    "details": {},
    "docs": "string",
    "reason": "string",
    "slugs": [
      "string"
    ],
    "conflict": {
      "etag": "string",
      "ops": [
        null
      ]
    }
  },
  "requestId": "string"
}
The Forumulate teamUpdated