Konzepte
Fehler
Jede Ablehnung ist ein Problem nach RFC 9457 mit einem stabilen Code. Verzweigen Sie anhand des Codes; zeigen Sie einem Menschen das Detail.
Der Aufbau eines Problems
Lehnt die API einen Aufruf ab, antwortet sie mit einem Status von 400 oder höher und einem Body vom Typ application/problem+json, wie RFC 9457 ihn beschreibt:
{
"type": "https://attendbeacon.com/developers/errors#moduleOff",
"title": "The module is switched off",
"status": 409,
"detail": "The Sponsors module is switched off for this event. Its organiser can switch it on under the event's Modules; nothing was deleted.",
"instance": "/api/v1/events/b3ac0000-0000-4000-8000-000000000001/sponsors",
"code": "moduleOff",
"traceId": "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01",
"module": "sponsors",
"error": "The Sponsors module is switched off for this event. ..."
}codeist das, worauf Ihre Software verzweigt. Codes sind stabil: Einmal ausgeliefert, werden sie nie umbenannt.detailist ein Satz für einen Menschen: Zeigen Sie ihn in Ihrem Protokoll oder Ihrer Oberfläche an.typeverweist auf die Zeile des Codes in der Tabelle unten.traceIdhilft dem Support von AttendBeacon, den Aufruf zu finden. Schicken Sie die ID mit, wenn Sie fragen.- Manche Codes bringen mehr mit:
scope(der Scope, der einem Schlüssel fehlt),module,errors(jedes Feld, das nicht stimmt),etag,taken,sessions. errorwiederholtdetailfür Flows, die vor den Problem Details gebaut wurden. Es bleibt in v1 erhalten; neuer Code solltedetaillesen.
Felder, die nicht stimmen
invalidRequest listet jedes Feld mit dem auf, was daran nicht stimmt. So kann ein Formular die Meldung direkt neben dem Feld anzeigen:
{
"status": 400,
"code": "invalidRequest",
"detail": "Some fields are not right; errors names each.",
"errors": [
{ "field": "startDate", "message": "startDate is a date such as 2026-11-12." },
{ "field": "timeZone", "message": "timeZone is an IANA zone such as Europe/Amsterdam." }
]
}Eine abgelehnte Anmeldung nennt auch die teilnehmende Person, gezählt ab 0, mit einem Code für das, was nicht stimmt: { "attendee": 0, "field": "email", "code": "notEmail" }.
Was Sie wiederholen sollten
| Status | Wiederholen? |
|---|---|
| 400, 401, 403, 404, 409, 412, 422 | Nein: Dieselbe Anfrage wird erneut abgelehnt. Korrigieren Sie sie zuerst. |
| 429 | Ja, nach den Sekunden in Retry-After. Siehe Ratenlimits. |
| 500, 502, 503, 504 | Ja, einige Male mit wachsender Wartezeit, und bei einem POST mit demselben Idempotency-Key. Siehe Idempotenz. |
Alle Codes
| Code | Status | Bedeutung und was zu tun ist |
|---|---|---|
invalidKey | 401 | No working API key. No key was sent, or it is not one this platform made. Send it as Authorization: Bearer abk_... or in X-Api-Key. |
keyExpired | 401 | The key has expired. The key's expiry date has passed. Make a new key in the workspace under Integrations, API & MCP. |
keyRevoked | 401 | The key was revoked. Somebody revoked the key in the workspace. Make a new key. |
wrongAudience | 401 | A token for another resource. A token an assistant got by signing in works where it was issued for: the MCP server (/mcp) or the REST API (/api/v1). |
invalidOrigin | 403 | Not from this origin. The MCP server takes browser requests from AttendBeacon's own origin only; servers and command-line clients send no Origin. |
missingScope | 403 | The key lacks a scope. The key works but may not do this; scope names the scope it needs. Scopes are chosen when a key is made. |
peopleScope | 403 | Personal data needs people:read. This call is about people by name or address, which needs the people:read scope as well. |
notFound | 404 | Not found. There is no such resource in this key's workspace. Another workspace's ids read as not found. |
eventNotFound | 404 | No such event. There is no such event in this key's workspace. |
attendeeNotFound | 404 | No such attendee. There is no such attendee at this event. |
noDoor | 404 | No such door. There is no such door at this event. |
moduleOff | 409 | The module is switched off. The event's organiser switched this feature off under the event's Modules; module names it. Nothing was deleted: switched on again, its data is back. |
onlineEvent | 409 | An online event has no doors. Check-in and other door features do not apply to an online event. |
alreadyCancelled | 409 | Already cancelled. The ticket is already cancelled. |
clash | 409 | The room is taken. Another session is in the room at that time; sessions names it. Send allowClash: true to place it anyway. |
slugTaken | 409 | The address is taken. Another event already has this slug. |
historyNeedsLicence | 409 | A licence is needed first. Reopening an earlier edition above the free limit needs its licence, bought in the workspace. |
endsCommunity | 409 | This would end the community status. A paid ticket ends an event's free community status above the free limit; confirm in the workspace. |
codeTaken | 409 | The code exists. The event already has a discount code with these letters. |
capacityBelowTaken | 409 | Capacity below what is sold. The capacity would be lower than the places already taken; taken says how many. |
idempotencyKeyInUse | 409 | The same request is still running. A request with this Idempotency-Key is still being handled. Wait a moment and send it again. |
preconditionFailed | 412 | Changed since you read it. If-Match does not name the resource as it is now: somebody changed it. Read it again, then send the change. |
idempotencyKeyReused | 422 | Idempotency-Key used for another request. This Idempotency-Key was used within 24 hours for a request with another method, path or body. Use a new key for a new request. |
invalidRequest | 400 | The request is not valid. A field or parameter is missing or wrong; errors names each, with what is wrong. |
invalidBody | 400 | The body is not readable. The body is not JSON, or a field has the wrong type. |
invalidCursor | 400 | The cursor is not valid. Pass nextCursor exactly as a list returned it, with the same filters. |
invalidUpdatedSince | 400 | updatedSince is not a moment. updatedSince is an ISO 8601 moment such as 2026-10-09T08:00:00Z. |
invalidSort | 400 | Unknown sort. sort is changed (oldest change first, the default) or -created (newest first). |
invalidIdempotencyKey | 400 | Idempotency-Key is not valid. An Idempotency-Key is 1 to 255 visible ASCII characters; a UUID is a good one. |
invalid | 400 | An attendee's details are not right. errors names which attendee (from 0) and which field: firstName, lastName, email, company, jobTitle or a question id, with what is wrong (required, tooLong, notEmail, notOption). |
soldOut | 400 | Sold out. The ticket type has no places left; ticketTypeId names it. Sent as 400 since v1 began, kept so for flows that branch on it. |
unknownTicket | 400 | No such ticket type. ticketTypeId is not a ticket type of this event. |
empty | 400 | Nobody to register. Send at least one attendee. |
tooMany | 400 | Too many at once. At most 50 attendees in one request; send more requests. |
registrationRefused | 400 | The registration was refused. Another reason the order was refused; reason says which, such as addOnSoldOut or namesLaterNotOffered. |
eventType | 400 | Not an event type. event is one of the webhook event types (GET /webhooks/event-types). |
webhookUrl | 400 | Not an address. url is an absolute https address without user name or fragment, at most 2,000 characters. |
webhookHttps | 400 | Not https. url must be https. |
webhookPrivate | 400 | Not a public address. url points at a private, loopback or link-local address, which AttendBeacon never calls. |
tooManyHooks | 400 | Too many subscriptions. A workspace has at most 200 automation subscriptions. Switch off flows or Zaps it no longer needs. |
tooManyEndpoints | 400 | Too many webhook endpoints. A workspace has at most 20 webhook endpoints. Remove one it no longer needs. |
webhooksUnavailable | 503 | Webhooks are not available here. This deployment keeps no signing secrets, so endpoints cannot be added or given a new secret. |
demoWorkspace | 403 | The demonstration is read-only. The demonstration workspace cannot be changed through the API. |
rateLimited | 429 | Too many requests. The key made more than its calls a minute. Retry-After says when to try again; RateLimit says what is left. |
serverError | 500 | Something went wrong here. An error on AttendBeacon's side. Retry with the same Idempotency-Key; traceId helps support find it. |
Fehler behandeln
const response = await fetch(url, { headers });
if (!response.ok) {
const problem = await response.json();
switch (problem.code) {
case "rateLimited":
await new Promise((resolve) => setTimeout(resolve, Number(response.headers.get("Retry-After")) * 1000));
break; // and try again
case "moduleOff":
console.warn(`Skipping: ${problem.module} is switched off for this event.`);
break;
default:
throw new Error(`${problem.code}: ${problem.detail} (trace ${problem.traceId})`);
}
}if (!response.IsSuccessStatusCode)
{
var problem = await response.Content.ReadFromJsonAsync<JsonElement>();
var code = problem.GetProperty("code").GetString();
if (code == "rateLimited")
{
await Task.Delay(response.Headers.RetryAfter?.Delta ?? TimeSpan.FromSeconds(30));
// and try again
}
else
{
throw new InvalidOperationException($"{code}: {problem.GetProperty("detail").GetString()} (trace {problem.GetProperty("traceId").GetString()})");
}
}if not response.ok:
problem = response.json()
if problem["code"] == "rateLimited":
time.sleep(int(response.headers.get("Retry-After", "30")))
# and try again
elif problem["code"] == "moduleOff":
print(f"Skipping: {problem['module']} is switched off for this event.")
else:
raise RuntimeError(f"{problem['code']}: {problem['detail']} (trace {problem['traceId']})")try {
$data = Invoke-RestMethod -Uri $url -Headers $headers
} catch {
$problem = $_.ErrorDetails.Message | ConvertFrom-Json
if ($problem.code -eq "rateLimited") { Start-Sleep -Seconds 30 } # and try again
else { throw "$($problem.code): $($problem.detail) (trace $($problem.traceId))" }
}