# Explaining Markets Competition > A live, out-of-sample benchmark and open quarterly competition measuring how well AI systems explain stock returns around earnings announcements. Participating systems receive earnings events on a signed webhook as they happen and submit predictions using any information available before the announcement plus the earnings-call transcript; predictions are scored against realized returns on a live leaderboard. Introduced in the working paper by Koijen and Levy, where the best-optimized agentic systems raise the explained variation in returns (R²) from ~8% to ~20%. You build a "submission" that (1) receives HMAC-signed webhook deliveries when events fire and (2) POSTs predictions to the REST API. Accounts, submissions, credentials, and teams are managed in the web portal; your code only needs the webhook handler and the predictions call. Authenticate API calls with your submission's key in the `X-API-Key` header. API base URL: https://api.explainingmarkets.ai/v1 This file concatenates the roadmap, the full participant documentation, and a compact listing of the API endpoints. The machine-readable contract is at /openapi.json. For the slim index see /llms.txt. --- ## Quickstart ### Overview The competition lets your system receive information-release events over a signed webhook and submit predictions about how the market will react. You set everything up in the portal; your code only needs to receive webhooks and call the predictions endpoint. The [API reference](/docs/api) documents those programmatic endpoints. ### API base URL Base your requests at `https://api.explainingmarkets.ai/v1`. ### Users, submissions, and teams Your account is a **user**; each competition entry is a **submission**. One person can own and join multiple submissions, and each submission has its own webhook URL, API key, and signing secret. Teams have role-based access — **admin** (full control, including managing members and the submission lifecycle), **editor** (edit settings and rotate credentials), and **reader** (view-only). You manage roles and the submission lifecycle in the portal. ### 1. Sign up and complete your profile Sign up in the portal and complete your profile. That activates your account and unlocks creating and joining submissions. ### 2. Create a submission Create a submission in the portal and give it a public name — you become its admin. It stays in `draft` until both credentials and a webhook URL are set, then becomes `active` and starts receiving events. ### 3. Get your credentials On the submission's **Credentials** tab, generate your API key and signing secret. They are shown **once** — store them somewhere safe; rotation (also in the portal) is the recovery path. The API key authenticates your prediction requests; the signing secret verifies incoming webhooks. ### 4. Set your webhook URL On the submission's **Webhook** tab, set the HTTPS URL where you want to receive event deliveries. Once credentials and a webhook URL are both set, the submission becomes active. See [webhook signing](/docs/webhooks) for verifying deliveries. ### 5. Smoke-test end to end Use the **Test Webhook** button on the submission to send a synthetic delivery to your URL within a few seconds; your handler verifies it (the starter repos do this out of the box). The submission's **Health** tab shows rolling delivery and prediction counters so you can confirm the round trip. ### 6. Receive events and submit predictions This is the part your code handles. When an event fires, a delivery arrives at your webhook URL; read the `prediction_deadline` from the payload (default: webhook fire time + 5 minutes). The deadline is **per-submission** and starts when your handler ACKs the webhook with 200, so slow delivery never shrinks your window. Then submit your prediction with the submission's API key: ```bash curl -X POST "https://api.explainingmarkets.ai/v1/predictions" \ -H "X-API-Key: $KEY" \ -H "Content-Type: application/json" \ -d '{ "event_id": "", "predictions": [ {"identifier_value": "AAPL", "predicted_percentile": 0.92} ] }' ``` Predictions are **never rejected for timing** — late, early, and duplicate POSTs all return `201` and are tagged for scoring — but only your **first valid prediction for an event counts**. Rejections mean something is structurally wrong: a disabled submission (`403 SUBMISSION_DISABLED`), an auto-disabled webhook (`403 WEBHOOK_NOT_REGISTERED`, until you re-register in the dashboard), or a closed event (`409 EVENT_CLOSED`). You can also poll the upcoming events calendar — see the [API reference](/docs/api). #### What information may your agent use? Every event on the calendar (`GET /v1/events`) carries a `knowledge_cutoff`: your agent must not use any information from after that instant. The value is an ISO 8601 date-time in UTC (e.g. `2026-01-13T21:00:00Z`). Your agent may use any data source, model, or tool subject to that cutoff. Note that the event materials delivered to your webhook will include a summary of the earnings call — which of course is after the cutoff — as well as an [earnings preview](/blog/earnings-previews), which we prepare prior to the knowledge cutoff, and, when the stock has liquid listed options, three option-implied statistics measured before it (the implied earnings volatility, the implied absolute move, and the 25-delta skew). The materials arrive as a list of items: pick each one by its `id`, never by position, and note that the option statistics are a JSON object while the other two are text. The [API reference](/docs/api) describes every item. See the [official rules](/contest-rules) for the binding statement of this requirement, or the [FAQ](/faq) for a shorter answer. ### 7. Manage your team Invite teammates, change roles, and remove members from the portal. Invite codes are single-use, a submission tops out at 10 members, and a submission always keeps at least one admin. ### Need help? Questions, or something not working? Email [contact@explainingmarkets.ai](mailto:contact@explainingmarkets.ai). --- ## Webhook signing Every webhook delivery is signed with HMAC-SHA256 in the [Standard Webhooks](https://github.com/standard-webhooks/standard-webhooks) style. You don't have to implement verification yourself — clone a starter repo with a vendored verifier and a working handler for [Modal](https://github.com/explaining-markets/starter-modal) or [Railway](https://github.com/explaining-markets/starter-railway). ### Quick start (FastAPI) ```python import os from fastapi import FastAPI, Request, Response # verify_webhook ships vendored in each starter repo (explaining_markets/), # so there's nothing to install — clone a starter and it's already there. from explaining_markets import verify_webhook, WebhookVerificationError app = FastAPI() SECRET = os.environ["EM_WEBHOOK_SECRET"] # whsec_... @app.post("/competition/webhook") async def hook(request: Request) -> Response: raw_body = await request.body() # raw bytes — DO NOT use request.json() try: event = verify_webhook( raw_body=raw_body, headers=request.headers, secret=SECRET, ) except WebhookVerificationError: return Response(status_code=401) # event is the parsed JSON. Use event["id"] as your idempotency key. process(event) return Response(status_code=200) ``` ### Headers you receive | Header | Description | | --- | --- | | `Webhook-Id` | Stable per logical event across retries. Use as your idempotency key. | | `Webhook-Timestamp` | Unix seconds, refreshed on each delivery attempt. | | `Webhook-Signature` | One or more space-delimited `v1,` signatures. Multiple appear during signing-secret rotation — accept the delivery if **any** signature verifies. | ### Common mistakes 1. **Re-serializing the body before verification.** The signature covers the exact bytes we sent. `json.dumps(json.loads(body))` reorders keys and adds spaces; verification fails. 2. **Using `request.json()` instead of `request.body()`.** Same issue — the parsed dict is no longer the original byte string. 3. **Ignoring the timestamp.** The verifier defaults to a 5-minute tolerance; set `tolerance_seconds=` if your clocks drift. 4. **Not deduping on `Webhook-Id`.** We retry on 5xx and timeout. Dedupe in your app or expect to process the same event more than once. ### Test vectors Frozen test vectors let you confirm your verifier is wired up correctly without waiting for a real event delivery — both our server-side signer and the vendored verifier pin to these values. They cover a single-signature delivery and a rotation-overlap delivery (two space-delimited signatures, accept if either verifies). Fetch them at [`/test_vectors.json`](/test_vectors.json), or find them in each starter repo at `tests/test_vectors.json`. --- ## Official rules **Last updated:** September 29, 2026 **NO PURCHASE OR PAYMENT NECESSARY TO ENTER OR WIN. A PURCHASE WILL NOT IMPROVE YOUR SCORE OR LIKELIHOOD OF WINNING. VOID WHERE PROHIBITED.** --- ### 1. Sponsor and Competition The Explaining Markets Q4 2026 competition (the "Competition") is sponsored and administered by The University of Chicago, an Illinois not-for-profit corporation, located at 5801 South Ellis Avenue, Chicago, Illinois 60637 (the "University" or "Sponsor"). Optiver Services US LLC, located at 130 East Randolph Street, Suite 800, Chicago, Illinois 60601 (“Optiver”) is the Competition partner and provides the funding for the prizes. The University administers the Competition, determines scores and eligibility, verifies winners, and pays the prizes. The University personnel and designees responsible for administering the Competition are referred to collectively as the “Competition Organizers.” Optiver does not accept participant funds and does not determine the winners. The Competition is a free, skill-based research and engineering contest. Participants develop agents to predict the relative stock-market reaction to earnings announcements using only permitted information. These methods may include traditional statistical or machine-learning models, language models or other artificial-intelligence systems, or combinations of these approaches. Competition inputs are derived from publicly available sources. No real money is invested, wagered, pooled, or traded through the Competition, and no prize is based on a random drawing or on the result of a single earnings announcement. --- ### 2. Eligibility Participation is open, subject to applicable law and platform availability, to anyone globally. However, **prize eligibility** is open, subject to applicable law and platform availability, only to natural persons who are legal residents of the United States (the fifty (50) states and the District of Columbia) and at least eighteen (18) years old and have reached the age of majority where they live. Teams are permitted, but every team member must satisfy the eligibility requirements. Eligibility is subject to applicable law, these Official Rules, sanctions restrictions, and the participant’s ability to provide the identity, residency, tax, and payment documentation reasonably required by the University. Void where prohibited. The following are not eligible for prizes: * **(a)** persons who design, administer, score, audit, or have nonpublic access to the Competition; * **(b)** employees of the University or Optiver; * **(c)** immediate family or household members of the foregoing; * **(d)** persons who are subject to applicable U.S. sanctions or export restrictions; and * **(e)** persons whose participation or receipt of a prize would violate law, an applicable employer or University policy, a fiduciary or confidentiality duty, or another binding obligation. The Competition is void where prohibited. --- ### 3. How to Enter; Accounts and Teams To enter, create a free Explaining Markets account, complete the required profile, create or join a submission, and connect the submission to the Competition platform as described in the technical documentation. No payment to the University or Optiver is required. The University will make available a functional no-cost method of participating. Participants may voluntarily use third-party models, computing, software, or data at their own expense, but no such expenditure is required or improves eligibility for a prize. Each person may maintain only one user account and may not share or transfer an account. A person may develop or join multiple submissions for research and leaderboard purposes, up to a maximum of five submissions. Each submission may have up to ten (10) registered team members. The prize roster is the roster recorded at the Registration Deadline. To be eligible for a prize, a submission must furnish a model card through the Explaining Markets portal or dashboard. The model card is attached to the submission via the Explaining Markets [portal](https://explainingmarkets.ai/submissions). The model card must provide a meaningful high-level description of the methods used to generate the submission’s predictions. At a minimum, it must indicate whether the submission uses: * traditional statistical or machine-learning models, such as regression, boosting, or neural networks; * language models or other generative-artificial-intelligence systems; * a hybrid or ensemble of multiple approaches; or * another approach, which must be described at a comparable level of detail. The model card need not disclose source code, model weights, proprietary prompts, detailed feature definitions, hyperparameters, trade secrets, or other confidential intellectual property. Participants retain ownership of their models, methods, code, prompts, and other intellectual property. The model card must be materially accurate. If the methods used by a submission materially change during the Competition, participants must update the submission's model card so that the public description remains materially accurate. A submission that does not furnish a compliant model card may participate in the Competition and appear on the leaderboard, but it is not eligible for a prize. The Competition Organizers will determine whether a model card satisfies this Rule. Additionally, submissions may be subject to an independent audit and/or an audit using AI which does not reveal proprietary details, yet confirms a submission's adherence to the competition rules. --- ### 4. Competition Period and Predictions Registration closes at 11:59 p.m. Central Time on October 11, 2026 (the “Registration Deadline”). The Scoring Period covers eligible earnings events designated by the University from October 12 through December 15, 2026. For each event, the Competition API identifies a `knowledge_cutoff` and a prediction deadline. The `knowledge_cutoff` is the controlling cutoff for determining what information a submission may use to generate its prediction for that event. A valid prediction is a number from 0 through 1 representing the submission’s predicted percentile of the stock’s market reaction for that event. The first valid prediction received before the applicable prediction deadline is the one that will be used for scoring. An API response accepting a prediction does not by itself establish that the prediction was timely, valid, compliant with the `knowledge_cutoff`, or otherwise eligible for scoring. A submission must not use, directly or indirectly, any information that became available after the event-specific `knowledge_cutoff`, except for information provided for that event through the official Competition APIs. Information provided through the official Competition APIs, such as an earnings-call summary, may be used even when provided after the `knowledge_cutoff`. This restriction applies to every part of the prediction process, including data collection, model inputs, features, prompts, retrieval results, external searches, manual research, human adjustments, model selection, and prediction revisions. In particular, post-announcement market data—including prices, quotes, returns, volume, order-book data, options data, or other market-derived signals observed after the `knowledge_cutoff`—may not be used unless that information is expressly provided through the official Competition APIs. Nonpublic, embargoed, confidential, hacked, misappropriated, or unlawfully obtained information is prohibited regardless of when it is obtained. A submission that violates this Rule is not eligible for a prize. Competition organizers may also publicly flag the submission as violating these Rules, remove it from the leaderboard, or both, at any time. --- ### 5. Scoring and Winner Selection This is a skill-based Competition. Winners are determined by objective aggregate performance across the quarter's common set of valid scored earnings events (the "Scored Events"), expected to include hundreds of earnings announcements, not by chance. The exact scoring methodology is publicly available at [https://github.com/explaining-markets/examples/blob/501bd31/src/examples/scoring.py](https://github.com/explaining-markets/examples/blob/501bd31/src/examples/scoring.py). The scoring methodology and the frozen code version identified above are incorporated into these Rules and control the technical calculation. All submissions will be evaluated on the same final set of Scored Events. Events with unavailable, unreliable, corrected, or otherwise invalid data may be excluded for every submission. For each submission, competition organizers will first calculate the arithmetic mean of that submission’s timely, valid predictions for the Scored Events. This mean will be calculated before any missing predictions are imputed. For each Scored Event for which the submission did not provide a timely, valid prediction, the missing prediction will be imputed using this submission-specific mean. A late, malformed, nonnumeric, or out-of-range prediction will be treated as a missing prediction for purposes of this Rule. An exact tie is resolved first by higher timely-prediction coverage before imputation. If a tie remains, the prizes for the tied positions are combined and divided equally among the tied eligible submissions. No random tie-breaker will be used. If a submission did not provide a timely, valid prediction for any Scored Event, its submission-specific mean will be undefined. In that circumstance, the submission will not be eligible for prizes. All decisions concerning the Scored Events, prediction validity, imputation, scoring, rankings, tie-breaking, eligibility, compliance, and winner selection are made at the discretion of the Competition Organizers and are final and binding to the fullest extent permitted by law. --- ### 6. Prizes The total prize amount is $7,500 in U.S. dollars. The prizes are fixed in advance, funded by Optiver, paid by the University, and do not depend on the number of participants, participant spending, or any participant-funded pool. | Placement | Prize | | :--- | :--- | | **1st Place** | $2,500 | | **2nd Place** | $2,000 | | **3rd Place** | $1,500 | | **4th Place** | $1,000 | | **5th Place** | $500 | Each listed prize is awarded to the applicable submission, not to each team member. A person may receive no more than one prize. If a person is a registered team member on more than one submission that would otherwise place, only that person's highest-placing submission is awarded a prize; each lower-placing submission is passed over, and the affected prize is awarded to the next highest-ranked eligible submission. Unless the University approves a different written allocation submitted before the Registration Deadline, a team prize will be divided equally among its verified, prize-eligible team members. Prizes may not be transferred to an ineligible person or proxy. The University may use a reasonable payment method and may withhold amounts required by law. --- ### 7. Winner Verification; Taxes Leaderboard results are preliminary until eligibility and compliance are verified. Potential winners will be notified using the email address associated with their accounts and must respond within ten (10) calendar days, or within any longer period stated in the notice. The University may require proof of identity, age, residence, team membership, eligibility, tax status, and payment information, together with an affidavit of eligibility and a liability or publicity release where lawful. The University may also require information reasonably necessary to verify the accuracy of a submission’s model card and its compliance with the `knowledge_cutoff` requirements, including relevant logs, timestamps, data-source descriptions, API records, retrieval records, prompts, or other technical records. Additionally, submissions may be subject to an independent audit and/or an audit using AI which does not reveal proprietary details, yet confirms a submission's adherence to the competition rules. A potential winner who does not timely provide the requested information, cannot legally receive payment, fails to furnish a compliant model card, violates the `knowledge_cutoff` requirements, or is otherwise found ineligible or noncompliant forfeits the prize. The forfeited prize may be awarded to the next highest-ranked eligible submission. Winners are solely responsible for taxes, fees, and reporting obligations. The University may require IRS Form W-9 or other applicable documentation and will issue tax reporting forms as required by law. A list of winners will be made available on the Competition [leaderboard](https://explainingmarkets.ai/leaderboard) following the end of the Scoring Period and after verification of the winners is complete. --- ### 8. Public Leaderboard; Model Cards; Participant Content Submission names, display names, model cards, predictions, explanations designated for display, scores, ranks, performance metrics, and Competition-compliance notices may appear publicly on the Competition website, portal, dashboard, or leaderboard and may be indexed, shared, cached, archived, or redistributed by third parties. The University may identify verified winners by name, organization, placement, and prize amount where permitted by law. The University may publicly identify a submission as under review, ineligible for a prize, in violation of these Rules, disqualified, or removed from the leaderboard. The University may also state the general basis for that status, including a determination that the submission used information from after an applicable `knowledge_cutoff`. Participants retain ownership of their agents, models, methods, prompts, source code, model weights, and other preexisting or independently developed technology. Furnishing a model card does not transfer ownership of that technology to the University or Optiver and does not require a participant to disclose source code, model weights, proprietary prompts, detailed feature definitions, hyperparameters, trade secrets, or other confidential intellectual property. By submitting predictions, a model card, explanations, or other content, each participant grants the University a nonexclusive, royalty-free, worldwide license to host, reproduce, execute where applicable, evaluate, audit, display, publish, archive, and use that submitted content and the resulting performance and compliance data to operate the Competition and to conduct and publish Competition-related research. This license permits the University to display the model card publicly with the submission. Private source code, model weights, prompts, and other private technical materials are not licensed unless separately submitted to the University. Each participant represents that the participant has the rights needed to make the submission and that the participant’s model card and other disclosures are materially accurate and not misleading. --- ### 9. Privacy and Optiver Recruiting The University will collect and process registration, profile, technical, submission, and prize-administration information. By entering, each participant agrees that the University may share the participant's name, email address, role, and organization with Optiver, and that Optiver may use that information to contact the participant about recruiting or employment opportunities. Optiver will process information it receives under its applicable privacy policy. Participants outside the United States understand that personal information may be transferred to and processed in the United States and other countries described in the applicable privacy notices. Public leaderboard information, including public model cards and public Competition-compliance notices, is separate from the nonpublic profile and verification information described above. --- ### 10. Integrity; Prohibited Conduct Participants must act honestly and comply with these Rules and the technical documentation. Prohibited conduct includes: * Using multiple or false identities * Account sharing * Collusion intended to distort rankings * Using, directly or indirectly, information that became available after an event’s `knowledge_cutoff`, except for information provided for that event through the official Competition APIs * Furnishing a materially false, incomplete, or misleading model card, or failing to update a model card after a material change in the submission’s methods * Using material nonpublic or misappropriated information * Manipulating or attempting to manipulate a security or market outcome * Tampering with, overloading, reverse engineering, or exploiting the platform, API, scoring system, or another submission * Bypassing rate limits or security controls * Infringing third-party rights * Interfering with other participants The University may investigate suspected noncompliance; require reasonable logs, records, explanations, or other evidence; audit a submission; correct or recalculate scores; remove content; suspend accounts; publicly flag a submission as violating these Rules; remove a submission from the leaderboard; disqualify a participant or submission; or withhold or recover a prize when the Competition Organizers determine that these Rules were violated or that the integrity of the Competition was compromised. A submission determined to have violated the `knowledge_cutoff` requirements is not eligible for a prize. The University may publicly flag or remove such a submission at any time, including during the Scoring Period, after preliminary results are published, during winner verification, or after final results are announced. Acceptance of a prediction by the API, prior appearance on the leaderboard, or prior publication of a score or rank does not prevent the University from later investigating the submission, revising its status, correcting its score, removing it from the leaderboard, disqualifying it, or recovering a prize. All decisions concerning investigations, compliance, remedies, eligibility, scoring, and winner selection are made at the discretion of the Competition Organizers and are final and binding to the fullest extent permitted by law. --- ### 11. Technical Problems; Modification or Cancellation The University may correct clerical, data, or scoring errors; update preliminary rankings; exclude an affected event for all submissions; or modify, suspend, extend, or cancel the Competition when reasonably necessary because of fraud, abuse, security risks, platform or data failures, force majeure, insufficient valid Scored Events, or legal requirements. The University will provide notice of material changes when practicable and will seek to preserve the announced skill-based scoring method and fixed prize amounts. If the Competition cannot be completed as planned, the University may award prizes based on eligible performance through a fair announced cutoff if a sufficient common sample remains. If no fair skill-based determination is possible, the University may cancel the Competition without selecting winners. Winners will not be selected by random drawing. --- ### 12. Financial and Service Disclaimers; Release The Competition is a research simulation. It does not execute securities transactions, accept investment capital, provide personalized investment advice, or constitute an offer, solicitation, recommendation, or endorsement to buy or sell any security or financial instrument. Participants and third parties act on Competition information at their own risk. **THE PLATFORM, API, EVENT MATERIALS, MARKET DATA, SCORING OUTPUTS, AND LEADERBOARD ARE PROVIDED "AS IS" AND "AS AVAILABLE." TO THE FULLEST EXTENT PERMITTED BY LAW, THE UNIVERSITY, OPTIVER, AND THEIR AFFILIATES, TRUSTEES, DIRECTORS, OFFICERS, EMPLOYEES, CONTRACTORS, AGENTS, DATA PROVIDERS, AND SERVICE PROVIDERS (THE "RELEASED PARTIES") DISCLAIM WARRANTIES OF ACCURACY, COMPLETENESS, TIMELINESS, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, SECURITY, AND UNINTERRUPTED OR ERROR-FREE OPERATION.** To the fullest extent permitted by law, each participant releases the Released Parties from claims arising from participation, administration of the Competition, technical or data failures, or acceptance or use of a prize, except for liability that cannot lawfully be released. The Released Parties will not be liable for indirect, incidental, special, consequential, exemplary, or punitive damages, lost profits, lost data, trading losses, or loss of opportunity. Each participant will indemnify the Released Parties against third-party claims arising from that participant's unlawful conduct, infringement of third-party rights, material breach of these Rules, or false eligibility representations. Some jurisdictions do not permit certain exclusions or limitations, so parts of this Section may not apply. --- ### 13. Governing Law; General Terms These Rules and disputes arising from the Competition are governed by the laws of the State of Illinois, without regard to conflict-of-laws principles, except to the extent mandatory law in a participant's jurisdiction provides otherwise. Any action arising from the Competition must be brought exclusively in a state or federal court located in Cook County, Illinois, and each participant consents to the jurisdiction and venue of those courts. The Competition Organizers have final authority to interpret and apply these Rules, administer the Competition, resolve ambiguities or disputes, and make all decisions concerning the Competition. This authority includes decisions concerning event inclusion or exclusion, prediction validity and timeliness, imputation, scoring, rankings, model-card compliance, `knowledge_cutoff` compliance, investigations, public compliance notices, eligibility, disqualification, prize forfeiture or recovery, modification or cancellation of the Competition, and winner selection. All such decisions are made at the discretion of the Competition Organizers and are final and binding to the fullest extent permitted by law. If a provision is unenforceable, it will be enforced to the maximum extent permitted and the remaining provisions will remain effective. A failure to enforce a provision is not a waiver. These Rules and the incorporated scoring methodology are the complete Competition terms and control over inconsistent FAQs, marketing statements, or other descriptions. The English-language version controls to the extent permitted by law. --- ## Webhook test vectors Frozen known-answer HMAC signatures to self-test your verifier offline — a single-signature and a rotation-overlap case. Also served at /test_vectors.json. ```json { "_comment": "Frozen test vectors for the webhook signing algorithm. Pinned by app/services/webhook_signer.py tests AND by the participant verifier package (packages/competition_webhooks/tests). Changing any value here is a breaking change for downstream verifier consumers. Single-signature vectors carry a scalar 'secret'; rotation-overlap vectors carry a 'secrets' list (current secret first) and an 'expected_signature_header' with one space-delimited 'v1,...' signature per secret.", "vectors": [ { "name": "minimal payload, single signature", "secret": "whsec_dGVzdC1zZWNyZXQtMzItYnl0ZXMtZm9yLXRlc3R2ZWN0", "webhook_id": "evt_01HX7M9TESTVECTORID", "timestamp": 1714850123, "raw_body": "{\"id\":\"evt_01HX7M9TESTVECTORID\",\"event_id\":\"e1\"}", "expected_signature_header": "v1,vIYng2J6M2XsRpNnxCKxc178O2qAxCx9m/umiJLOtho=" }, { "name": "rotation overlap, two signatures (current secret first)", "secrets": [ "whsec_cm90YXRpb24tY3VycmVudC1zZWNyZXQtMzItYnl0ZXM", "whsec_cm90YXRpb24tcHJldmlvdXMtc2VjcmV0LTMyYnl0ZSE" ], "webhook_id": "evt_01HX7M9ROTATIONVECTOR", "timestamp": 1714850123, "raw_body": "{\"id\":\"evt_01HX7M9ROTATIONVECTOR\",\"event_id\":\"e2\"}", "expected_signature_header": "v1,wCGWQpJklrBow2HfEQIXZl9MLbBpV6eKhAXZ03OoqTA= v1,8axRlr9R2kFkemPuZjd2iV0YcCpw+qqUy30rV18iR3I=" } ] } ``` --- ## API Base URL: https://api.explainingmarkets.ai/v1 ### GET /events Get the events calendar Returns calendar entries within an optional `[start_date, end_date]` window. Forward-looking scheduled events and realized events both appear. Scheduled entries are refreshed periodically; a missing entry between successive calls indicates the upstream source has dropped the event. Parameters: - `start_date` [query] - `end_date` [query] Responses: 200 Calendar. ### POST /predictions Submit Predictions Submit a prediction for a specific event. The API accepts all valid predictions regardless of timing. However, only a submission's **first valid prediction for an event counts towards the score**. Predictions are only rejected when something is structurally wrong (see 4XX error codes below). Request body (`PredictionSubmission`) — required. Responses: 201 Prediction accepted (see `status` for the timing tag).; 400 Malformed JSON or identifier not in event focal_assets.; 401 Missing or invalid API key.; 403 Submission disabled / deleted, or unknown api key. In the event that your webhook is repeatedly failing, it will be automatically disabled and you will be notified that this has occurred. Until the webhook is registered again in the competition dashboard, this route will return `403 WEBHOOK_NOT_REGISTERED` responses.; 404 Unknown event_id.; 409 Event is closed or scored; the prediction window has permanently closed (`EVENT_CLOSED`). No further predictions accepted. ### GET /archive Historical archive manifest Returns the discovery manifest for the per-quarter historical archive, with a short-lived CloudFront-signed download `url` attached to every file. Download the gzip-JSONL files directly from those URLs (cached at the CDN edge). Requires the same `X-API-Key` as `/predictions`. Responses: 200 Archive catalog with signed download URLs.; 401 Missing or invalid API key. ### GET /archive/{event_type}/{quarter} Signed URL for one archive file Returns a fresh CloudFront-signed download URL for a single `(event_type, quarter)` archive file — e.g. to refresh an expired URL without re-fetching the whole manifest. Parameters: - `event_type` [path] (required) - `quarter` [path] (required) Responses: 200 Signed download URL for the requested quarter file.; 400 Malformed event_type or quarter.; 401 Missing or invalid API key. ### GET /health Your submission's health counters Rolling 24-hour counters for your submission — outbound webhook deliveries (us → your endpoint) and inbound prediction submissions (your system → us). Useful for monitoring or alerting on delivery failures. Authenticate with your submission's API key (the same key you use for `/predictions`); it returns the health of whichever submission the key belongs to. The portal shows these same counters on your submission's Health tab. Responses: 200 Health counters.; 401 Missing or invalid API key. ### POST /webhook/test Send a test event to your webhook URL Sends a synthetic test event to your submission's registered webhook URL so you can verify your handler end to end before any real event fires. It takes the same delivery path as a real broadcast; the payload is tagged with `event_type=TEST`. Authenticate with your submission's API key. You can also trigger a test from the portal — the **Send test** button on your submission's Webhook tab does exactly the same thing. Responses: 202 Test delivery enqueued.; 401 Missing or invalid API key.; 404 Submission not found.; 409 No webhook URL registered, or credentials not initialized. ### Outbound webhook (delivered to your URL) - **event_broadcast** (POST) — Event Trigger Broadcast Payload sent to the Submission's registered callback URL when an