Appearance
Respond to a Return
Answers a request that was returned to you. It does exactly what a person does when they answer a return in Johari: the request goes back to whoever returned it, with your answer.
Use it when a request you raised has status: "returned" and returnedTo: "creator". The callback that tells you it was returned carries both, and its note is the reason it was returned. See Returned.
Endpoint
| Method | URL |
|---|---|
POST | /api/requests/:requestID/respond-to-return |
| Path parameter | Description |
|---|---|
requestID | The request's requestID, from Create a Request or a callback |
Send the body as JSON with Content-Type: application/json, and sign the exact JSON text. The path you sign includes the request ID:
<timestamp>.POST./api/requests/6650f1a2b3c4d5e6f7a8b9e1/respond-to-return.<the JSON body>When you can use it
All three must be true:
- The request was raised with your API key. That includes child requests made from it.
- Its
statusis"returned". - It was returned to your key's user:
returnedTois"creator".
If it was returned to someone else (its approver or confirmer), you get 403. That person answers it in Johari, and you get the callbacks.
Body fields
| Field | Type | Required | Description |
|---|---|---|---|
idempotencyKey | string | Yes | Your unique ID for this response, 1 to 255 characters. A UUID is ideal. Use a new one for each new response, and reuse it only to retry the same response. See Idempotency |
note | string | Yes | Your answer, e.g. "The stamped invoice is now attached. The amount is correct.". Not empty, up to 2000 characters |
Any other field is ignored.
What happens
Exactly what happens when a person answers the return in Johari:
- The request goes back to the stage it was returned from:
pending(waiting for approval) if an approver returned it before approving it. The approver gets their usual WhatsApp message asking them to approve it.pending-paymentif the cashier returned it before paying it. The cashier gets their usual WhatsApp message.
- Your
noteis added to the request, shown as written by your key's user with(API)after the name, e.g.Neema Mollel (API). - You get a
request.status-changedcallback with the newstatusand your note asnote(if the request has acallbackURL). Get a Request shows the same.
Asked for a document?
Add it first with Add Files, then respond.
Response
data on success:
| Field | Type | Description |
|---|---|---|
requestID | string | The request's ID |
requestNumber | string | Its number in Johari, e.g. "1042" |
status | string | Where the request went back to: "pending" (an approver returned it, it is waiting for approval again) or "pending-payment" (the cashier returned it, it is waiting for payment again) |
Example
The body:
json
{
"idempotencyKey": "9f3b2a1c-4d5e-4f6a-8b7c-0d1e2f3a4b5c",
"note": "The stamped invoice is now attached. The amount is correct."
}bash
REQUEST_ID="6650f1a2b3c4d5e6f7a8b9e1"
BODY=$(cat <<'EOF'
{
"idempotencyKey": "9f3b2a1c-4d5e-4f6a-8b7c-0d1e2f3a4b5c",
"note": "The stamped invoice is now attached. The amount is correct."
}
EOF
)
TS=$(date +%s)
SIG=$(printf '%s' "$TS.POST./api/requests/$REQUEST_ID/respond-to-return.$BODY" \
| openssl dgst -sha256 -hmac "$SIGNING_SECRET" \
| sed 's/^.* //')
curl -X POST "$BASE_URL/api/requests/$REQUEST_ID/respond-to-return" \
-H "Content-Type: application/json" \
-H "x-api-key: $API_KEY" \
-H "x-timestamp: $TS" \
-H "x-signature: $SIG" \
--data-raw "$BODY"js
const crypto = require("crypto");
const requestID = "6650f1a2b3c4d5e6f7a8b9e1";
// callJohari is from the Signing page
const result = await callJohari("POST", `/api/requests/${requestID}/respond-to-return`, {
idempotencyKey: crypto.randomUUID(),
note: "The stamped invoice is now attached. The amount is correct.",
});
if (result.httpStatus === 200) {
console.log("Request", result.data.requestNumber, "is now", result.data.status);
} else {
console.error(result.httpStatus, result.message, result.data);
}python
import uuid
request_id = "6650f1a2b3c4d5e6f7a8b9e1"
# call_johari is from the Signing page
result = call_johari("POST", f"/api/requests/{request_id}/respond-to-return", {
"idempotencyKey": str(uuid.uuid4()),
"note": "The stamped invoice is now attached. The amount is correct.",
})
if result["httpStatus"] == 200:
print("Request", result["data"]["requestNumber"], "is now", result["data"]["status"])
else:
print(result["httpStatus"], result["message"], result["data"])Response 200:
json
{
"status": "success",
"data": {
"requestID": "6650f1a2b3c4d5e6f7a8b9e1",
"requestNumber": "1042",
"status": "pending-payment"
},
"message": "Response submitted successfully"
}Response 409, same idempotencyKey sent again after it worked:
json
{
"status": "error",
"data": {
"requestID": "6650f1a2b3c4d5e6f7a8b9e1",
"requestNumber": "1042",
"status": "pending-payment"
},
"message": "A request with this idempotencyKey has already been processed"
}Response 403, the request was returned to someone else:
json
{
"status": "error",
"data": "This request was returned to its confirmer (Amina Juma), so only they can respond to it",
"message": "This request was returned to its confirmer (Amina Juma), so only they can respond to it"
}Response 400, the request is not returned (or the return was already answered):
json
{
"status": "error",
"data": "This request is not in returned status",
"message": "This request is not in returned status"
}Response 404, wrong ID, or the request was not raised with your key:
json
{
"status": "error",
"data": "Request not found",
"message": "Request not found"
}The usual 401 errors apply too. Every possible error is listed on the Errors page.
Common mistakes
Responding to a request returned to someone else
Only answer when returnedTo is "creator". When it is "approver" or "confirmer", you get 403: that person answers it in Johari.
Checking returnedTo without status
returnedTo keeps its last value after the request moves on. Only status: "returned" means the request is waiting for an answer now.
A new idempotencyKey on every retry
Retries must reuse the key. If your first call worked but the answer was lost, a retry with a new key gets 400 (This request is not in returned status) instead of the 409 that tells you it worked. If the cashier returned the request again in the meantime, it would even answer the new return with your old note.
Reusing the key of an earlier response
A request can be returned more than once. Answer each return with a new key. An earlier key gets the 409 for the earlier response (same note) or 400 (a different note), and nothing is sent to the cashier.