1. Reference
  2. Test sinks

A test sink is a receiver Greatwait runs for you, in a project’s test environment, that fails on demand. Give it a program — fail twice and then succeed, hold the connection until the sender gives up, answer 429 with a delay hint — point a destination at it, and watch what the sender concludes from each failure before your own receiver ever produces one.

No quickstart uses one. First value is a delivery to a receiver you own, in the live environment the dashboard opens. A sink exists only in the test environment, refuses a live credential, and never sends a delivery anywhere.

​
Reach the test environment

The dashboard does not link to the test environment. Its address works:

  1. Sign in and open your project. The address ends in /live, as in https://app.greatwait.dev/o/<organization>/p/<project>/live.
  2. Change live to test and open that address. The workspace’s System page reads Environment: test.
  3. Open /o/<organization>/p/<project>/test/settings/access, choose New key, and copy the secret it shows once. That credential acts in the test environment and nowhere else.

Keep it apart from the key the quickstarts export as GREATWAIT_API_KEY. Sink operations refuse a live credential, and a live credential is what those pages use.

​
Rehearse a failure

  1. Create a destination with endpoints.create. Its address has to pass the same public HTTPS check as any destination; step 3 replaces it. Give it a name when an active destination already delivers to that address, or the call answers state_conflict.
  2. Create a sink for that destination with testsinks.create and a program. The response carries the sink’s url.
  3. Point the destination at that url with endpoints.update.
  4. Create a one-shot against the destination with schedules.create.
  5. Read what the sink received with sinkdeliveries.list, and what the sender concluded with attempts.list.

A program that fails twice and then succeeds:

{
  "behavior": "server_error",
  "forDeliveries": 2,
  "then": "success"
}

forDeliveries is how many deliveries the behavior applies to, and then is what the sink does after them; then needs forDeliveries. status chooses the answer for client_error or server_error, delayMs sets how long delay waits, retryAfterSeconds sets the hint rate_limited sends, and completionDelayMs sets how long a deferring behavior waits before it reports.

​
Behaviors

BehaviorWhat the sink doesThe sender, at the default status
client_errorAnswers a selected 4xx. The sender records a customer refusal, and retries it only when the status is one the receiver may recover from — 401, 403 and 404, listed as clientErrorStatusesRetried. The default, 422, is not one of those, so it settles on the first attempt.stops: the refusal is final
defer_abandonAcknowledges the delivery and then never reports at all. The sender waits until the deadline in the envelope and records ambiguity, because a receiver that took the work and went quiet may well have done it. This is the case the completion deadline exists to bound.ambiguous: it may have run
defer_failAcknowledges the delivery, then reports failed with the credential in its signed envelope. The occurrence goes back on the ordinary retry ladder — the same place a 500 puts it — which is how a receiver says its job died rather than that it vanished.retries it
defer_succeedAcknowledges the delivery with 202 and the pending marker, keeps the work, then reports succeeded with the credential in its signed envelope. The whole deferred exchange, without writing a receiver.records success
delayWaits a bounded interval, then accepts. Exercises a slow receiver that still succeeds.records success
disconnectAuthenticates the delivery and then drops the connection without processing it, holding until the sender gives up. Nothing was claimed and nothing ran, but the sender cannot know that.ambiguous: it may have run
duplicateAccepts and reports the occurrence as already handled, without processing it again. What occurrence idempotency looks like from the sender’s side.records success
invalid_signatureRejects the delivery as unauthenticated regardless of whether the signature verified. Exercises the key-mismatch path without forging a signature. The sender retries on the receiver’s ordinary budget, because the usual cause is a credential the receiver is about to redeploy.retries it
rate_limitedAnswers 429 with a bounded Retry-After. The sender honours the hint and does not spend its give-up budget.retries it
server_errorAnswers a selected 5xx. The sender retries with backoff.retries it
successVerifies, records, and accepts.records success
timeoutVerifies and records the delivery, then never answers. The receiver acted and the sender cannot know it.ambiguous: it may have run

A request that fails verification is refused whatever the program says; invalid_signature is how to rehearse a key mismatch without forging anything.

​
Bounds

WhatBound
Sinks per project environment10
Longest delay10,000 ms
Longest a timeout or disconnect holds the request45,000 ms
Longest wait before a deferred report5,000 ms
Delivery receipts kept per sink, oldest evicted first50
Largest request body a sink reads69,632 bytes
Body bytes kept on a receipt4,096 bytes

​
Operations

OperationRequestScopes
testsinks.createPOST /v1/test-sinksendpoints:write
testsinks.listGET /v1/test-sinksendpoints:read
testsinks.readGET /v1/test-sinks/{sinkId}endpoints:read
testsinks.deleteDELETE /v1/test-sinks/{sinkId}endpoints:write
testsinks.configurePUT /v1/test-sinks/{sinkId}/programendpoints:write
sinkdeliveries.listGET /v1/test-sinks/{sinkId}/deliveriesendpoints:read
sinkdeliveries.readGET /v1/test-sinks/{sinkId}/deliveries/{deliveryRecordId}endpoints:read